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 }