Permalink
Browse files

#1633

  • Loading branch information...
1 parent 1252c88 commit f1787892a7b116dd752c279cd8d7dc20107cc967 @tandraschko tandraschko committed Feb 16, 2017
@@ -15,6 +15,7 @@
*/
package org.primefaces.component.outputlabel;
+import org.primefaces.util.EditableValueHolderState;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Level;
@@ -39,109 +40,119 @@
import org.primefaces.util.ComponentUtils;
import org.primefaces.util.CompositeUtils;
import org.primefaces.util.HTML;
+import org.primefaces.util.SharedStringBuilder;
public class OutputLabelRenderer extends CoreRenderer {
private static final Logger LOG = Logger.getLogger(OutputLabelRenderer.class.getName());
+ private static final String SB_STYLE_CLASS = OutputLabelRenderer.class.getName() + "#styleClass";
+
@Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
- ResponseWriter writer = context.getResponseWriter();
- OutputLabel label = (OutputLabel) component;
- String clientId = label.getClientId(context);
- String value = ComponentUtils.getValueToRender(context, label);
- UIComponent targetParent = null;
- UIComponent target = null;
- String targetClientId = null;
- UIInput input = null;
- String styleClass = label.getStyleClass();
- styleClass = styleClass == null ? OutputLabel.STYLE_CLASS : OutputLabel.STYLE_CLASS + " " + styleClass;
+ final ResponseWriter writer = context.getResponseWriter();
+ final OutputLabel label = (OutputLabel) component;
+ final String clientId = label.getClientId(context);
+ final String value = ComponentUtils.getValueToRender(context, label);
+
+ final StringBuilder styleClass = SharedStringBuilder.get(context, SB_STYLE_CLASS);
+ styleClass.append(OutputLabel.STYLE_CLASS);
+ if (label.getStyleClass() != null) {
+ styleClass.append(" ");
+ styleClass.append(label.getStyleClass());
+ }
+
+ final EditableValueHolderState state = new EditableValueHolderState();;
String _for = label.getFor();
-
- if(_for != null) {
- target = SearchExpressionFacade.resolveComponent(context, label, _for);
-
- if (CompositeUtils.isComposite(target)) {
- targetParent = target;
- target = CompositeUtils.extractDeepestEditableValueHolder(target);
- }
-
- if(target instanceof InputHolder) {
- InputHolder inputHolder = ((InputHolder) target);
- targetClientId = inputHolder.getInputClientId();
- inputHolder.setLabelledBy(clientId);
- }
- else {
- targetClientId = target.getClientId(context);
- }
-
- if(target instanceof UIInput) {
- input = (UIInput) target;
-
- if(value != null && (input.getAttributes().get("label") == null || input.getValueExpression("label") == null)) {
- ValueExpression ve = label.getValueExpression("value");
-
- if(ve != null) {
- input.setValueExpression("label", ve);
+ if (!isValueBlank(_for)) {
+ ContextCallback callback = new ContextCallback() {
+ @Override
+ public void invokeContextCallback(FacesContext context, UIComponent target) {
+ if (target instanceof InputHolder) {
+ InputHolder inputHolder = ((InputHolder) target);
+ state.setClientId(inputHolder.getInputClientId());
+
+ inputHolder.setLabelledBy(clientId);
}
else {
- String labelString = value;
- int colonPos = labelString.lastIndexOf(':');
-
- if(colonPos != -1) {
- labelString = labelString.substring(0, colonPos);
+ state.setClientId(target.getClientId(context));
+ }
+
+ if (target instanceof UIInput) {
+ UIInput input = (UIInput) target;
+
+ if (value != null && (input.getAttributes().get("label") == null || input.getValueExpression("label") == null)) {
+ ValueExpression ve = label.getValueExpression("value");
+
+ if(ve != null) {
+ input.setValueExpression("label", ve);
+ }
+ else {
+ String labelString = value;
+ int colonPos = labelString.lastIndexOf(':');
+
+ if(colonPos != -1) {
+ labelString = labelString.substring(0, colonPos);
+ }
+
+ input.getAttributes().put("label", labelString);
+ }
+ }
+
+ if (!input.isValid()) {
+ styleClass.append(" ui-state-error");
}
- input.getAttributes().put("label", labelString);
+ if (label.isIndicateRequired()) {
+ state.setRequired(input.isRequired());
+
+ // fallback if required=false
+ if (!state.isRequired()) {
+ PrimeConfiguration config = RequestContext.getCurrentInstance().getApplicationContext().getConfig();
+ if (config.isBeanValidationAvailable() && isNotNullDefined(input, context)) {
+ state.setRequired(true);
+ }
+ }
+ }
}
}
-
- if(!input.isValid()) {
- styleClass = styleClass + " ui-state-error";
- }
+ };
+
+ UIComponent forComponent = SearchExpressionFacade.resolveComponent(context, label, _for);
+
+ if (CompositeUtils.isComposite(forComponent)) {
+ CompositeUtils.invokeOnDeepestEditableValueHolder(context, forComponent, callback);
+ }
+ else {
+ callback.invokeContextCallback(context, forComponent);
}
}
writer.startElement("label", label);
writer.writeAttribute("id", clientId, "id");
- writer.writeAttribute("class", styleClass, "id");
+ writer.writeAttribute("class", styleClass.toString(), "id");
renderPassThruAttributes(context, label, HTML.LABEL_ATTRS);
- if(target != null) {
- writer.writeAttribute("for", targetClientId, "for");
+ if (!isValueBlank(_for)) {
+ writer.writeAttribute("for", state.getClientId(), "for");
}
- if(value != null) {
- if(label.isEscape())
+ if (value != null) {
+ if (label.isEscape()) {
writer.writeText(value, "value");
- else
+ }
+ else {
writer.write(value);
+ }
}
renderChildren(context, label);
- if (input != null && label.isIndicateRequired()) {
-
- PrimeConfiguration config = RequestContext.getCurrentInstance().getApplicationContext().getConfig();
-
- boolean required = false;
- if(targetParent != null) {
- RequiredContextCallBack requiredCallBack = new RequiredContextCallBack();
- targetParent.invokeOnComponent(context, input.getClientId(), requiredCallBack);
- required = requiredCallBack.isRequired();
- } else {
- required = input.isRequired();
- }
-
- if (required) {
- encodeRequiredIndicator(writer, label);
- }
- else if (config.isBeanValidationAvailable() && isNotNullDefined(input, context)) {
- encodeRequiredIndicator(writer, label);
- }
+ if (!isValueBlank(_for) && label.isIndicateRequired() && state.isRequired()) {
+ encodeRequiredIndicator(writer, label);
}
-
+
writer.endElement("label");
}
@@ -190,18 +201,4 @@ public void encodeChildren(FacesContext context, UIComponent component) throws I
public boolean getRendersChildren() {
return true;
}
-
- private static class RequiredContextCallBack implements ContextCallback {
-
- private boolean required;
-
- @Override
- public void invokeContextCallback(FacesContext context, UIComponent target) {
- required = target instanceof UIInput ? ((UIInput)target).isRequired() : false;
- }
-
- public boolean isRequired() {
- return required;
- }
- }
}
@@ -1,20 +1,55 @@
+/*
+ * Copyright 2009-2017 PrimeTek.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.primefaces.util;
import java.beans.BeanInfo;
import java.util.List;
import javax.faces.FacesException;
+import javax.faces.component.ContextCallback;
import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
import javax.faces.view.AttachedObjectTarget;
import javax.faces.view.EditableValueHolderAttachedObjectTarget;
public class CompositeUtils {
- public static boolean isComposite(UIComponent component)
- {
+ static class EditableValueHolderCallbackWrapper implements ContextCallback {
+ private final ContextCallback callback;
+
+ public EditableValueHolderCallbackWrapper(ContextCallback callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void invokeContextCallback(FacesContext context, UIComponent target) {
+ if (isComposite(target)) {
+ invokeOnEditableValueHolder(context, target, this);
+ }
+ else {
+ callback.invokeContextCallback(context, target);
+ }
+ }
+ }
+
+ public static boolean isComposite(UIComponent component) {
return UIComponent.isCompositeComponent(component);
}
- public static UIComponent extractEditableValueHolder(UIComponent composite) {
+ public static void invokeOnEditableValueHolder(FacesContext context, UIComponent composite,
+ ContextCallback callback) {
BeanInfo info = (BeanInfo) composite.getAttributes().get(UIComponent.BEANINFO_KEY);
List<AttachedObjectTarget> targets = (List<AttachedObjectTarget>) info.getBeanDescriptor()
.getValue(AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY);
@@ -28,28 +63,15 @@ public static UIComponent extractEditableValueHolder(UIComponent composite) {
+ "\" in composite component with id: \"" + composite.getClientId() + "\"");
}
- return children;
+ ComponentTraversalUtils.closestNamingContainer(composite)
+ .invokeOnComponent(context, children.getClientId(context), callback);
}
}
-
- return null;
}
-
- /**
- * Gets the deepest <code>EditableValueHolder</code> component contained in parent composite parameter.
- * If not defined, returns parent parameter. Otherwise the deepest <code>EditableValueHolder</code>.
- *
- * @param component root component
- * @return the deepest <code>EditableValueHolder</code> component if any, otherwise the source component.
- */
- public static UIComponent extractDeepestEditableValueHolder(UIComponent component) {
- UIComponent deepest = component;
-
- if (UIComponent.isCompositeComponent(component)) {
- deepest = extractEditableValueHolder(deepest);
- deepest = extractDeepestEditableValueHolder(deepest);
- }
- return deepest;
+ public static void invokeOnDeepestEditableValueHolder(FacesContext context, UIComponent composite,
+ ContextCallback callback) {
+ EditableValueHolderCallbackWrapper callbackWrapper = new EditableValueHolderCallbackWrapper(callback);
+ invokeOnEditableValueHolder(context, composite, callbackWrapper);
}
}
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009-2017 PrimeTek.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.primefaces.util;
+
+public class EditableValueHolderState {
+
+ private String clientId;
+ private boolean valid;
+ private boolean required;
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public boolean isValid() {
+ return valid;
+ }
+
+ public void setValid(boolean valid) {
+ this.valid = valid;
+ }
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ public void setRequired(boolean required) {
+ this.required = required;
+ }
+}

0 comments on commit f178789

Please sign in to comment.