1 /* 2 * $Id: ImportAttributeModel.java 1291847 2012-02-21 15:09:30Z nlebas $ 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 package org.apache.tiles.template; 23 24 import java.util.Collection; 25 import java.util.HashMap; 26 import java.util.Map; 27 28 import org.apache.tiles.Attribute; 29 import org.apache.tiles.AttributeContext; 30 import org.apache.tiles.TilesContainer; 31 import org.apache.tiles.access.TilesAccess; 32 import org.apache.tiles.request.Request; 33 import org.slf4j.Logger; 34 import org.slf4j.LoggerFactory; 35 36 /** 37 * <p> 38 * <strong>Import attribute(s) in specified context.</strong> 39 * </p> 40 * <p> 41 * Import attribute(s) to requested scope. Attribute name and scope are 42 * optional. If not specified, all attributes are imported in page scope. Once 43 * imported, an attribute can be used as any other beans from jsp contexts. 44 * </p> 45 * 46 * @version $Rev: 1291847 $ $Date: 2012-02-22 02:09:30 +1100 (Wed, 22 Feb 2012) $ 47 * @since 2.2.0 48 */ 49 public class ImportAttributeModel { 50 51 /** 52 * The logging object. 53 */ 54 private Logger log = LoggerFactory.getLogger(getClass()); 55 56 /** 57 * Executes the model. 58 * 59 * @param name The name of the attribute to import. If it is 60 * <code>null</code>, all the attributes will be imported. 61 * @param scope The scope into which the attribute(s) will be imported. If 62 * <code>null</code>, the import will go in page scope. 63 * @param toName The name of the attribute into which the attribute will be 64 * imported. To be used in conjunction to <code>name</code>. If 65 * <code>null</code>, the value of <code>name</code> will be used. 66 * @param ignore If <code>true</code>, if the attribute is not present, the 67 * problem will be ignored. 68 * @param request The request. 69 */ 70 public void execute(String name, String scope, String toName, boolean ignore, Request request) { 71 Map<String, Object> attributes = getImportedAttributes( 72 name, toName, ignore, request); 73 if (scope == null) { 74 scope = request.getAvailableScopes().get(0); 75 } 76 request.getContext(scope).putAll(attributes); 77 } 78 79 /** 80 * Retuns a Map that contains the attributes to be imported. The importing 81 * code must be done by the caller. 82 * @param name The attribute to import. If null, all the attributes will be 83 * imported. 84 * @param toName The destination name of the attribute to import. Valid only 85 * if <code>name</code> is specified. 86 * @param ignore If <code>true</code> and the attribute is not found, or an 87 * exception happens, the problem will be ignored. 88 * @param request The request. 89 * 90 * @return A Map of the attributes to be imported: the key is the name of an 91 * attribute, the value is the value of that attribute. 92 * @since 2.2.0 93 */ 94 private Map<String, Object> getImportedAttributes(String name, 95 String toName, boolean ignore, Request request) { 96 TilesContainer container = TilesAccess.getCurrentContainer(request); 97 Map<String, Object> retValue = new HashMap<String, Object>(); 98 AttributeContext attributeContext = container 99 .getAttributeContext(request); 100 // Some tags allow for unspecified attributes. This 101 // implies that the tag should use all of the attributes. 102 if (name != null) { 103 importSingleAttribute(container, attributeContext, name, toName, 104 ignore, retValue, request); 105 } else { 106 importAttributes(attributeContext.getCascadedAttributeNames(), 107 container, attributeContext, retValue, ignore, request); 108 importAttributes(attributeContext.getLocalAttributeNames(), 109 container, attributeContext, retValue, ignore, request); 110 } 111 return retValue; 112 } 113 114 /** 115 * Imports a single attribute. 116 * 117 * @param container The Tiles container to use. 118 * @param attributeContext The context from which the attributes will be 119 * got. 120 * @param name The name of the attribute. 121 * @param toName The name of the destination attribute. If null, 122 * <code>name</code> will be used. 123 * @param ignore If <code>true</code> and the attribute is not found, or an 124 * exception happens, the problem will be ignored. 125 * @param attributes The map of the attributes to fill. 126 * @param request The request. 127 */ 128 private void importSingleAttribute(TilesContainer container, 129 AttributeContext attributeContext, String name, String toName, 130 boolean ignore, Map<String, Object> attributes, 131 Request request) { 132 Attribute attr = attributeContext.getAttribute(name); 133 if (attr != null) { 134 try { 135 Object attributeValue = container.evaluate(attr, 136 request); 137 if (attributeValue == null) { 138 if (!ignore) { 139 throw new NoSuchAttributeException( 140 "Error importing attributes. " + "Attribute '" 141 + name + "' has a null value "); 142 } 143 } else { 144 if (toName != null) { 145 attributes.put(toName, attributeValue); 146 } else { 147 attributes.put(name, attributeValue); 148 } 149 } 150 } catch (RuntimeException e) { 151 if (!ignore) { 152 throw e; 153 } else if (log.isDebugEnabled()) { 154 log.debug("Ignoring Tiles Exception", e); 155 } 156 } 157 } else if (!ignore) { 158 throw new NoSuchAttributeException( 159 "Error importing attributes. " + "Attribute '" + name 160 + "' is null"); 161 } 162 } 163 164 /** 165 * Imports all the attributes. 166 * 167 * @param names The names of the attributes to be imported. 168 * @param container The Tiles container to use. 169 * @param attributeContext The context from which the attributes will be 170 * got. 171 * @param attributes The map of the attributes to fill. 172 * @param ignore If <code>true</code> and the attribute is not found, or an 173 * exception happens, the problem will be ignored. 174 * @param request The request. 175 */ 176 private void importAttributes(Collection<String> names, 177 TilesContainer container, AttributeContext attributeContext, 178 Map<String, Object> attributes, boolean ignore, 179 Request request) { 180 if (names == null || names.isEmpty()) { 181 return; 182 } 183 184 for (String name : names) { 185 if (name == null && !ignore) { 186 throw new NoSuchAttributeException( 187 "Error importing attributes. " 188 + "Attribute with null key found."); 189 } else if (name == null) { 190 continue; 191 } 192 193 importSingleAttribute(container, attributeContext, name, name, 194 ignore, attributes, request); 195 } 196 } 197 }