View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.facelets.extension;
21  
22  import org.apache.myfaces.tobago.component.Attributes;
23  import org.apache.myfaces.tobago.component.InputSuggest;
24  import org.apache.myfaces.tobago.component.LabelLayout;
25  import org.apache.myfaces.tobago.component.OnComponentPopulated;
26  import org.apache.myfaces.tobago.component.Visual;
27  import org.apache.myfaces.tobago.facelets.SuggestMethodRule;
28  import org.apache.myfaces.tobago.facelets.SupportsMarkupRule;
29  import org.apache.myfaces.tobago.facelets.TobagoComponentHandler;
30  import org.apache.myfaces.tobago.internal.util.Deprecation;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  
34  import javax.el.ELException;
35  import javax.faces.application.Application;
36  import javax.faces.component.EditableValueHolder;
37  import javax.faces.component.UIComponent;
38  import javax.faces.view.facelets.ComponentConfig;
39  import javax.faces.view.facelets.ComponentHandler;
40  import javax.faces.view.facelets.FaceletContext;
41  import javax.faces.view.facelets.MetaRuleset;
42  import javax.faces.view.facelets.Metadata;
43  import javax.faces.view.facelets.TagAttribute;
44  import java.io.IOException;
45  
46  /**
47   * @deprecated since Tobago 3.0. The tx-library is deprecated, please use the tc-library.
48   */
49  @Deprecated
50  public abstract class TobagoLabelExtensionHandler extends ComponentHandler {
51  
52    private static final Logger LOG = LoggerFactory.getLogger(TobagoLabelExtensionHandler.class);
53  
54    private TagAttribute fieldIdAttribute;
55    private Class subComponentLastType = Object.class;
56    private Metadata subComponentMapper;
57  
58    public TobagoLabelExtensionHandler(final ComponentConfig config) {
59      super(config);
60      fieldIdAttribute = getAttribute(Attributes.fieldId.getName());
61    }
62  
63    protected abstract String getSubComponentType();
64  
65    protected abstract String getSubRendererType();
66  
67    @Override
68    public void applyNextHandler(final FaceletContext ctx, final UIComponent panel)
69        throws IOException, ELException {
70      if (ComponentHandler.isNew(panel)) {
71        Deprecation.LOG.warn("The tx library is deprecated, please use the tc library. "
72            + "See 'Migration to 3.0' on the web site.");
73        // ensure that input has no parent (isNew)
74        final UIComponent input = panel.getChildren().remove(0);
75        try {
76          input.getAttributes().put("tobago.panel", panel);
77          nextHandler.apply(ctx, input);
78        } finally {
79          input.getAttributes().remove("tobago.panel");
80        }
81        UIComponent date = null;
82        if (panel.getChildCount() > 1) {
83          date = panel.getChildren().get(0);
84        }
85        panel.getChildren().add(input);
86        if (date != null) {
87          panel.getChildren().add(date);
88        }
89      } else {
90        final UIComponent input = panel.getChildren().get(0);
91        nextHandler.apply(ctx, input);
92      }
93    }
94  
95    @Override
96    public void onComponentCreated(
97        final FaceletContext faceletContext, final UIComponent panel, final UIComponent parent) {
98  
99      final Application application = faceletContext.getFacesContext().getApplication();
100 
101     final String uid;
102     if (fieldIdAttribute != null) {
103       uid = fieldIdAttribute.getValue(faceletContext);
104     } else {
105       uid = panel.getId() + "_tx_field";
106     }
107     if (checkForAlreadyCreated(panel, uid)) {
108       return;
109     }
110 
111     final UIComponent input = application.createComponent(getSubComponentType());
112     input.setRendererType(getSubRendererType());
113     input.setId(uid);
114 
115     setSubComponentAttributes(faceletContext, input);
116     enrichInput(faceletContext, input);
117 
118     panel.getChildren().add(input);
119   }
120 
121   protected void enrichInput(final FaceletContext faceletContext, final UIComponent input) {
122     input.getAttributes().put(Attributes.labelLayout.getName(), LabelLayout.flexLeft);
123   }
124 
125   private boolean checkForAlreadyCreated(final UIComponent panel, final String uid) {
126     if (panel.getChildCount() > 0) {
127       for (final UIComponent child : panel.getChildren()) {
128         if (uid.equals(child.getId())) {
129           return true;
130         }
131       }
132     }
133     return false;
134   }
135 
136   @Override
137   public void onComponentPopulated(
138       final FaceletContext faceletContext, final UIComponent component, final UIComponent parent) {
139     super.onComponentPopulated(faceletContext, component, parent);
140 
141     if (component.getChildren().size() > 1) {
142       final UIComponent input = component.getChildren().get(0);
143       if (input instanceof EditableValueHolder) {
144         TobagoComponentHandler.addDefaultValidators(faceletContext.getFacesContext(), (EditableValueHolder) input);
145       }
146       if (input instanceof OnComponentPopulated) {
147         ((OnComponentPopulated) input).onComponentPopulated(faceletContext.getFacesContext(), component);
148       }
149     }
150   }
151 
152   private void setSubComponentAttributes(final FaceletContext ctx, final Object instance) {
153     if (instance != null) {
154       final Class type = instance.getClass();
155       if (subComponentMapper == null || !subComponentLastType.equals(type)) {
156         subComponentLastType = type;
157         subComponentMapper = createSubComponentMetaRuleset(type).finish();
158       }
159       subComponentMapper.applyMetadata(ctx, instance);
160     }
161   }
162 
163   protected MetaRuleset createSubComponentMetaRuleset(final Class aClass) {
164     final MetaRuleset metaRuleset = super.createMetaRuleset(aClass);
165     metaRuleset.ignore(Attributes.tip.getName());
166     metaRuleset.ignore(Attributes.labelWidth.getName());
167     if (Visual.class.isAssignableFrom(aClass)) {
168       metaRuleset.addRule(SupportsMarkupRule.INSTANCE);
169     }
170     if (InputSuggest.class.isAssignableFrom(aClass)) {
171       metaRuleset.addRule(SuggestMethodRule.INSTANCE);
172     }
173     return metaRuleset;
174   }
175 
176   @Override
177   protected MetaRuleset createMetaRuleset(final Class aClass) {
178     final MetaRuleset metaRuleset = super.createMetaRuleset(aClass);
179     final TagAttribute[] attrs = tag.getAttributes().getAll();
180     for (int i = 0; i < attrs.length; i++) {
181       final TagAttribute attr = attrs[i];
182       if (!attr.getLocalName().equals(Attributes.rendered.getName())) {
183         metaRuleset.ignore(attr.getLocalName());
184       }
185     }
186     return metaRuleset;
187   }
188 }