Return-Path: X-Original-To: apmail-empire-db-commits-archive@www.apache.org Delivered-To: apmail-empire-db-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A09D518F3A for ; Mon, 1 Feb 2016 13:18:43 +0000 (UTC) Received: (qmail 88439 invoked by uid 500); 1 Feb 2016 13:18:30 -0000 Delivered-To: apmail-empire-db-commits-archive@empire-db.apache.org Received: (qmail 88399 invoked by uid 500); 1 Feb 2016 13:18:30 -0000 Mailing-List: contact commits-help@empire-db.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: empire-db-dev@empire-db.apache.org Delivered-To: mailing list commits@empire-db.apache.org Received: (qmail 88369 invoked by uid 99); 1 Feb 2016 13:18:30 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 Feb 2016 13:18:30 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 95AEDE031B; Mon, 1 Feb 2016 13:18:30 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: doebele@apache.org To: commits@empire-db.apache.org Date: Mon, 01 Feb 2016 13:18:32 -0000 Message-Id: In-Reply-To: <37918ad0aa02444f8bc6616e06fea287@git.apache.org> References: <37918ad0aa02444f8bc6616e06fea287@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [3/3] empire-db git commit: EMPIREDB-235 EMPIREDB-235 Project: http://git-wip-us.apache.org/repos/asf/empire-db/repo Commit: http://git-wip-us.apache.org/repos/asf/empire-db/commit/9176b225 Tree: http://git-wip-us.apache.org/repos/asf/empire-db/tree/9176b225 Diff: http://git-wip-us.apache.org/repos/asf/empire-db/diff/9176b225 Branch: refs/heads/master Commit: 9176b225f4c3816486b05146a22167e0a0d5b851 Parents: 1f1259b Author: Rainer Döbele Authored: Mon Feb 1 14:18:21 2016 +0100 Committer: Rainer Döbele Committed: Mon Feb 1 14:18:21 2016 +0100 ---------------------------------------------------------------------- .../empire-db-example-jsf2/pom.xml | 2 +- .../jsf2/custom/controls/FileInputControl.java | 14 + .../websample/web/pages/EmployeeDetailPage.java | 18 + .../main/resources/lang/messages_de.properties | 14 +- .../main/resources/lang/messages_en.properties | 3 + .../src/main/webapp/WEB-INF/faces-config.xml | 20 +- .../src/main/webapp/css/content.css | 51 +- .../main/webapp/pages/employeeDetailPage.xhtml | 35 +- .../main/webapp/resources/empire/mitem.xhtml | 19 + .../main/webapp/resources/empire/mlist.xhtml | 19 + .../main/webapp/resources/empire/select.xhtml | 21 + .../main/webapp/resources/empire/tabPage.xhtml | 15 + .../main/webapp/resources/empire/tabView.xhtml | 17 + .../apache/empire/jsf2/app/WebApplication.java | 4 +- .../empire/jsf2/components/ControlTag.java | 464 +++++++++++-------- .../apache/empire/jsf2/components/InputTag.java | 149 ++++-- .../apache/empire/jsf2/components/LabelTag.java | 56 ++- .../apache/empire/jsf2/components/LinkTag.java | 86 +++- .../empire/jsf2/components/MenuItemTag.java | 52 ++- .../empire/jsf2/components/MenuListTag.java | 91 +++- .../empire/jsf2/components/SelectTag.java | 110 ++++- .../empire/jsf2/components/TabPageTag.java | 92 ++++ .../empire/jsf2/components/TabViewTag.java | 387 ++++++++++++++++ .../jsf2/controls/CheckboxInputControl.java | 65 +-- .../empire/jsf2/controls/InputControl.java | 304 +++++++----- .../jsf2/controls/InputControlManager.java | 111 ++++- .../empire/jsf2/controls/RadioInputControl.java | 437 +++++++++++++++++ .../jsf2/controls/SelectInputControl.java | 252 +++++++--- .../jsf2/controls/TextAreaInputControl.java | 28 +- .../empire/jsf2/controls/TextInputControl.java | 359 ++++++++------ .../pageelements/StaticListPageElement.java | 2 +- .../java/org/apache/empire/jsf2/pages/Page.java | 24 +- .../apache/empire/jsf2/pages/PageOutcome.java | 6 +- .../empire/jsf2/pages/PagesELResolver.java | 2 +- .../apache/empire/jsf2/utils/SessionMap.java | 66 +++ .../empire/jsf2/utils/TagEncodingHelper.java | 227 ++++++--- .../java/org/apache/empire/data/Column.java | 20 + .../java/org/apache/empire/db/DBColumn.java | 26 +- .../org/apache/empire/db/DBTableColumn.java | 31 +- 39 files changed, 2904 insertions(+), 795 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-examples/empire-db-example-jsf2/pom.xml ---------------------------------------------------------------------- diff --git a/empire-db-examples/empire-db-example-jsf2/pom.xml b/empire-db-examples/empire-db-example-jsf2/pom.xml index 98f1131..fbf3328 100644 --- a/empire-db-examples/empire-db-example-jsf2/pom.xml +++ b/empire-db-examples/empire-db-example-jsf2/pom.xml @@ -50,7 +50,7 @@ - - - - - + + + + + + + + @@ -50,15 +54,24 @@ - - - - - + + + + + + - + + - + + + + + + + + http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/mitem.xhtml ---------------------------------------------------------------------- diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/mitem.xhtml b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/mitem.xhtml new file mode 100644 index 0000000..c7db84c --- /dev/null +++ b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/mitem.xhtml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/mlist.xhtml ---------------------------------------------------------------------- diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/mlist.xhtml b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/mlist.xhtml new file mode 100644 index 0000000..9e66b02 --- /dev/null +++ b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/mlist.xhtml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/select.xhtml ---------------------------------------------------------------------- diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/select.xhtml b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/select.xhtml new file mode 100644 index 0000000..dabc56b --- /dev/null +++ b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/select.xhtml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/tabPage.xhtml ---------------------------------------------------------------------- diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/tabPage.xhtml b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/tabPage.xhtml new file mode 100644 index 0000000..dcb22f2 --- /dev/null +++ b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/tabPage.xhtml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/tabView.xhtml ---------------------------------------------------------------------- diff --git a/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/tabView.xhtml b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/tabView.xhtml new file mode 100644 index 0000000..3979187 --- /dev/null +++ b/empire-db-examples/empire-db-example-jsf2/src/main/webapp/resources/empire/tabView.xhtml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java index 0afee55..0766b50 100644 --- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java @@ -51,8 +51,6 @@ import org.apache.empire.jsf2.impl.ResourceTextResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -// import com.sun.faces.application.ApplicationImpl; - public abstract class WebApplication { private static final Logger log = LoggerFactory.getLogger(WebApplication.class); @@ -67,7 +65,7 @@ public abstract class WebApplication private FacesImplementation facesImpl = null; - private static WebApplication appInstance = null; + private static WebApplication appInstance = null; public static WebApplication getInstance() { http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java index 91d82d8..3b5c4ec 100644 --- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/ControlTag.java @@ -26,6 +26,8 @@ import javax.faces.component.UIComponentBase; import javax.faces.component.UIInput; import javax.faces.component.UINamingContainer; import javax.faces.component.html.HtmlOutputLabel; +import javax.faces.component.visit.VisitCallback; +import javax.faces.component.visit.VisitContext; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; @@ -44,7 +46,7 @@ public class ControlTag extends UIInput implements NamingContainer public static String DEFAULT_CONTROL_SEPARATOR_TAG = "td"; public static String DEFAULT_LABEL_SEPARATOR_CLASS = "eCtlLabel"; public static String DEFAULT_INPUT_SEPARATOR_CLASS = "eCtlInput"; - + public static abstract class ControlSeparatorComponent extends javax.faces.component.UIComponentBase { private ControlTag control = null; @@ -60,49 +62,64 @@ public class ControlTag extends UIInput implements NamingContainer @Override public String getFamily() { - return UINamingContainer.COMPONENT_FAMILY; + return UINamingContainer.COMPONENT_FAMILY; } + /* + @Override + public String getClientId(FacesContext context) + { + String clientId = super.getClientId(context); + log.info("ControlSeparatorComponent-ID is {}", clientId); + // default behavior + return clientId; + } + */ + @Override public void encodeBegin(FacesContext context) throws IOException { super.encodeBegin(context); - + UIComponent parent = getParent(); if (!(parent instanceof ControlTag)) parent = parent.getParent(); if (!(parent instanceof ControlTag)) - { log.error("Invalid parent component for "+getClass().getName()); + { log.error("Invalid parent component for " + getClass().getName()); return; } - - control = (ControlTag)parent; + + this.control = (ControlTag) parent; } - - protected abstract void writeAttributes(ResponseWriter writer, TagEncodingHelper helper, String tagName) throws IOException; - + + protected abstract void writeAttributes(ResponseWriter writer, TagEncodingHelper helper, String tagName) + throws IOException; + @Override public boolean getRendersChildren() { return true; } - + @Override public void encodeChildren(FacesContext context) throws IOException { - if (control!=null) - { // write end tag - TagEncodingHelper helper = control.helper; + if (this.control != null) + { // write end tag + TagEncodingHelper helper = this.control.helper; String tagName = helper.getTagAttributeString("tag", "td"); - + // render components ResponseWriter writer = context.getResponseWriter(); writer.startElement(tagName, this); writeAttributes(writer, helper, tagName); // write children - super.encodeChildren(context); + if (control.helper.isVisible()) + super.encodeChildren(context); + else + log.debug("Field {} is not visible.", helper.getColumn().getName()); // end writer.endElement(tagName); } @@ -112,10 +129,10 @@ public class ControlTag extends UIInput implements NamingContainer public static class LabelSeparatorComponent extends ControlSeparatorComponent { @Override - protected void writeAttributes(ResponseWriter writer, TagEncodingHelper helper, String tagName) + protected void writeAttributes(ResponseWriter writer, TagEncodingHelper helper, String tagName) throws IOException { - String styleClass = helper.getTagAttributeString("labelClass", DEFAULT_LABEL_SEPARATOR_CLASS); + String styleClass = helper.getTagAttributeString("labelClass", ControlTag.DEFAULT_LABEL_SEPARATOR_CLASS); if (StringUtils.isNotEmpty(styleClass)) writer.writeAttribute("class", styleClass, null); } @@ -124,18 +141,21 @@ public class ControlTag extends UIInput implements NamingContainer public static class InputSeparatorComponent extends ControlSeparatorComponent { @Override - protected void writeAttributes(ResponseWriter writer, TagEncodingHelper helper, String tagName) + protected void writeAttributes(ResponseWriter writer, TagEncodingHelper helper, String tagName) throws IOException { - String styleClass = helper.getTagAttributeString("inputClass", DEFAULT_INPUT_SEPARATOR_CLASS); + String styleClass = helper.getTagAttributeString("inputClass", ControlTag.DEFAULT_INPUT_SEPARATOR_CLASS); + // styleClass if (StringUtils.isNotEmpty(styleClass)) writer.writeAttribute("class", styleClass, null); + // colspan String colSpan = helper.getTagAttributeString("colspan"); if (StringUtils.isNotEmpty(colSpan) && tagName.equalsIgnoreCase("td")) writer.writeAttribute("colspan", colSpan, null); } + } - + public static class ValueOutputComponent extends javax.faces.component.UIComponentBase { private final String tagName = "span"; @@ -151,63 +171,64 @@ public class ControlTag extends UIInput implements NamingContainer @Override public String getFamily() { - return UINamingContainer.COMPONENT_FAMILY; + return UINamingContainer.COMPONENT_FAMILY; } - + @Override public void encodeBegin(FacesContext context) throws IOException { super.encodeBegin(context); - + UIComponent parent = getParent(); if (!(parent instanceof ControlTag)) parent = parent.getParent(); if (!(parent instanceof ControlTag)) parent = parent.getParent(); if (!(parent instanceof ControlTag)) - { log.error("Invalid parent component for "+getClass().getName()); + { log.error("Invalid parent component for " + getClass().getName()); return; } - - ControlTag controlTag = (ControlTag)parent; + + ControlTag controlTag = (ControlTag) parent; InputControl control = controlTag.control; InputControl.ValueInfo valInfo = controlTag.inpInfo; TagEncodingHelper helper = controlTag.helper; - if (control==null) + if (control == null) control = helper.getInputControl(); // Oops, should not come here - if (valInfo==null) + if (valInfo == null) valInfo = helper.getValueInfo(context); // Oops, should not come here - + String styleClass = helper.getTagStyleClass("eInpDis"); - String tooltip = helper.getValueTooltip(helper.getTagAttributeString("title")); - + String tooltip = helper.getValueTooltip(helper.getTagAttributeString("title")); + // render components ResponseWriter writer = context.getResponseWriter(); - writer.startElement(tagName, this); + writer.startElement(this.tagName, this); if (StringUtils.isNotEmpty(styleClass)) writer.writeAttribute("class", styleClass, null); if (StringUtils.isNotEmpty(tooltip)) writer.writeAttribute("title", tooltip, null); // render Value control.renderValue(valInfo, writer); - writer.endElement(tagName); + writer.endElement(this.tagName); } } - + // Logger - private static final Logger log = LoggerFactory.getLogger(ControlTag.class); + private static final Logger log = LoggerFactory.getLogger(ControlTag.class); - private static final String readOnlyState = "readOnlyState"; - - private static final boolean encodeLabel = true; + private static final String readOnlyState = "readOnlyState"; + + private static final boolean encodeLabel = true; - protected final TagEncodingHelper helper = new TagEncodingHelper(this, "eInput"); + protected final TagEncodingHelper helper = new TagEncodingHelper(this, "eInput"); - protected InputControl control = null; - protected InputControl.InputInfo inpInfo = null; - protected boolean hasRequiredFlagSet = false; + protected InputControl control = null; + protected InputControl.InputInfo inpInfo = null; + protected boolean hasRequiredFlagSet = false; + private boolean creatingComponents = false; public ControlTag() { @@ -224,22 +245,51 @@ public class ControlTag extends UIInput implements NamingContainer { // getStateHelper().put(inpControlPropName, control); // getStateHelper().put(inputInfoPropName, inpInfo); - getStateHelper().put(readOnlyState, (inpInfo==null)); + getStateHelper().put(ControlTag.readOnlyState, (this.inpInfo == null)); } private boolean initState(FacesContext context) { - // Check visibility - if (helper.isVisible()==false) - return false; // not visible // Check read-Only - Boolean ros = (Boolean)getStateHelper().get(readOnlyState); - if (ros!=null && ros.booleanValue()) + Boolean ros = (Boolean) getStateHelper().get(ControlTag.readOnlyState); + if (ros != null && ros.booleanValue()) return false; + // Must have children + if (getChildCount() == 0) + { log.warn("InputTag has no children! Unable to init Input state for id={}", getClientId()); + log.warn("Problem might be related to Mojarra's state context saving for dynamic components (affects all versions > 2.1.6). See com.sun.faces.context.StateContext.java:AddRemoveListener"); + return false; + } // control = ; - control = helper.getInputControl(); - inpInfo = helper.getInputInfo(context); - return (control!=null && inpInfo!=null); + this.control = helper.getInputControl(); + this.inpInfo = helper.getInputInfo(context); + return (this.control != null && this.inpInfo != null); + } + + /** + * remember original clientId + * necessary only inside UIData + */ + private String treeClientId = null; + + @Override + public boolean visitTree(VisitContext visitContext, VisitCallback callback) + { + FacesContext context = visitContext.getFacesContext(); + treeClientId = this.getClientId(context); + return super.visitTree(visitContext, callback); + } + + @Override + public String getClientId(FacesContext context) + { + // Check if dynamic components are being created + if (this.treeClientId!=null && (this.creatingComponents || this.control!=null && this.control.isCreatingComponents())) + { // return the original tree client id + return treeClientId; + } + // default behavior + return super.getClientId(context); } @Override @@ -249,79 +299,78 @@ public class ControlTag extends UIInput implements NamingContainer // add label and input components when the view is loaded for the first time super.encodeBegin(context); - // Check visiblity - if (helper.isVisible()==false) - { setRendered(false); - return; // not visible - } - // init helper.encodeBegin(); - control = helper.getInputControl(); - + this.control = helper.getInputControl(); + boolean isCustomInput = isCustomInput(); - + // create children - if (encodeLabel) + if (ControlTag.encodeLabel) { // Create Label Separator Tag - ControlSeparatorComponent labelSepTag = null; + ControlSeparatorComponent labelSepTag = null; if (getChildCount() > 0) labelSepTag = (ControlSeparatorComponent) getChildren().get(0); if (labelSepTag == null) - { labelSepTag = new LabelSeparatorComponent(); - getChildren().add(labelSepTag); + { try { + creatingComponents = true; + labelSepTag = new LabelSeparatorComponent(); + getChildren().add(labelSepTag); + helper.resetComponentId(labelSepTag); + } finally { + creatingComponents = false; + } } labelSepTag.setRendered(true); encodeLabel(context, labelSepTag); if (isCustomInput) - { // don't render twice! + { // don't render twice! labelSepTag.setRendered(false); - } - } + } + } if (!isCustomInput) { // Create Input Separator Tag - ControlSeparatorComponent inputSepTag = null; + ControlSeparatorComponent inputSepTag = null; if (getChildCount() > 1) inputSepTag = (ControlSeparatorComponent) getChildren().get(1); if (inputSepTag == null) - { inputSepTag = new InputSeparatorComponent(); - getChildren().add(inputSepTag); + { try { + creatingComponents = true; + inputSepTag = new InputSeparatorComponent(); + getChildren().add(inputSepTag); + helper.resetComponentId(inputSepTag); + } finally { + creatingComponents = false; + } } encodeInput(context, inputSepTag); } - - /* - ResponseWriter writer = context.getResponseWriter(); - writer.startElement("td", this); - writer.write("hello world!"); - writer.endElement("td"); - - if (!isCustomInput()) - { - writer.startElement("td", this); - encodeInput(context, this); - writer.endElement("td"); - } - */ - + // done saveState(); } - + @Override public boolean getRendersChildren() { return true; } - - @Override - public void encodeChildren(FacesContext context) - throws IOException + + @Override + public void encodeChildren(FacesContext context) + throws IOException { - if (isCustomInput()) + super.encodeChildren(context); + } + + @Override + public void encodeEnd(FacesContext context) + throws IOException + { + if (isRendered() && isCustomInput()) // MyFaces Patch! { - String tagName = helper.getTagAttributeString("tag", DEFAULT_CONTROL_SEPARATOR_TAG); - String inpClass = helper.getTagAttributeString("inputClass", DEFAULT_INPUT_SEPARATOR_CLASS); + String tagName = helper.getTagAttributeString("tag", ControlTag.DEFAULT_CONTROL_SEPARATOR_TAG); + String inpClass = helper.getTagAttributeString("inputClass", ControlTag.DEFAULT_INPUT_SEPARATOR_CLASS); String colSpan = helper.getTagAttributeString("colspan"); ResponseWriter writer = context.getResponseWriter(); @@ -331,27 +380,66 @@ public class ControlTag extends UIInput implements NamingContainer if (StringUtils.isNotEmpty(colSpan) && tagName.equalsIgnoreCase("td")) writer.writeAttribute("colspan", colSpan, null); // encode children - super.encodeChildren(context); + super.encodeEnd(context); // end of element writer.endElement(tagName); - } + } + else + { // default + super.encodeEnd(context); + } + } + + @Override + public void setId(String id) + { + super.setId(id); + // reset record + helper.setRecord(null); } @Override - public void encodeEnd(FacesContext context) - throws IOException + public void processDecodes(FacesContext context) { - super.encodeEnd(context); + if (helper.isInsideUIData()) + { // Check input controls + if (getChildCount()>1 && (getChildren().get(1) instanceof InputSeparatorComponent)) + { // Make sure all inputs are rendered + boolean hasChanged = false; + boolean readOnly = helper.isRecordReadOnly(); + InputSeparatorComponent parent = (InputSeparatorComponent)getChildren().get(1); + // set rendered of children + for (UIComponent child : parent.getChildren()) + { // set rendered + boolean rendered = (child instanceof ValueOutputComponent) ? readOnly : !readOnly; + if (child.isRendered()!=rendered) + { + child.setRendered(rendered); + hasChanged = true; + } + } + // give control chance to update + if (hasChanged && log.isDebugEnabled()) + log.debug("Changing UIInput readOnly state for {} to {}", helper.getColumnName(), readOnly); + if (this.control==null) + this.control = helper.getInputControl(); + if (this.inpInfo==null) + this.inpInfo = helper.getInputInfo(context); + this.control.updateInputState(parent, inpInfo, context); + } + } + // default + super.processDecodes(context); } @Override - public void setRequired(boolean required) + public void setRequired(boolean required) { super.setRequired(required); // flag has been set - hasRequiredFlagSet = true; + this.hasRequiredFlagSet = true; } - + public boolean isCustomInput() { Object custom = getAttributes().get("custom"); @@ -359,62 +447,71 @@ public class ControlTag extends UIInput implements NamingContainer return ObjectUtils.getBoolean(custom); return false; } - + private void encodeLabel(FacesContext context, UIComponentBase parent) throws IOException { // render components - HtmlOutputLabel labelComponent = null; - if (parent.getChildCount() > 0) - { - labelComponent = (HtmlOutputLabel) parent.getChildren().get(0); - // update - helper.updateLabelComponent(context, labelComponent, null); - } - if (labelComponent == null) - { - String forInput = isCustomInput() ? helper.getTagAttributeString("for") : "*"; - // createLabelComponent - labelComponent = helper.createLabelComponent(context, forInput, "eLabel", null, true); - parent.getChildren().add(0, labelComponent); + try { + creatingComponents = true; + HtmlOutputLabel labelComponent = null; + if (parent.getChildCount() > 0) + { + labelComponent = (HtmlOutputLabel) parent.getChildren().get(0); + // update + helper.updateLabelComponent(context, labelComponent, null); + } + if (labelComponent == null) + { + String forInput = isCustomInput() ? helper.getTagAttributeString("for") : "*"; + // createLabelComponent + labelComponent = helper.createLabelComponent(context, forInput, "eLabel", null, true); + parent.getChildren().add(0, labelComponent); + helper.resetComponentId(labelComponent); + } + } finally { + creatingComponents = false; } // render components parent.encodeAll(context); } - + private void encodeInput(FacesContext context, UIComponentBase parent) throws IOException { // render components - if (this.helper.isRecordReadOnly()) // && allowValueComponent(parent)) - { - UIComponent valueComp = (parent.getChildCount()>0 ? parent.getChildren().get(0) : null); - if (valueComp != null && !(valueComp instanceof ValueOutputComponent)) - { // remove InputComponent - parent.getChildren().clear(); - valueComp = null; - } + try { + creatingComponents = true; + // check children + int count = parent.getChildCount(); + boolean resetChildId = (count==0); + // continue + this.inpInfo = helper.getInputInfo(context); + // set required + if (this.hasRequiredFlagSet==false) + super.setRequired(helper.isValueRequired()); + // create Input Controls + // boolean recordReadOnly = helper.isRecordReadOnly(); + control.renderInput(parent, inpInfo, context, false); + // create Value Component + UIComponent valueComp = (count>0 ? parent.getChildren().get(count-1) : null); if (valueComp == null) - { + { // create ValueOutputComponent valueComp = new ValueOutputComponent(); parent.getChildren().add(valueComp); } - } - else - { // check for ValueOutputComponent - UIComponent valueComp = (parent.getChildCount()>0 ? parent.getChildren().get(0) : null); - if (valueComp instanceof ValueOutputComponent) - { // remove ValueOutputComponent - parent.getChildren().clear(); + // Walk through the list of controls + boolean readOnly = helper.isRecordReadOnly(); + for (UIComponent child : parent.getChildren()) + { // reset child-id + if (resetChildId) + helper.resetComponentId(child); + // set rendered + boolean rendered = (child instanceof ValueOutputComponent) ? readOnly : !readOnly; + child.setRendered(rendered); } - // continue - inpInfo = helper.getInputInfo(context); - // set required - if (hasRequiredFlagSet==false) - super.setRequired(helper.isValueRequired()); - // render input - control.renderInput(parent, inpInfo, context, false); - + } finally { + creatingComponents = false; } // render components parent.encodeAll(context); @@ -424,58 +521,58 @@ public class ControlTag extends UIInput implements NamingContainer public Object getValue() { // check for record - if (helper.getRecord()!=null) + if (helper.getRecord() != null) return helper.getDataValue(true); // default Object value = super.getValue(); - return value; + return value; } - + @Override public Object getSubmittedValue() - { // Check state - if (control==null || inpInfo==null || helper.isReadOnly()) + { // Check state + if (this.control == null || this.inpInfo == null || helper.isReadOnly()) return null; // Get Input Tag - if (getChildCount()<=1) + if (getChildCount() <= 1) return null; // get Input Value - ControlSeparatorComponent inputSepTag = (ControlSeparatorComponent) getChildren().get(1); - return control.getInputValue(inputSepTag, inpInfo, true); + ControlSeparatorComponent inputSepTag = (ControlSeparatorComponent) getChildren().get(1); + return this.control.getInputValue(inputSepTag, this.inpInfo, true); } @Override public void validateValue(FacesContext context, Object value) - { // Check state - if (inpInfo==null || !isValid()) + { // Check state + if (this.inpInfo == null || !isValid()) return; // Skip Null values on partial submit - if (isEmpty(value) && isPartialSubmit(context)) // && helper.isValueRequired() - { // Value is null - log.debug("Skipping validation for {} due to Null value.", inpInfo.getColumn().getName()); + if (UIInput.isEmpty(value) && isPartialSubmit(context)) // && helper.isValueRequired() + { // Value is null + log.debug("Skipping validation for {} due to Null value.", this.inpInfo.getColumn().getName()); return; } // Validate value - inpInfo.validate(value); + this.inpInfo.validate(value); setValid(true); // don't call base class! // super.validateValue(context, value); - } - + } + @Override public void validate(FacesContext context) { - if (initState(context)==false) + if (initState(context) == false) return; // get submitted value and validate if (log.isDebugEnabled()) - log.debug("Validating input for {}.", inpInfo.getColumn().getName()); + log.debug("Validating input for {}.", this.inpInfo.getColumn().getName()); // Validate value - try { - // Will internally call getSubmittedValue() and validateValue() + try + { // Will internally call getSubmittedValue() and validateValue() super.validate(context); - - } catch(Exception e) { + + } catch (Exception e) { // Value is not valid if (!(e instanceof EmpireException)) e = new FieldIllegalValueException(helper.getColumn(), "", e); @@ -488,39 +585,44 @@ public class ControlTag extends UIInput implements NamingContainer @Override public void updateModel(FacesContext context) { - if (initState(context)==false) + if (initState(context) == false) return; // No Action if (!isValid() || !isLocalValueSet()) - return; + return; // check required? Object value = getLocalValue(); // check required - if (isEmpty(value) && isPartialSubmit(context) && !helper.isTempoaryNullable()) - { // Value is null, but required - log.debug("Skipping model update for {} due to Null value.", inpInfo.getColumn().getName()); + if (UIInput.isEmpty(value) && isPartialSubmit(context) && !helper.isTempoaryNullable()) + { // Value is null, but required + log.debug("Skipping model update for {} due to Null value.", this.inpInfo.getColumn().getName()); return; } // super.updateModel(context); - log.debug("Updating model input for {}.", inpInfo.getColumn().getName()); - inpInfo.setValue(value); + log.debug("Updating model input for {}.", this.inpInfo.getColumn().getName()); + this.inpInfo.setValue(value); setValue(null); setLocalValueSet(false); // Post update - ControlSeparatorComponent inputSepTag = (ControlSeparatorComponent) getChildren().get(1); - control.postUpdateModel(inputSepTag, inpInfo, context); + ControlSeparatorComponent inputSepTag = (ControlSeparatorComponent) getChildren().get(1); + this.control.postUpdateModel(inputSepTag, this.inpInfo, context); } - + + public InputControl getInputControl() + { + return this.control; + } + public Column getInputColumn() { return helper.getColumn(); } - + public boolean isInputReadOnly() { return helper.isRecordReadOnly(); } - + public boolean isInputRequired() { return helper.isValueRequired(); @@ -529,20 +631,10 @@ public class ControlTag extends UIInput implements NamingContainer private boolean isPartialSubmit(FacesContext context) { // Check Required Flag - if (hasRequiredFlagSet && !isRequired()) + if (this.hasRequiredFlagSet && !isRequired()) return true; // partial return helper.isPartialSubmit(context); } - - /** - * Check the parent allows the creation of a if the ValueOutputComponent. - * This method should never return false. If it does, the method "helper.isRecordReadOnly()" does not return the same value for subsequent calls as when the component was first encoded. - * @param parent the parent tag - * @return true on success or false if the parent's first child is not a instance of ValueOutputComponent - private boolean allowValueComponent(UIComponentBase parent) - { - return (parent.getChildCount()>0 ? (parent.getChildren().get(0) instanceof ValueOutputComponent) : true); - } - */ + } http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java index 4bc5f9a..ac6270d 100644 --- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/InputTag.java @@ -23,6 +23,8 @@ import java.util.Map; import javax.faces.component.NamingContainer; import javax.faces.component.UIInput; +import javax.faces.component.visit.VisitCallback; +import javax.faces.component.visit.VisitContext; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; @@ -37,23 +39,23 @@ import org.slf4j.LoggerFactory; public class InputTag extends UIInput implements NamingContainer { // Logger - private static final Logger log = LoggerFactory.getLogger(InputTag.class); - + private static final Logger log = LoggerFactory.getLogger(InputTag.class); + // private static final String inpControlPropName = InputControl.class.getSimpleName(); // private static final String inputInfoPropName = InputControl.InputInfo.class.getSimpleName(); - private static final String readOnlyState = "readOnlyState"; + private static final String readOnlyState = "readOnlyState"; - protected final TagEncodingHelper helper = new TagEncodingHelper(this, "eInput"); + private final TagEncodingHelper helper = new TagEncodingHelper(this, "eInput"); - private InputControl control = null; - private InputControl.InputInfo inpInfo = null; - protected boolean hasRequiredFlagSet = false; + private InputControl control = null; + private InputControl.InputInfo inpInfo = null; + protected boolean hasRequiredFlagSet = false; /* private static int itemIdSeq = 0; private final int itemId; */ - + public InputTag() { super(); @@ -62,7 +64,7 @@ public class InputTag extends UIInput implements NamingContainer itemId = ++itemIdSeq; if (log.isDebugEnabled()) log.debug("InputTag {} created", itemId); - */ + */ } @Override @@ -75,28 +77,54 @@ public class InputTag extends UIInput implements NamingContainer { // getStateHelper().put(inpControlPropName, control); // getStateHelper().put(inputInfoPropName, inpInfo); - getStateHelper().put(readOnlyState, (inpInfo==null)); + getStateHelper().put(readOnlyState, (inpInfo == null)); } private boolean initState(FacesContext context) { // Check visibility - if (helper.isVisible()==false) + if (helper.isVisible() == false) return false; // not visible // Read only State - Boolean ros = (Boolean)getStateHelper().get(readOnlyState); - if (ros!=null && ros.booleanValue()) + Boolean ros = (Boolean) getStateHelper().get(readOnlyState); + if (ros != null && ros.booleanValue()) return false; // Must have children - if (getChildCount()==0) - { log.warn("InputTag has no children! Unable to init Input state."); - log.warn("Problem might be related to Mojarra 2.1.7 to 2.1.11 (and possibly later) - please use Mojarra 2.1.6!"); + if (getChildCount() == 0) + { log.warn("InputTag has no children! Unable to init Input state for id={}", getClientId()); + log.warn("Problem might be related to Mojarra's state context saving for dynamic components (affects all versions > 2.1.6). See com.sun.faces.context.StateContext.java:AddRemoveListener"); return false; } // Init Control and inputInfo; control = helper.getInputControl(); inpInfo = helper.getInputInfo(context); - return (control!=null && inpInfo!=null); + return (control != null && inpInfo != null); + } + + /** + * remember original clientId + * necessary only inside UIData + */ + private String treeClientId = null; + + @Override + public boolean visitTree(VisitContext visitContext, VisitCallback callback) + { + FacesContext context = visitContext.getFacesContext(); + treeClientId = getClientId(context); + return super.visitTree(visitContext, callback); + } + + @Override + public String getClientId(FacesContext context) + { + // Check if dynamic components are being created + if (this.treeClientId!=null && control!=null && control.isCreatingComponents()) + { // return the original tree client id + return treeClientId; + } + // default behavior + return super.getClientId(context); } @Override @@ -107,15 +135,15 @@ public class InputTag extends UIInput implements NamingContainer super.encodeBegin(context); // Check visiblity - if (helper.isVisible()==false) + if (helper.isVisible() == false) { setRendered(false); return; // not visible } - + // init helper.encodeBegin(); control = helper.getInputControl(); - + // render components if (helper.isRecordReadOnly()) { @@ -130,16 +158,46 @@ public class InputTag extends UIInput implements NamingContainer { inpInfo = helper.getInputInfo(context); // set required - if (hasRequiredFlagSet==false) + if (hasRequiredFlagSet == false) super.setRequired(helper.isValueRequired()); // render input control.renderInput(this, inpInfo, context, true); } saveState(); } + + @Override + public void setId(String id) + { + super.setId(id); + // reset record + helper.setRecord(null); + } + + /* + @Override + public void processDecodes(FacesContext context) + { + if (helper.isInsideUIData()) + { // Check input controls + if (getChildCount()>0) + { // Change readOnly and disabled too + boolean readOnly = helper.isRecordReadOnly(); + log.info("Changing UIInput readOnly state for {} to {}", helper.getColumnName(), readOnly); + if (control==null) + control = helper.getInputControl(); + if (inpInfo==null) + inpInfo = helper.getInputInfo(context); + control.updateInputState(this, inpInfo, context); + } + } + // default + super.processDecodes(context); + } + */ @Override - public void setRequired(boolean required) + public void setRequired(boolean required) { super.setRequired(required); // flag has been set @@ -150,17 +208,17 @@ public class InputTag extends UIInput implements NamingContainer public Object getValue() { // check for record - if (helper.getRecord()!=null) + if (helper.getRecord() != null) return helper.getDataValue(true); // default - Object value = super.getValue(); - return value; + Object value = super.getValue(); + return value; } @Override public Object getSubmittedValue() - { // Check state - if (control==null || inpInfo==null || helper.isReadOnly()) + { // Check state + if (control == null || inpInfo == null || helper.isReadOnly()) return null; // get Input Value return control.getInputValue(this, inpInfo, true); @@ -168,12 +226,12 @@ public class InputTag extends UIInput implements NamingContainer @Override public void validateValue(FacesContext context, Object value) - { // Check state - if (inpInfo==null) + { // Check state + if (inpInfo == null) return; // Skip Null values if not required - if (isEmpty(value) && isPartialSubmit(context)) // && helper.isValueRequired() - { // Value is null + if (UIInput.isEmpty(value) && isPartialSubmit(context)) // && helper.isValueRequired() + { // Value is null log.debug("Skipping validation for {} due to Null value.", inpInfo.getColumn().getName()); return; } @@ -182,23 +240,23 @@ public class InputTag extends UIInput implements NamingContainer setValid(true); // don't call base class! // super.validateValue(context, value); - } - + } + @Override public void validate(FacesContext context) { - if (initState(context)==false) + if (initState(context) == false) return; // get submitted value and validate if (log.isDebugEnabled()) log.debug("Validating input for {}.", inpInfo.getColumn().getName()); - + // Validate value - try { - // Will internally call getSubmittedValue() and validateValue() + try + { // Will internally call getSubmittedValue() and validateValue() super.validate(context); - } catch(Exception e) { + } catch (Exception e) { // Value is not valid if (!(e instanceof EmpireException)) e = new FieldIllegalValueException(helper.getColumn(), "", e); @@ -211,15 +269,15 @@ public class InputTag extends UIInput implements NamingContainer @Override public void updateModel(FacesContext context) { - if (initState(context)==false) + if (initState(context) == false) return; // No Action if (!isValid() || !isLocalValueSet()) - return; + return; // check required Object value = getLocalValue(); - if (isEmpty(value) && isPartialSubmit(context) && !helper.isTempoaryNullable()) - { // Value is null, but required + if (UIInput.isEmpty(value) && isPartialSubmit(context) && !helper.isTempoaryNullable()) + { // Value is null, but required log.debug("Skipping model update for {} due to Null value.", inpInfo.getColumn().getName()); return; } @@ -231,17 +289,17 @@ public class InputTag extends UIInput implements NamingContainer // Post update control.postUpdateModel(this, inpInfo, context); } - + public Column getInputColumn() { return helper.getColumn(); } - + public boolean isInputReadOnly() { return helper.isRecordReadOnly(); } - + public boolean isInputRequired() { return helper.isValueRequired(); @@ -258,6 +316,7 @@ public class InputTag extends UIInput implements NamingContainer /** * write value element + * * @param vi * @param writer * @return http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LabelTag.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LabelTag.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LabelTag.java index f276b78..6e93ca3 100644 --- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LabelTag.java +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LabelTag.java @@ -20,8 +20,11 @@ package org.apache.empire.jsf2.components; import java.io.IOException; +import javax.faces.component.NamingContainer; import javax.faces.component.UIOutput; import javax.faces.component.html.HtmlOutputLabel; +import javax.faces.component.visit.VisitCallback; +import javax.faces.component.visit.VisitContext; import javax.faces.context.FacesContext; import org.apache.empire.commons.ObjectUtils; @@ -30,13 +33,15 @@ import org.apache.empire.jsf2.utils.TagEncodingHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class LabelTag extends UIOutput // implements NamingContainer +public class LabelTag extends UIOutput implements NamingContainer { // Logger private static final Logger log = LoggerFactory.getLogger(LabelTag.class); - protected final TagEncodingHelper helper = new TagEncodingHelper(this, "eLabel"); + private final TagEncodingHelper helper = new TagEncodingHelper(this, "eLabel"); + private boolean creatingComponents = false; + public LabelTag() { log.trace("component LabelTag created"); @@ -47,6 +52,32 @@ public class LabelTag extends UIOutput // implements NamingContainer { return "javax.faces.NamingContainer"; } + + /** + * remember original clientId + * necessary only inside UIData + */ + private String treeClientId = null; + + @Override + public boolean visitTree(VisitContext visitContext, VisitCallback callback) + { + FacesContext context = visitContext.getFacesContext(); + treeClientId = this.getClientId(context); + return super.visitTree(visitContext, callback); + } + + @Override + public String getClientId(FacesContext context) + { + // Check if dynamic components are being created + if (this.treeClientId!=null && this.creatingComponents) + { // return the original tree client id + return treeClientId; + } + // default behavior + return super.getClientId(context); + } @Override public void encodeBegin(FacesContext context) @@ -65,14 +96,19 @@ public class LabelTag extends UIOutput // implements NamingContainer helper.updateLabelComponent(context, labelComponent, forInput); } if (labelComponent == null) - { - String forInput = helper.getTagAttributeString("for"); - String styleClass = helper.getTagStyleClass(DataType.UNKNOWN, null); - String style = helper.getTagAttributeString("style"); - // createLabelComponent - labelComponent = helper.createLabelComponent(context, forInput, styleClass, style, getColon()); - this.getChildren().add(labelComponent); - } + { try { + creatingComponents = true; + String forInput = helper.getTagAttributeString("for"); + String styleClass = helper.getTagStyleClass(DataType.UNKNOWN, null); + String style = helper.getTagAttributeString("style"); + // createLabelComponent + labelComponent = helper.createLabelComponent(context, forInput, styleClass, style, getColon()); + this.getChildren().add(labelComponent); + helper.resetComponentId(labelComponent); + } finally { + creatingComponents = false; + } + } // render components labelComponent.encodeAll(context); http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LinkTag.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LinkTag.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LinkTag.java index 1c04306..e0f88f0 100644 --- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LinkTag.java +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/LinkTag.java @@ -27,7 +27,10 @@ import javax.faces.component.UINamingContainer; import javax.faces.component.UIOutput; import javax.faces.component.UIPanel; import javax.faces.component.UIParameter; +import javax.faces.component.html.HtmlGraphicImage; import javax.faces.component.html.HtmlOutcomeTargetLink; +import javax.faces.component.visit.VisitCallback; +import javax.faces.component.visit.VisitContext; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; @@ -35,6 +38,7 @@ import org.apache.empire.commons.ObjectUtils; import org.apache.empire.commons.StringUtils; import org.apache.empire.data.DataType; import org.apache.empire.jsf2.controls.InputControl; +import org.apache.empire.jsf2.controls.InputControlManager; import org.apache.empire.jsf2.utils.StringResponseWriter; import org.apache.empire.jsf2.utils.TagEncodingHelper; import org.slf4j.Logger; @@ -58,6 +62,8 @@ public class LinkTag extends UIOutput // implements NamingContainer protected final TagEncodingHelper helper = new TagEncodingHelper(this, "eLink"); + private boolean creatingComponents = false; + public LinkTag() { log.trace("component link created"); @@ -68,6 +74,32 @@ public class LinkTag extends UIOutput // implements NamingContainer { return UINamingContainer.COMPONENT_FAMILY; } + + /** + * remember original clientId + * necessary only inside UIData + */ + private String treeClientId = null; + + @Override + public boolean visitTree(VisitContext visitContext, VisitCallback callback) + { + FacesContext context = visitContext.getFacesContext(); + treeClientId = this.getClientId(context); + return super.visitTree(visitContext, callback); + } + + @Override + public String getClientId(FacesContext context) + { + // Check if dynamic components are being created + if (this.treeClientId!=null && this.creatingComponents) + { // return the original tree client id + return treeClientId; + } + // default behavior + return super.getClientId(context); + } @Override public void encodeBegin(FacesContext context) @@ -93,7 +125,18 @@ public class LinkTag extends UIOutput // implements NamingContainer { UIComponent c = getChildren().get(0); if (c instanceof HtmlOutcomeTargetLink) + { // reuse linkComponent = (HtmlOutcomeTargetLink)c; + helper.restoreComponentId(linkComponent); + // check image + if (linkComponent.getChildCount()>0) + { // Check HtmlGraphicImage + int last = linkComponent.getChildCount()-1; + UIComponent lcc = linkComponent.getChildren().get(last); + if (lcc instanceof HtmlGraphicImage) + helper.restoreComponentId(lcc); + } + } else { // Something's wrong here? log.info("INFO: Unexpected child node for {}! Child item type is {}.", getClass().getName(), c.getClass().getName()); @@ -102,7 +145,7 @@ public class LinkTag extends UIOutput // implements NamingContainer if (facetComponent==null) { log.warn("WARN: component's facetComponent has not been set! Using Default (javax.faces.Panel)."); - log.warn("Problem might be related to Mojarra 2.1.7 to 2.1.11 (and possibly later) - please use Mojarra 2.1.6!"); + log.warn("Problem might be related to Mojarra's state context saving for dynamic components (affects all versions > 2.1.6). See com.sun.faces.context.StateContext.java:AddRemoveListener"); facetComponent = (UIPanel)context.getApplication().createComponent("javax.faces.Panel"); facetComponent.setRendererType("javax.faces.Group"); getFacets().put(UIComponent.COMPOSITE_FACET_NAME, facetComponent); @@ -110,9 +153,23 @@ public class LinkTag extends UIOutput // implements NamingContainer } } if (linkComponent == null) - { - linkComponent = new HtmlOutcomeTargetLink(); - this.getChildren().add(0, linkComponent); + { try { + creatingComponents = true; + linkComponent = new HtmlOutcomeTargetLink(); + this.getChildren().add(0, linkComponent); + helper.saveComponentId(linkComponent); + // encode image + String imagePath = helper.getTagAttributeString("image"); + if (StringUtils.isNotEmpty(imagePath)) + { // Create image + HtmlGraphicImage img = encodeImage(context, linkComponent, imagePath); + linkComponent.getChildren().add(img); + helper.saveComponentId(linkComponent); + } + // done + } finally { + creatingComponents = false; + } } // set params setLinkProperties(linkComponent); @@ -166,6 +223,10 @@ public class LinkTag extends UIOutput // implements NamingContainer } else { // An ordinary link + String text = helper.getTagAttributeString("text"); + if (text!=null) + return helper.getTextResolver(FacesContext.getCurrentInstance()).resolveText(text); + // Use value Object value = getValue(); return value; } @@ -182,7 +243,8 @@ public class LinkTag extends UIOutput // implements NamingContainer // Set Attributes Map attr = getAttributes(); // Set outcome - String outcome = StringUtils.toString(attr.get("page")); + Object page = attr.get("page"); + String outcome = StringUtils.toString(page); link.setOutcome(outcome); // Copy attributes if ((value=attr.get("style"))!=null) @@ -191,6 +253,10 @@ public class LinkTag extends UIOutput // implements NamingContainer link.setTabindex(StringUtils.toString(value)); if ((value=attr.get("onclick"))!=null) link.setOnclick(StringUtils.toString(value)); + // title + String title = helper.getTagAttributeString("title"); + if (StringUtils.isNotEmpty(title)) + link.setTitle(title); // include view param link.setIncludeViewParams(false); } @@ -219,6 +285,7 @@ public class LinkTag extends UIOutput // implements NamingContainer param.setName(paramName); param.setValue(paramValue); link.getChildren().add(param); + helper.resetComponentId(param); } protected String writeStartElement(ResponseWriter writer) @@ -228,7 +295,7 @@ public class LinkTag extends UIOutput // implements NamingContainer String tagName = StringUtils.coalesce(StringUtils.toString(map.get("tag")), "span"); String cssClass = helper.getTagStyleClass(); Object style = map.get("style"); - Object title = map.get("title"); + Object title = helper.getTagAttributeValue("title"); // Write tag writer.startElement(tagName, this); helper.writeAttribute(writer, "class", cssClass); @@ -237,6 +304,13 @@ public class LinkTag extends UIOutput // implements NamingContainer return tagName; } + protected HtmlGraphicImage encodeImage(FacesContext context, HtmlOutcomeTargetLink parent, String imagePath) + { + HtmlGraphicImage img = InputControlManager.createComponent(context, HtmlGraphicImage.class); + img.setValue(imagePath); + return img; + } + /* * public String getLabelValue() * { http://git-wip-us.apache.org/repos/asf/empire-db/blob/9176b225/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/MenuItemTag.java ---------------------------------------------------------------------- diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/MenuItemTag.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/MenuItemTag.java index 4b2296e..b6982bd 100644 --- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/MenuItemTag.java +++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/components/MenuItemTag.java @@ -36,8 +36,8 @@ public class MenuItemTag extends LinkTag // Logger private static final Logger log = LoggerFactory.getLogger(MenuItemTag.class); - protected MenuListTag parentMenu = null; - protected String menuId; + private MenuListTag parentMenu = null; + private String menuId; /* private static int itemIdSeq = 0; @@ -67,7 +67,8 @@ public class MenuItemTag extends LinkTag { // Detect Parent Menu parentMenu = getParentMenu(); - menuId = StringUtils.toString(getAttributes().get("menuId")); + menuId = helper.getTagAttributeString("menuId"); + if(!isRendered()) return; @@ -75,11 +76,22 @@ public class MenuItemTag extends LinkTag ResponseWriter writer = context.getResponseWriter(); writer.startElement("li", this); writer.writeAttribute("id", getClientId(context), null); - writer.writeAttribute("class", getStyleClass(), null); - // writer.writeAttribute("item", String.valueOf(itemId), null); + helper.writeAttribute(writer, "class", getStyleClass()); + String wrap = (parentMenu!=null ? parentMenu.getItemWrapTag() : null); + if (StringUtils.isNotEmpty(wrap)) + { // Wrap-Element + writer.startElement(wrap, this); + // writer.writeAttribute("class", "item", null); + } + // begin super.encodeBegin(context); + + // End Wrapper + if (StringUtils.isNotEmpty(wrap)) + writer.endElement(wrap); + } @Override @@ -119,7 +131,7 @@ public class MenuItemTag extends LinkTag { super.encodeEnd(context); } - // end of list item + // EndElement ResponseWriter writer = context.getResponseWriter(); writer.endElement("li"); } @@ -165,10 +177,19 @@ public class MenuItemTag extends LinkTag // All present return menuId.equals(parentMenu.getCurrentId()); } + + private boolean isParent() + { + if (menuId==null || parentMenu==null || parentMenu.getCurrentId()==null) + return false; + // All present + String currentId = parentMenu.getCurrentId(); + return (currentId.length()>menuId.length() && currentId.startsWith(menuId)); + } private boolean isDisabled() { - Object value = getAttributes().get("disabled"); + Object value = helper.getTagAttributeValue("disabled"); if (value!=null) return ObjectUtils.getBoolean(value); return false; @@ -176,7 +197,7 @@ public class MenuItemTag extends LinkTag private boolean isExpanded() { - Object value = getAttributes().get("expanded"); + Object value = helper.getTagAttributeValue("expanded"); boolean auto = false; if (value!=null) { // is current? @@ -198,15 +219,15 @@ public class MenuItemTag extends LinkTag @Override public boolean isRendered() { - Object value = getAttributes().get("currentOnly"); + Object value = helper.getTagAttributeValue("currentOnly"); boolean currentOnly = false; - if(value!=null) + if (value!=null) currentOnly = ObjectUtils.getBoolean(value); // Check parent if (currentOnly && menuId!=null && parentMenu!=null && parentMenu.getCurrentId()!=null) { - return isCurrent(); + return isCurrent() || isParent(); } return super.isRendered(); @@ -214,7 +235,7 @@ public class MenuItemTag extends LinkTag private String getStyleClass() { - String styleClass = StringUtils.toString(getAttributes().get("styleClass")); + String styleClass = helper.getTagAttributeString("styleClass"); if (parentMenu!=null) { // Style Class @@ -223,8 +244,11 @@ public class MenuItemTag extends LinkTag // Menu Class if (isCurrent()) styleClass = appendStyleClass(styleClass, parentMenu.getCurrentClass()); - else if (isExpanded()) - styleClass = appendStyleClass(styleClass, parentMenu.getExpandedClass()); + else if (isParent()) + styleClass = appendStyleClass(styleClass, parentMenu.getParentClass()); + // expanded + if (isExpanded()) + styleClass = appendStyleClass(styleClass, parentMenu.getExpandedClass()); // Disabled / enabled if (isDisabled()) styleClass = appendStyleClass(styleClass, parentMenu.getDisabledClass());