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  package org.apache.myfaces.view.facelets.tag.composite;
20  
21  import org.apache.myfaces.view.facelets.tag.BeanPropertyTagRule;
22  import org.apache.myfaces.view.facelets.tag.MetadataImpl;
23  import org.apache.myfaces.view.facelets.tag.MetadataTargetImpl;
24  import org.apache.myfaces.view.facelets.util.ParameterCheck;
25  
26  import javax.faces.context.FacesContext;
27  import javax.faces.view.facelets.FaceletContext;
28  import javax.faces.view.facelets.MetaRule;
29  import javax.faces.view.facelets.MetaRuleset;
30  import javax.faces.view.facelets.Metadata;
31  import javax.faces.view.facelets.MetadataTarget;
32  import javax.faces.view.facelets.Tag;
33  import javax.faces.view.facelets.TagAttribute;
34  import javax.faces.view.facelets.TagException;
35  import java.beans.BeanInfo;
36  import java.beans.IntrospectionException;
37  import java.util.ArrayList;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.logging.Level;
42  import java.util.logging.Logger;
43  
44  public class CompositeMetaRulesetImpl extends MetaRuleset
45  {
46      private final static Metadata NONE = new NullMetadata();
47  
48      //private final static Logger log = Logger.getLogger("facelets.tag.meta");
49      private final static Logger log = Logger.getLogger(CompositeMetadataTargetImpl.class.getName());
50      
51      private static final String METADATA_KEY
52              = "org.apache.myfaces.view.facelets.tag.composite.CompositeMetaRulesetImpl.METADATA";
53  
54      private static Map<String, MetadataTarget> getMetaData()
55      {
56          FacesContext facesContext = FacesContext.getCurrentInstance();
57          Map<String, Object> applicationMap = facesContext
58                  .getExternalContext().getApplicationMap();
59  
60          Map<String, MetadataTarget> metadata =
61                  (Map<String, MetadataTarget>) applicationMap.get(METADATA_KEY);
62  
63          if (metadata == null)
64          {
65              metadata = new HashMap<String, MetadataTarget>();
66              applicationMap.put(METADATA_KEY, metadata);
67          }
68  
69          return metadata;
70      }
71  
72      private final Map<String, TagAttribute> _attributes;
73  
74      private final List<Metadata> _mappers;
75  
76      private final List<MetaRule> _rules;
77  
78      private final Tag _tag;
79  
80      private final Class<?> _type;
81      
82      private final MetadataTarget _meta;
83  
84      public CompositeMetaRulesetImpl(Tag tag, Class<?> type, BeanInfo beanInfo)
85      {
86          _tag = tag;
87          _type = type;
88          _attributes = new HashMap<String, TagAttribute>();
89          _mappers = new ArrayList<Metadata>();
90          _rules = new ArrayList<MetaRule>();
91  
92          // setup attributes
93          for (TagAttribute attribute : _tag.getAttributes().getAll())
94          {
95              _attributes.put(attribute.getLocalName(), attribute);
96          }
97  
98          // add default rules
99          _rules.add(BeanPropertyTagRule.INSTANCE);
100         
101         try
102         {
103             _meta = new CompositeMetadataTargetImpl(_getBaseMetadataTarget(), beanInfo);            
104         }
105         catch (IntrospectionException e)
106         {
107             throw new TagException(_tag, "Error Creating TargetMetadata", e);
108         }
109     }
110 
111     public MetaRuleset add(Metadata mapper)
112     {
113         ParameterCheck.notNull("mapper", mapper);
114 
115         if (!_mappers.contains(mapper))
116         {
117             _mappers.add(mapper);
118         }
119 
120         return this;
121     }
122 
123     public MetaRuleset addRule(MetaRule rule)
124     {
125         ParameterCheck.notNull("rule", rule);
126 
127         _rules.add(rule);
128 
129         return this;
130     }
131 
132     public MetaRuleset alias(String attribute, String property)
133     {
134         ParameterCheck.notNull("attribute", attribute);
135         ParameterCheck.notNull("property", property);
136 
137         TagAttribute attr = (TagAttribute) _attributes.remove(attribute);
138         if (attr != null)
139         {
140             _attributes.put(property, attr);
141         }
142 
143         return this;
144     }
145 
146     public Metadata finish()
147     {
148         assert !_rules.isEmpty();
149         
150         if (!_attributes.isEmpty())
151         {
152             MetadataTarget target = this._getMetadataTarget();
153             int ruleEnd = _rules.size() - 1;
154 
155             // now iterate over attributes
156             for (Map.Entry<String, TagAttribute> entry : _attributes.entrySet())
157             {
158                 Metadata data = null;
159 
160                 int i = ruleEnd;
161 
162                 // First loop is always safe
163                 do
164                 {
165                     MetaRule rule = _rules.get(i);
166                     data = rule.applyRule(entry.getKey(), entry.getValue(), target);
167                     i--;
168                 } while (data == null && i >= 0);
169 
170                 if (data == null)
171                 {
172                     if (log.isLoggable(Level.SEVERE))
173                     {
174                         log.severe(entry.getValue() + " Unhandled by MetaTagHandler for type " + _type.getName());
175                     }
176                 }
177                 else
178                 {
179                     _mappers.add(data);
180                 }
181             }
182         }
183 
184         if (_mappers.isEmpty())
185         {
186             return NONE;
187         }
188         else
189         {
190             return new MetadataImpl(_mappers.toArray(new Metadata[_mappers.size()]));
191         }
192     }
193 
194     public MetaRuleset ignore(String attribute)
195     {
196         ParameterCheck.notNull("attribute", attribute);
197 
198         _attributes.remove(attribute);
199 
200         return this;
201     }
202 
203     public MetaRuleset ignoreAll()
204     {
205         _attributes.clear();
206 
207         return this;
208     }
209 
210     private final MetadataTarget _getMetadataTarget()
211     {
212         return _meta;
213     }
214     
215     private final MetadataTarget _getBaseMetadataTarget()
216     {
217         Map<String, MetadataTarget> metadata = getMetaData();
218         String key = _type.getName();
219 
220         MetadataTarget meta = metadata.get(key);
221         if (meta == null)
222         {
223             try
224             {
225                 meta = new MetadataTargetImpl(_type);
226             }
227             catch (IntrospectionException e)
228             {
229                 throw new TagException(_tag, "Error Creating TargetMetadata", e);
230             }
231 
232             metadata.put(key, meta);
233         }
234 
235         return meta;
236     }    
237 
238     private static class NullMetadata extends Metadata
239     {
240         /**
241          * {@inheritDoc}
242          */
243         @Override
244         public void applyMetadata(FaceletContext ctx, Object instance)
245         {
246             // do nothing
247         }
248     }
249 }