001/* 002 * Copyright 2002-2013 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.ui; 018 019import java.util.Collection; 020import java.util.LinkedHashMap; 021import java.util.Map; 022 023import org.springframework.core.Conventions; 024import org.springframework.util.Assert; 025 026/** 027 * Implementation of {@link java.util.Map} for use when building model data for use 028 * with UI tools. Supports chained calls and generation of model attribute names. 029 * 030 * <p>This class serves as generic model holder for both Servlet and Portlet MVC, 031 * but is not tied to either of those. Check out the {@link Model} interface for 032 * a Java-5-based interface variant that serves the same purpose. 033 * 034 * @author Rob Harrop 035 * @author Juergen Hoeller 036 * @since 2.0 037 * @see Conventions#getVariableName 038 * @see org.springframework.web.servlet.ModelAndView 039 * @see org.springframework.web.portlet.ModelAndView 040 */ 041@SuppressWarnings("serial") 042public class ModelMap extends LinkedHashMap<String, Object> { 043 044 /** 045 * Construct a new, empty {@code ModelMap}. 046 */ 047 public ModelMap() { 048 } 049 050 /** 051 * Construct a new {@code ModelMap} containing the supplied attribute 052 * under the supplied name. 053 * @see #addAttribute(String, Object) 054 */ 055 public ModelMap(String attributeName, Object attributeValue) { 056 addAttribute(attributeName, attributeValue); 057 } 058 059 /** 060 * Construct a new {@code ModelMap} containing the supplied attribute. 061 * Uses attribute name generation to generate the key for the supplied model 062 * object. 063 * @see #addAttribute(Object) 064 */ 065 public ModelMap(Object attributeValue) { 066 addAttribute(attributeValue); 067 } 068 069 070 /** 071 * Add the supplied attribute under the supplied name. 072 * @param attributeName the name of the model attribute (never {@code null}) 073 * @param attributeValue the model attribute value (can be {@code null}) 074 */ 075 public ModelMap addAttribute(String attributeName, Object attributeValue) { 076 Assert.notNull(attributeName, "Model attribute name must not be null"); 077 put(attributeName, attributeValue); 078 return this; 079 } 080 081 /** 082 * Add the supplied attribute to this {@code Map} using a 083 * {@link org.springframework.core.Conventions#getVariableName generated name}. 084 * <p><emphasis>Note: Empty {@link Collection Collections} are not added to 085 * the model when using this method because we cannot correctly determine 086 * the true convention name. View code should check for {@code null} rather 087 * than for empty collections as is already done by JSTL tags.</emphasis> 088 * @param attributeValue the model attribute value (never {@code null}) 089 */ 090 public ModelMap addAttribute(Object attributeValue) { 091 Assert.notNull(attributeValue, "Model object must not be null"); 092 if (attributeValue instanceof Collection && ((Collection<?>) attributeValue).isEmpty()) { 093 return this; 094 } 095 return addAttribute(Conventions.getVariableName(attributeValue), attributeValue); 096 } 097 098 /** 099 * Copy all attributes in the supplied {@code Collection} into this 100 * {@code Map}, using attribute name generation for each element. 101 * @see #addAttribute(Object) 102 */ 103 public ModelMap addAllAttributes(Collection<?> attributeValues) { 104 if (attributeValues != null) { 105 for (Object attributeValue : attributeValues) { 106 addAttribute(attributeValue); 107 } 108 } 109 return this; 110 } 111 112 /** 113 * Copy all attributes in the supplied {@code Map} into this {@code Map}. 114 * @see #addAttribute(String, Object) 115 */ 116 public ModelMap addAllAttributes(Map<String, ?> attributes) { 117 if (attributes != null) { 118 putAll(attributes); 119 } 120 return this; 121 } 122 123 /** 124 * Copy all attributes in the supplied {@code Map} into this {@code Map}, 125 * with existing objects of the same name taking precedence (i.e. not getting 126 * replaced). 127 */ 128 public ModelMap mergeAttributes(Map<String, ?> attributes) { 129 if (attributes != null) { 130 for (Map.Entry<String, ?> entry : attributes.entrySet()) { 131 String key = entry.getKey(); 132 if (!containsKey(key)) { 133 put(key, entry.getValue()); 134 } 135 } 136 } 137 return this; 138 } 139 140 /** 141 * Does this model contain an attribute of the given name? 142 * @param attributeName the name of the model attribute (never {@code null}) 143 * @return whether this model contains a corresponding attribute 144 */ 145 public boolean containsAttribute(String attributeName) { 146 return containsKey(attributeName); 147 } 148 149}