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.shared.EJBLookup;
036: import com.flexive.shared.FxLanguage;
037: import com.flexive.shared.exceptions.FxApplicationException;
038: import com.flexive.shared.exceptions.FxInvalidParameterException;
039: import com.flexive.shared.exceptions.FxUpdateException;
040: import com.flexive.shared.value.*;
041: import com.flexive.faces.FxJsfUtils;
042: import org.apache.commons.lang.StringUtils;
043: import org.apache.commons.logging.Log;
044: import org.apache.commons.logging.LogFactory;
045: import org.apache.myfaces.custom.date.HtmlInputDate;
046: import org.apache.myfaces.custom.fileupload.HtmlInputFileUpload;
047: import org.apache.myfaces.custom.fileupload.UploadedFile;
048:
049: import javax.faces.component.UIComponent;
050: import javax.faces.component.UIInput;
051: import javax.faces.context.FacesContext;
052: import javax.faces.context.ResponseWriter;
053: import javax.faces.render.Renderer;
054: import java.io.IOException;
055: import java.text.ParseException;
056: import java.util.Date;
057: import java.util.List;
058: import java.util.Map;
059:
060: /**
061: * Renderer for the FxValueInput component.
062: *
063: * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
064: * @version $Rev: 207 $
065: */
066: public class FxValueInputRenderer extends Renderer {
067: private static final Log LOG = LogFactory
068: .getLog(FxValueInputRenderer.class);
069:
070: protected static final String LANG_CONTAINER = "_language_";
071: protected static final String DEFAULT_LANGUAGE = "_defaultLanguage";
072: protected static final String LANG_SELECT = "_languageSelect";
073: protected static final String INPUT = "_input_";
074: protected static final String CSS_CONTAINER = "fxValueInput";
075: protected static final String CSS_LANG_CONTAINER = "fxValueInputRow";
076: protected static final String CSS_TEXT_INPUT = "fxValueTextInput";
077: protected static final String CSS_TEXTAREA = "fxValueTextArea";
078: protected static final String CSS_TEXTAREA_HTML = "fxValueTextAreaHtml";
079: protected static final String CSS_INPUTELEMENTWIDTH = "fxValueInputElementWidth";
080:
081: /**
082: * {@inheritDoc}
083: */
084: @Override
085: public void encodeBegin(FacesContext context, UIComponent input)
086: throws IOException {
087: FxValueInput component = (FxValueInput) input;
088: ResponseWriter writer = context.getResponseWriter();
089: String clientId = input.getClientId(context);
090: //noinspection unchecked
091: FxValue value = component.getInputMapper().encode(
092: getFxValue(context, component));
093: RenderHelper helper = component.isReadOnly() ? new ReadOnlyModeHelper(
094: writer, component, clientId, value)
095: : new EditModeHelper(writer, component, clientId, value);
096: component.getChildren().clear();
097: if (!(value instanceof FxVoid)) {
098: helper.render();
099: }
100: }
101:
102: /**
103: * {@inheritDoc}
104: */
105: @Override
106: public void decode(FacesContext context, UIComponent component) {
107: FxValueInput input = (FxValueInput) component;
108: if (!(input.getValue() instanceof FxVoid)
109: && !input.isReadOnly()) {
110: input.setSubmittedValue(decodeFxValue(context, component));
111: }
112: }
113:
114: /**
115: * Return the FxValue used as input for the component.
116: *
117: * @param context the faces context
118: * @param input the FxValueInput component @return the FxValue used as input for the component.
119: * @return the FxValue stored in the input component
120: */
121: private FxValue getFxValue(FacesContext context, UIInput input) {
122: Object o = input.getSubmittedValue() != null ? input
123: .getSubmittedValue() : input.getValue();
124: if (o == null) {
125: throw new FxInvalidParameterException("VALUE",
126: "ex.jsf.valueInput.null", input
127: .getClientId(context)).asRuntimeException();
128: } else if (!(o instanceof FxValue)) {
129: throw new FxInvalidParameterException("VALUE",
130: "ex.jsf.valueInput.invalidType", o.getClass()
131: .getCanonicalName()).asRuntimeException();
132: }
133: return (FxValue) o;
134: }
135:
136: /**
137: * Decode FxValue items posted for this component.
138: *
139: * @param context the current faces context
140: * @param component the component to be rendered
141: * @return FxValue items posted for this component.
142: */
143: private FxValue decodeFxValue(FacesContext context,
144: UIComponent component) {
145: final FxValueInput input = (FxValueInput) component;
146: final Map parameters = context.getExternalContext()
147: .getRequestParameterMap();
148: final Map parameterValues = context.getExternalContext()
149: .getRequestParameterValuesMap();
150: final String clientId = component.getClientId(context);
151: final FxValue value = getFxValue(context, input).copy();
152:
153: if (value.isMultiLanguage() && !input.isDisableMultiLanguage()) {
154: final int defaultLanguageId = Integer
155: .parseInt((String) parameters.get(clientId
156: + DEFAULT_LANGUAGE));
157: value.setDefaultLanguage(defaultLanguageId, true);
158: // update all languages
159: for (FxLanguage language : getLanguages()) {
160: final String inputId = clientId + INPUT
161: + language.getId();
162: updateTranslation(input, value, inputId, language
163: .getId(), parameters, parameterValues);
164: }
165: } else {
166: updateTranslation(input, value, clientId
167: + FxValueInputRenderer.INPUT, value
168: .getDefaultLanguage(), parameters, parameterValues);
169: }
170:
171: return value;
172: }
173:
174: @SuppressWarnings({"unchecked"})
175: private void updateTranslation(FxValueInput input, FxValue value,
176: String inputId, long languageId, Map parameters,
177: Map parameterValues) {
178: if (value instanceof FxSelectMany) {
179: final String selectedOptions = StringUtils.join(
180: (String[]) parameterValues.get(inputId), ',');
181: if (StringUtils.isNotBlank(selectedOptions)) {
182: // update selection
183: value.setTranslation(languageId, selectedOptions);
184: } else {
185: // remove all selected items
186: ((FxSelectMany) value).getDefaultTranslation()
187: .deselectAll();
188: }
189: } else if (value instanceof FxDate
190: || value instanceof FxDateTime) {
191: // get date value from dateinput child
192: //noinspection unchecked
193: final HtmlInputDate dateInput = FxJsfUtils.findChild(input,
194: HtmlInputDate.class);
195: HtmlInputDate.UserData data = (HtmlInputDate.UserData) dateInput
196: .getSubmittedValue();
197: try {
198: final Date date = data.parse();
199: if (date != null) {
200: value.setTranslation(languageId, date);
201: } else {
202: value.setEmpty(languageId);
203: }
204: } catch (ParseException e) {
205: // keep old value
206: }
207: } else if (value instanceof FxBinary) {
208: final HtmlInputFileUpload upload = (HtmlInputFileUpload) FacesContext
209: .getCurrentInstance().getViewRoot().findComponent(
210: inputId);
211: if (upload != null) {
212: try {
213: final UploadedFile file = (UploadedFile) upload
214: .getSubmittedValue();
215: if (file != null && file.getSize() > 0) {
216: //noinspection unchecked
217:
218: String name = file.getName();
219: if (name.indexOf('\\') > 0)
220: name = name.substring(name
221: .lastIndexOf('\\') + 1);
222: value.setTranslation(languageId,
223: new BinaryDescriptor(name, file
224: .getSize(), file
225: .getInputStream()));
226: }
227: } catch (Exception e) {
228: throw new FxUpdateException(LOG, e,
229: "ex.jsf.valueInput.file.upload.io", e)
230: .asRuntimeException();
231: }
232: }
233: } else if (value instanceof FxBoolean) {
234: value.setTranslation(languageId, StringUtils
235: .isNotBlank((String) parameters.get(inputId)));
236: } else {
237: final String postedValue = (String) parameters.get(inputId);
238: if (StringUtils.isNotBlank(postedValue)) {
239: value.setTranslation(languageId, postedValue);
240: } else {
241: value.removeLanguage(languageId);
242: }
243: }
244: }
245:
246: /**
247: * Load all available languages.
248: *
249: * @return all available languages.
250: */
251: protected static List<FxLanguage> getLanguages() {
252: List<FxLanguage> languages;
253: try {
254: languages = EJBLookup.getLanguageEngine().loadAvailable(
255: true);
256: } catch (FxApplicationException e) {
257: throw e.asRuntimeException();
258: }
259: return languages;
260: }
261: }
|