/*
* (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Contributors:
* Nuxeo - initial API and implementation
*
* $Id$
*/
package org.nuxeo.ecm.platform.ui.web.directory;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.component.UIOutput;
import javax.faces.component.UIParameter;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.ValueBinding;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.common.utils.i18n.I18NUtils;
/**
* @author <a href="mailto:glefter@nuxeo.com">George Lefter</a>
*
*/
public class ChainSelectStatus extends UIOutput {
public static final String COMPONENT_TYPE = "nxdirectory.chainSelectStatus";
public static final String COMPONENT_FAMILY = "nxdirectory.chainSelectStatus";
public static final String REMOVE_ID = "chainSelect_removeId";
@SuppressWarnings("unused")
private static final Log log = LogFactory.getLog(ChainSelectStatus.class);
private String name;
private boolean displayIncremental = false;
private boolean displayRoot = false;
private String cssStyle;
private String cssStyleClass;
private String entryCssStyle;
private String entryCssStyleClass;
private String entrySeparator;
private String image;
// what to display - the value or the selection of the component
private String display;
// what will be display as a label in front of the select result
private String label;
public String getEntrySeparator() {
return entrySeparator;
}
public void setEntrySeparator(String entrySeparator) {
this.entrySeparator = entrySeparator;
}
@Override
public String getFamily() {
return COMPONENT_FAMILY;
}
@Override
public String getRendererType() {
return null;
}
@Override
public void restoreState(FacesContext context, Object state) {
Object[] values = (Object[]) state;
super.restoreState(context, values[0]);
name = (String) values[1];
displayIncremental = (Boolean) values[2];
displayRoot = (Boolean) values[3];
cssStyle = (String) values[4];
cssStyleClass = (String) values[5];
entryCssStyle = (String) values[6];
entryCssStyleClass = (String) values[7];
entrySeparator = (String) values[8];
display = (String) values[9];
image = (String) values[10];
label = (String) values[11];
}
@Override
public Object saveState(FacesContext arg0) {
Object[] values = new Object[12];
values[0] = super.saveState(arg0);
values[1] = name;
values[2] = displayIncremental;
values[3] = displayRoot;
values[4] = cssStyle;
values[5] = cssStyleClass;
values[6] = entryCssStyle;
values[7] = entryCssStyleClass;
values[8] = entrySeparator;
values[9] = display;
values[10] = image;
values[11] = label;
return values;
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String id = getClientId(context);
String cssStyle = getStringProperty("cssStyle", null);
String cssStyleClass = getStringProperty("cssStyleClass", null);
String separator = getStringProperty("separator", "/");
String entrySeparator = getStringProperty("entrySeparator", null);
String label = getStringProperty("label", null);
ChainSelect chain = getChain();
Boolean displayValueOnly = chain.getBooleanProperty("displayValueOnly",
false);
String display = getStringProperty("display", "selection");
Selection[] selections;
if (display.equals("selection")) {
selections = chain.getSelections();
} else {
selections = chain.getComponentValue();
}
boolean multiParentSelect = chain.getBooleanProperty(
"multiParentSelect", false);
if (displayValueOnly) {
cssStyle = chain.getStringProperty("displayValueOnlyStyle", null);
cssStyleClass = chain.getStringProperty(
"displayValueOnlyStyleClass", null);
}
writer.startElement("div", this);
writer.writeAttribute("id", id, "id");
if (cssStyle != null) {
writer.writeAttribute("style", cssStyle, "style");
}
if (cssStyleClass != null) {
writer.writeAttribute("class", cssStyleClass, "class");
}
if (selections.length > 0 && label != null) {
writer.write(label);
}
for (int i = 0; i < selections.length; i++) {
writer.startElement("div", this);
if (entryCssStyle != null) {
writer.writeAttribute("style", entryCssStyle, "style");
}
if (entryCssStyleClass != null) {
//FIXME: is this a typo? Should it be entryCssStyleClass down there instead of entryCssStyle?
writer.writeAttribute("class", entryCssStyle, "class");
}
if (!displayValueOnly && display.equals("value")
&& multiParentSelect) {
UICommand button = (UICommand) getFacet("removeButton");
if (button == null) {
throw new RuntimeException(
"f:facet with name='removeButton' not found for component "
+ getId());
}
String selectionId = selections[i].getValue(chain.getKeySeparator());
getUIParameter(button).setValue(selectionId);
button.encodeBegin(context);
button.encodeChildren(context);
button.encodeEnd(context);
}
String[] labels = selections[i].getLabels();
String[] values = selections[i].getValues();
String[] displayedLabels = null;
if (labels != null) {
displayedLabels = new String[labels.length];
for (int j = 0; j < labels.length; j++) {
// boolean localize = chain.getComponent(j)
// .getBooleanProperty("localize", false);
boolean localize;
String compDisplay;
if (chain.compInfos.get(i) != null) {
localize = chain.compInfos.get(i).localize;
compDisplay = chain.compInfos.get(i).display;
} else {
// fallback on the old solution
localize = chain.getComponent(j).getBooleanProperty(
"localize", false);
compDisplay = chain.getComponent(j).getDisplay();
}
String compLabel = labels[j];
if (localize) {
compLabel = translate(context, compLabel);
}
if ("id".equals(compDisplay)) {
displayedLabels[j] = values[j];
} else if ("idAndLabel".equals(compDisplay)) {
displayedLabels[j] = values[j] + " " + compLabel;
} else {
// default to "label"
displayedLabels[j] = compLabel;
}
}
}
String concatenatedLabel = StringUtils.join(displayedLabels,
separator);
if (concatenatedLabel.compareTo("") == 0 && displayedLabels.length != 0){
concatenatedLabel = translate(context, "label.directories.error");
}
writer.write(concatenatedLabel);
writer.endElement("div");
if (i != selections.length - 1) {
if (entrySeparator != null) {
writer.write(entrySeparator);
}
}
}
}
private UIParameter getUIParameter(UIComponent component) {
UIParameter param = null;
for (UIComponent child : component.getChildren()) {
if (child instanceof UIParameter) {
UIParameter paramChild = (UIParameter) child;
if (REMOVE_ID.equals(paramChild.getName())) {
param = (UIParameter) child;
break;
}
}
}
if (param == null) {
param = new UIParameter();
param.setName(REMOVE_ID);
component.getChildren().add(param);
}
return param;
}
@Override
public void encodeChildren(FacesContext context) throws IOException {
}
@Override
public void encodeEnd(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.endElement("div");
List<UIComponent> children = getChildren();
for (UIComponent component : children) {
component.setRendered(true);
}
}
public Object getProperty(String name) {
ValueBinding vb = getValueBinding(name);
if (vb != null) {
return vb.getValue(FacesContext.getCurrentInstance());
} else {
Map<String, Object> attrMap = getAttributes();
return attrMap.get(name);
}
}
public String getStringProperty(String name, String defaultValue) {
String value = (String) getProperty(name);
return value != null ? value : defaultValue;
}
public Boolean getBooleanProperty(String name, Boolean defaultValue) {
Boolean value = (Boolean) getProperty(name);
return value != null ? value : defaultValue;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ChainSelect getChain() {
UIComponent component = getParent();
while (component != null && !(component instanceof ChainSelect)) {
component = component.getParent();
}
return (ChainSelect) component;
}
public boolean isDisplayIncremental() {
return displayIncremental;
}
public void setDisplayIncremental(boolean displayIncremental) {
this.displayIncremental = displayIncremental;
}
public boolean isDisplayRoot() {
return displayRoot;
}
public void setDisplayRoot(boolean displayRoot) {
this.displayRoot = displayRoot;
}
public String getCssStyle() {
return cssStyle;
}
public void setCssStyle(String cssStyle) {
this.cssStyle = cssStyle;
}
public String getCssStyleClass() {
return cssStyleClass;
}
public void setCssStyleClass(String cssStyleClass) {
this.cssStyleClass = cssStyleClass;
}
public String getEntryCssStyle() {
return entryCssStyle;
}
public void setEntryCssStyle(String entryCssStyle) {
this.entryCssStyle = entryCssStyle;
}
public String getEntryCssStyleClass() {
return entryCssStyleClass;
}
public void setEntryCssStyleClass(String entryCssStyleClass) {
this.entryCssStyleClass = entryCssStyleClass;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getDisplay() {
return display;
}
public void setDisplay(String display) {
this.display = display;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
protected static String translate(FacesContext context, String label) {
String bundleName = context.getApplication().getMessageBundle();
Locale locale = context.getViewRoot().getLocale();
label = I18NUtils.getMessageString(bundleName, label, null, locale);
return label;
}
}