001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.core; 018 019import java.io.Serializable; 020import java.util.LinkedHashMap; 021import java.util.Map; 022 023import org.springframework.lang.Nullable; 024import org.springframework.util.Assert; 025import org.springframework.util.StringUtils; 026 027/** 028 * Support class for {@link AttributeAccessor AttributeAccessors}, providing 029 * a base implementation of all methods. To be extended by subclasses. 030 * 031 * <p>{@link Serializable} if subclasses and all attribute values are {@link Serializable}. 032 * 033 * @author Rob Harrop 034 * @author Juergen Hoeller 035 * @since 2.0 036 */ 037@SuppressWarnings("serial") 038public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable { 039 040 /** Map with String keys and Object values. */ 041 private final Map<String, Object> attributes = new LinkedHashMap<>(); 042 043 044 @Override 045 public void setAttribute(String name, @Nullable Object value) { 046 Assert.notNull(name, "Name must not be null"); 047 if (value != null) { 048 this.attributes.put(name, value); 049 } 050 else { 051 removeAttribute(name); 052 } 053 } 054 055 @Override 056 @Nullable 057 public Object getAttribute(String name) { 058 Assert.notNull(name, "Name must not be null"); 059 return this.attributes.get(name); 060 } 061 062 @Override 063 @Nullable 064 public Object removeAttribute(String name) { 065 Assert.notNull(name, "Name must not be null"); 066 return this.attributes.remove(name); 067 } 068 069 @Override 070 public boolean hasAttribute(String name) { 071 Assert.notNull(name, "Name must not be null"); 072 return this.attributes.containsKey(name); 073 } 074 075 @Override 076 public String[] attributeNames() { 077 return StringUtils.toStringArray(this.attributes.keySet()); 078 } 079 080 081 /** 082 * Copy the attributes from the supplied AttributeAccessor to this accessor. 083 * @param source the AttributeAccessor to copy from 084 */ 085 protected void copyAttributesFrom(AttributeAccessor source) { 086 Assert.notNull(source, "Source must not be null"); 087 String[] attributeNames = source.attributeNames(); 088 for (String attributeName : attributeNames) { 089 setAttribute(attributeName, source.getAttribute(attributeName)); 090 } 091 } 092 093 094 @Override 095 public boolean equals(@Nullable Object other) { 096 return (this == other || (other instanceof AttributeAccessorSupport && 097 this.attributes.equals(((AttributeAccessorSupport) other).attributes))); 098 } 099 100 @Override 101 public int hashCode() { 102 return this.attributes.hashCode(); 103 } 104 105}