001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.marshall.internal; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020 021import java.util.*; 022 023import org.apache.juneau.commons.bean.*; 024import org.apache.juneau.marshall.*; 025import org.apache.juneau.marshall.collections.*; 026 027/** 028 * Represents a wrapped {@link Map} where entries in the map can be removed without affecting the underlying map. 029 * 030 * 031 * @param <T> The class type of the wrapped bean. 032 * @serial exclude 033 */ 034@SuppressWarnings({ 035 "java:S110", // Inheritance depth inherited from JsonMap -> MarshalledMap -> LinkedHashMap chain; intentional 036 "rawtypes" // Raw types necessary for generic Map delegation 037}) 038public class DelegateMap<T extends Map> extends JsonMap implements Delegate<T> { 039 private static final long serialVersionUID = 1L; 040 041 private final transient ClassMeta<T> classMeta; 042 043 /** 044 * Constructor. 045 * 046 * @param m The metadata object that created this delegate object. 047 * @param session The current bean session. 048 */ 049 @SuppressWarnings({ 050 "javabugs:S2259", // The map must not be null, per the constructor contract. 051 "unchecked" // Type erasure requires cast for Map operations 052 }) 053 public DelegateMap(T m, MarshallingSession session) { 054 this.classMeta = session.getClassMetaForObject(m); 055 m.forEach((k, v) -> put(s(k), v)); 056 } 057 058 /** 059 * Remove all but the specified keys from this map. 060 * 061 * <p> 062 * This does not affect the underlying map. 063 * 064 * @param keys The remaining keys in the map (in the specified order). 065 * @return This object. 066 */ 067 public DelegateMap<T> filterKeys(List<String> keys) { 068 var m = new JsonMap(); 069 keys.forEach(k -> { 070 if (containsKey(k)) 071 m.put(k, get(k)); 072 }); 073 this.clear(); 074 this.putAll(m); 075 return this; 076 } 077 078 @Override 079 public boolean equals(Object o) { 080 return o instanceof Map<?,?> o2 && eq(this, o2, (x, y) -> x.entrySet().equals(y.entrySet())); 081 } 082 083 @Override 084 public int hashCode() { 085 return entrySet().hashCode(); 086 } 087 088 @Override /* Overridden from Delegate */ 089 public ClassMeta<T> getBeanInfo() { return classMeta; } 090}