001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2007
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.faces.components.toolkit;
034:
035: import com.flexive.shared.exceptions.FxRuntimeException;
036: import com.flexive.shared.value.FxValue;
037: import com.flexive.shared.value.mapper.InputMapper;
038: import com.sun.facelets.FaceletContext;
039: import com.sun.facelets.el.VariableMapperWrapper;
040: import com.sun.facelets.tag.TagAttribute;
041: import com.sun.facelets.tag.TagConfig;
042: import com.sun.facelets.tag.TagHandler;
043:
044: import javax.el.ELException;
045: import javax.el.ValueExpression;
046: import javax.el.VariableMapper;
047: import javax.faces.FacesException;
048: import javax.faces.component.UIComponent;
049: import java.io.IOException;
050:
051: /**
052: * A facelets handler that renders a complete form element for editing or displaying
053: * a property of a content instance provided by {@link FxContentView}. The output template
054: * is provided by fxValueInputRow.xhtml (the component template of fx:fxValueInputRow).
055: * A custom template can be specified with the <code>template</code> parameter.
056: *
057: * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
058: * @version $Rev: 1 $
059: */
060: public class FxValueHandler extends TagHandler {
061: private static final String TEMPLATE_ROOT = "templates/";
062: private String template = "fxValueInputRow.xhtml";
063:
064: public FxValueHandler(TagConfig config) {
065: super (config);
066: }
067:
068: public void apply(FaceletContext ctx, UIComponent parent)
069: throws IOException, FacesException, ELException {
070: final String var;
071: try {
072: if (this .getAttribute("var") == null) {
073: // no variable name specified, use enclosing content view
074: if (!(parent instanceof FxContentView)) {
075: throw new FacesException(
076: "Facelet parent is no FxContentView instance and \"var\" attribute not specified.");
077: }
078: var = ((FxContentView) parent).getVar();
079: } else {
080: // use a custom variable name
081: var = this .getAttribute("var").getValue(ctx);
082: }
083: } catch (FxRuntimeException e) {
084: throw new FacesException(
085: "The fx:value component must be embedded in a fx:content instance.");
086: }
087: final boolean isNewValue = this .getAttribute("new") != null
088: && Boolean.valueOf(this .getAttribute("new").getValue(
089: ctx));
090: final VariableMapper origMapper = ctx.getVariableMapper();
091: final VariableMapperWrapper mapper = new VariableMapperWrapper(
092: origMapper);
093: try {
094: ctx.setVariableMapper(mapper);
095:
096: // get property attribute
097: final ValueExpression propertyExpression = this
098: .getAttribute("property").getValueExpression(ctx,
099: String.class);
100: final String property = (String) propertyExpression
101: .getValue(ctx);
102:
103: // assign id, label/labelKey and value based on the enclosing FxContentView instance
104: // if the property contains a slash, return the part after the last slash character as unique ID
105: mapper.setVariable("id", ctx.getExpressionFactory()
106: .createValueExpression(
107: property.indexOf('/') != -1 ? property
108: .substring(property
109: .lastIndexOf('/') + 1)
110: : property, String.class));
111: if (this .getAttribute("labelKey") == null) {
112: // use property label
113: mapper.setVariable("label", ctx.getExpressionFactory()
114: .createValueExpression(
115: ctx,
116: FxContentView.getExpression(var,
117: property, "label"),
118: String.class));
119: } else {
120: // use provided message key
121: assignAttribute(ctx, mapper, "labelKey", String.class);
122: }
123: // retrieve content from content view
124: mapper.setVariable("value", ctx.getExpressionFactory()
125: .createValueExpression(
126: ctx,
127: FxContentView.getExpression(var, property,
128: isNewValue ? "new" : null),
129: FxValue.class));
130:
131: // passthrough other template attributes
132: assignAttribute(ctx, mapper, "inputMapper",
133: InputMapper.class);
134: assignAttribute(ctx, mapper, "onchange", String.class);
135: assignAttribute(ctx, mapper, "readOnly", Boolean.class);
136: assignAttribute(ctx, mapper, "decorate", Boolean.class);
137: assignAttribute(ctx, mapper, "filter", Boolean.class);
138:
139: // TODO: cache templates/use a facelet ResourceResolver to encapsulate this
140: ctx.includeFacelet(parent, Thread.currentThread()
141: .getContextClassLoader().getResource(
142: TEMPLATE_ROOT + template));
143: } finally {
144: ctx.setVariableMapper(origMapper);
145: }
146: }
147:
148: private void assignAttribute(FaceletContext ctx,
149: VariableMapper mapper, String name, Class<?> expectedClass) {
150: final TagAttribute attribute = getAttribute(name);
151: if (attribute != null) {
152: mapper.setVariable(name, attribute.getValueExpression(ctx,
153: expectedClass));
154: }
155: }
156:
157: /**
158: * Sets the template name (relative to /WEB-INF/templates).
159: *
160: * @param template the template name (relative to /WEB-INF/templates).
161: */
162: public void setTemplate(String template) {
163: this.template = template;
164: }
165: }
|