1 /* 2 * $Id: GetAsStringModel.java 1625204 2014-09-16 02:21:04Z 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.io.IOException; 25 import java.io.Writer; 26 import java.util.Deque; 27 28 import org.apache.tiles.Attribute; 29 import org.apache.tiles.TilesContainer; 30 import org.apache.tiles.access.TilesAccess; 31 import org.apache.tiles.autotag.core.runtime.ModelBody; 32 import org.apache.tiles.autotag.core.runtime.annotation.Parameter; 33 import org.apache.tiles.request.Request; 34 import org.slf4j.Logger; 35 import org.slf4j.LoggerFactory; 36 37 /** 38 * <p> 39 * <strong> Render the value of the specified template attribute to the current 40 * Writer</strong> 41 * </p> 42 * 43 * <p> 44 * Retrieve the value of the specified template attribute property, and render 45 * it to the current Writer as a String. The usual toString() conversions is 46 * applied on found value. 47 * </p> 48 * 49 * @version $Rev: 1625204 $ $Date: 2014-09-16 12:21:04 +1000 (Tue, 16 Sep 2014) $ 50 * @since 2.2.0 51 */ 52 public class GetAsStringModel { 53 54 /** 55 * The logging object. 56 */ 57 private Logger log = LoggerFactory.getLogger(getClass()); 58 59 /** 60 * The attribute resolver to use. 61 */ 62 private AttributeResolver attributeResolver; 63 64 /** 65 * Constructor that uses the defaut attribute resolver. 66 * 67 * @since 3.0.0 68 */ 69 public GetAsStringModel() { 70 this(new DefaultAttributeResolver()); 71 } 72 73 /** 74 * Constructor. 75 * 76 * @param attributeResolver The attribute resolver to use. 77 * @since 2.2.0 78 */ 79 public GetAsStringModel(AttributeResolver attributeResolver) { 80 this.attributeResolver = attributeResolver; 81 } 82 83 /** 84 * Executes the operation. 85 * @param ignore If <code>true</code>, if an exception happens during 86 * rendering, of if the attribute is null, the problem will be ignored. 87 * @param preparer The preparer to invoke before rendering the attribute. 88 * @param role A comma-separated list of roles. If present, the attribute 89 * will be rendered only if the current user belongs to one of the roles. 90 * @param defaultValue The default value of the attribute. To use only if 91 * the attribute was not computed. 92 * @param defaultValueRole The default comma-separated list of roles. To use 93 * only if the attribute was not computed. 94 * @param defaultValueType The default type of the attribute. To use only if 95 * the attribute was not computed. 96 * @param name The name of the attribute. 97 * @param value The attribute to use immediately, if not null. 98 * @param request The request. 99 * @param modelBody The body. 100 * @throws IOException If an I/O error happens during rendering. 101 * @since 2.2.0 102 */ 103 public void execute(boolean ignore, String preparer, String role, 104 Object defaultValue, String defaultValueRole, 105 String defaultValueType, @Parameter(required = true) String name, 106 Attribute value, Request request, ModelBody modelBody) 107 throws IOException { 108 TilesContainer container = TilesAccess.getCurrentContainer(request); 109 Deque<Object> composeStack = ComposeStackUtil.getComposeStack(request); 110 Attribute attribute = resolveAttribute(container, ignore, preparer, 111 role, defaultValue, defaultValueRole, defaultValueType, name, 112 value, request); 113 if (attribute != null) { 114 composeStack.push(attribute); 115 } 116 modelBody.evaluateWithoutWriting(); 117 container = TilesAccess.getCurrentContainer(request); 118 Writer writer = request.getWriter(); 119 if (attribute != null) { 120 attribute = (Attribute) composeStack.pop(); 121 } 122 renderAttribute(attribute, container, writer, ignore, request); 123 } 124 125 /** 126 * Resolves the attribute. and starts the context. 127 * 128 * @param container The Tiles container to use. 129 * @param ignore If <code>true</code>, if an exception happens during 130 * rendering, of if the attribute is null, the problem will be ignored. 131 * @param preparer The preparer to invoke before rendering the attribute. 132 * @param role A comma-separated list of roles. If present, the attribute 133 * will be rendered only if the current user belongs to one of the roles. 134 * @param defaultValue The default value of the attribute. To use only if 135 * the attribute was not computed. 136 * @param defaultValueRole The default comma-separated list of roles. To use 137 * only if the attribute was not computed. 138 * @param defaultValueType The default type of the attribute. To use only if 139 * the attribute was not computed. 140 * @param name The name of the attribute. 141 * @param value The attribute to use immediately, if not null. 142 * @param request The request. 143 * @return The resolved attribute. 144 */ 145 private Attribute resolveAttribute(TilesContainer container, 146 boolean ignore, String preparer, String role, Object defaultValue, 147 String defaultValueRole, String defaultValueType, String name, 148 Attribute value, Request request) { 149 if (preparer != null) { 150 container.prepare(preparer, request); 151 } 152 Attribute attribute = attributeResolver.computeAttribute(container, 153 value, name, role, ignore, defaultValue, defaultValueRole, 154 defaultValueType, request); 155 container.startContext(request); 156 return attribute; 157 } 158 159 /** 160 * Renders the attribute as a string. 161 * 162 * @param attribute The attribute to use, previously resolved. 163 * @param container The Tiles container to use. 164 * @param writer The writer into which the attribute will be written. 165 * @param ignore If <code>true</code>, if an exception happens during 166 * rendering, of if the attribute is null, the problem will be ignored. 167 * @param request The request. 168 * @throws IOException If an I/O error happens during rendering. 169 */ 170 private void renderAttribute(Attribute attribute, TilesContainer container, 171 Writer writer, boolean ignore, Request request) 172 throws IOException { 173 try { 174 if (attribute == null && ignore) { 175 return; 176 } 177 Object value = container.evaluate(attribute, request); 178 if(value != null) { 179 writer.write(value.toString()); 180 } 181 } catch (IOException e) { 182 if (!ignore) { 183 throw e; 184 } else if (log.isDebugEnabled()) { 185 log.debug("Ignoring exception", e); 186 } 187 } catch (RuntimeException e) { 188 if (!ignore) { 189 throw e; 190 } else if (log.isDebugEnabled()) { 191 log.debug("Ignoring exception", e); 192 } 193 } finally { 194 container.endContext(request); 195 } 196 } 197 }