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.input;
034:
035: import com.flexive.faces.FxJsfComponentUtils;
036: import com.flexive.shared.value.FxValue;
037: import com.flexive.shared.value.mapper.IdentityInputMapper;
038: import com.flexive.shared.value.mapper.InputMapper;
039: import com.flexive.shared.value.renderer.FxValueFormatter;
040:
041: import javax.faces.component.UIInput;
042: import javax.faces.component.UIViewRoot;
043: import javax.faces.context.FacesContext;
044:
045: /**
046: * Input fields for FxValue variables, including multi-language support.
047: *
048: * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
049: * @version $Rev: 29 $
050: */
051: public class FxValueInput extends UIInput {
052: /**
053: * The JSF component type for a FxValue component.
054: */
055: public static final String COMPONENT_TYPE = "flexive.FxValueInput";
056:
057: private static ThreadLocal<Integer> idCounter = new ThreadLocal<Integer>();
058:
059: private Boolean disableMultiLanguage;
060: private Long externalId; // an optional external id for identifying this input (ignoring the clientId)
061: private Boolean readOnly;
062: private Boolean forceLineInput;
063: private Boolean filter;
064: private InputMapper inputMapper;
065: private String onchange;
066: private FxValueFormatter valueFormatter;
067:
068: /**
069: * Default constructor
070: */
071: public FxValueInput() {
072: setRendererType("flexive.FxValueInput");
073: addValidator(new FxValueInputValidator());
074: }
075:
076: /**
077: * Disables multi language support even if the FxValue
078: * object is multilingual (e.g. for search query editors).
079: *
080: * @return if multi language support should be disabled
081: */
082: public boolean isDisableMultiLanguage() {
083: if (disableMultiLanguage == null) {
084: return FxJsfComponentUtils.getBooleanValue(this ,
085: "disableMultiLanguage", false);
086: }
087: return disableMultiLanguage;
088: }
089:
090: public void setDisableMultiLanguage(boolean disableMultiLanguage) {
091: this .disableMultiLanguage = disableMultiLanguage;
092: }
093:
094: /**
095: * Sets the component to read-only mode. In read-only mode, the embedded FxValue
096: * is written directly to the response.
097: *
098: * @return true if read-only mode is enabled
099: */
100: public boolean isReadOnly() {
101: if (readOnly == null) {
102: return FxJsfComponentUtils.getBooleanValue(this ,
103: "readOnly", false);
104: }
105: return readOnly;
106: }
107:
108: public void setReadOnly(boolean readOnly) {
109: this .readOnly = readOnly;
110: }
111:
112: /**
113: * Return an arbitrary external ID assigned to this input component. This field
114: * can be used for identifying a component independent of its client ID.
115: * If the external ID is set (i.e. != -1), it replaces the clientId in the
116: * {@link com.flexive.faces.messages.FxFacesMessage#getId()} property when
117: * a validation error message is created.
118: *
119: * @return the external ID assigned to this component, or -1 if there is none
120: */
121: public long getExternalId() {
122: if (externalId == null) {
123: externalId = FxJsfComponentUtils.getLongValue(this ,
124: "externalId");
125: }
126: return externalId == null ? -1 : externalId;
127: }
128:
129: /**
130: * Set an external ID used for identifying this component.
131: *
132: * @param externalId an external ID
133: * @see #getExternalId()
134: */
135: public void setExternalId(long externalId) {
136: this .externalId = externalId;
137: }
138:
139: /**
140: * Return true if the input field must be rendered in a single line. For example,
141: * HTML editors are disabled by this setting.
142: *
143: * @return true if the input field must be rendered in a single line.
144: */
145: public boolean isForceLineInput() {
146: if (forceLineInput == null) {
147: return FxJsfComponentUtils.getBooleanValue(this ,
148: "forceLineInput", false);
149: }
150: return forceLineInput;
151: }
152:
153: /**
154: * Force single-line rendering for the input component. For example,
155: * HTML editors are disabled by this setting.
156: *
157: * @param forceLineInput true if the component must be rendered in a single line
158: */
159: public void setForceLineInput(boolean forceLineInput) {
160: this .forceLineInput = forceLineInput;
161: }
162:
163: /**
164: * Return true if the output filter is enabled (usually only applies
165: * to the component in read-only mode). If enabled, text will be filtered
166: * and HTML entities will be used for sensitive characters (e.g. "&gt;" instead of ">").
167: *
168: * @return true if the output filter is enabled
169: */
170: public boolean isFilter() {
171: if (filter == null) {
172: return FxJsfComponentUtils.getBooleanValue(this , "filter",
173: true);
174: }
175: return filter;
176: }
177:
178: public void setFilter(boolean filter) {
179: this .filter = filter;
180: }
181:
182: /**
183: * Return the input mapper to be used. If no input mapper was defined for the component,
184: * the identity mapper is used.
185: *
186: * @return the input mapper
187: */
188: public InputMapper getInputMapper() {
189: if (inputMapper == null) {
190: inputMapper = (InputMapper) FxJsfComponentUtils.getValue(
191: this , "inputMapper");
192: if (inputMapper == null) {
193: inputMapper = new IdentityInputMapper(); // use dummy mapper
194: }
195: }
196: return inputMapper;
197: }
198:
199: public void setInputMapper(InputMapper inputMapper) {
200: this .inputMapper = inputMapper;
201: }
202:
203: /**
204: * Return the (optional) onchange javascript to be called when an
205: * input element changed its value.
206: *
207: * @return the (optional) onchange javascript to be called if an input element changed its value.
208: */
209: public String getOnchange() {
210: if (onchange == null) {
211: onchange = FxJsfComponentUtils.getStringValue(this ,
212: "onchange");
213: }
214: return onchange;
215: }
216:
217: public void setOnchange(String onchange) {
218: this .onchange = onchange;
219: }
220:
221: /**
222: * Return the (optional) {@link FxValueFormatter} to be used for formatting the output
223: * in read-only mode.
224: *
225: * @return the (optional) {@link FxValueFormatter} to be used for formatting the output
226: * in read-only mode.
227: */
228: public FxValueFormatter getValueFormatter() {
229: if (valueFormatter == null) {
230: valueFormatter = (FxValueFormatter) FxJsfComponentUtils
231: .getValue(this , "valueFormatter");
232: }
233: return valueFormatter;
234: }
235:
236: public void setValueFormatter(FxValueFormatter valueFormatter) {
237: this .valueFormatter = valueFormatter;
238: }
239:
240: @Override
241: public String getClientId(FacesContext facesContext) {
242: if (getId() != null
243: && getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) {
244: // use autogenerated ID - don't use JSF's sequencers since we need the id to be rendered to the client
245: if (idCounter.get() == null) {
246: idCounter.set(0);
247: }
248: setId("fvi" + idCounter.get());
249: idCounter.set(idCounter.get() + 1);
250: }
251: return super .getClientId(facesContext);
252: }
253:
254: /**
255: * Return the input's current value and include the specified inputMapper, if present.
256: * If an input mapper was used, this component's value is mapped and returned. Otherwise,
257: * the component's current value is returned.
258: *
259: * @return the current value as rendered in the UI
260: */
261: public FxValue getUIValue() {
262: if (getInputMapper() != null) {
263: //noinspection unchecked
264: return getInputMapper().encode((FxValue) getValue());
265: } else {
266: return (FxValue) getValue();
267: }
268: }
269:
270: /**
271: * {@inheritDoc}
272: */
273: @Override
274: public void restoreState(FacesContext context, Object state) {
275: Object[] values = (Object[]) state;
276: int index = 0;
277: super .restoreState(context, values[index++]);
278: this .disableMultiLanguage = (Boolean) values[index++];
279: this .externalId = (Long) values[index++];
280: this .readOnly = (Boolean) values[index++];
281: this .forceLineInput = (Boolean) values[index++];
282: this .onchange = (String) values[index++];
283: //noinspection UnusedAssignment
284: this .filter = (Boolean) values[index++];
285: }
286:
287: /**
288: * {@inheritDoc}
289: */
290: @Override
291: public Object saveState(FacesContext context) {
292: Object[] values = new Object[7];
293: int index = 0;
294: values[index++] = super .saveState(context);
295: values[index++] = disableMultiLanguage;
296: values[index++] = externalId;
297: values[index++] = readOnly;
298: values[index++] = forceLineInput;
299: values[index++] = onchange;
300: //noinspection UnusedAssignment
301: values[index++] = filter;
302: return values;
303: }
304:
305: }
|