Package org.apache.myfaces.trinidad.facelets

Source Code of org.apache.myfaces.trinidad.facelets.MetaTagHandler$MetaRulesetImpl$MetadataImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.apache.myfaces.trinidad.facelets;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;

import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.MetaRule;
import javax.faces.view.facelets.MetaRuleset;
import javax.faces.view.facelets.Metadata;
import javax.faces.view.facelets.MetadataTarget;
import javax.faces.view.facelets.Tag;
import javax.faces.view.facelets.TagAttribute;
import javax.faces.view.facelets.TagAttributeException;
import javax.faces.view.facelets.TagConfig;
import javax.faces.view.facelets.TagException;
import javax.faces.view.facelets.TagHandler;

import org.apache.myfaces.trinidad.logging.TrinidadLogger;


/**
* A base tag for wiring state to an object instance based on rules populated at
* the time of creating a MetaRuleset.
*
* Implementation copied from Facelets 1.1.14, as it got hidden by JSF 2.0
*
* @author Jacob Hookom
*/

public abstract class MetaTagHandler extends TagHandler {
    private Class lastType = Object.class;

    private Metadata mapper;

    public MetaTagHandler(TagConfig config) {
        super(config);
    }

    /**
     * Extend this method in order to add your own rules.
     *
     * @param type
     * @return
     */
    protected MetaRuleset createMetaRuleset(Class type) {
        assert (type != null);
        return new MetaRulesetImpl(this.tag, type);
    }

    /**
     * Invoking/extending this method will cause the results of the created
     * MetaRuleset to auto-wire state to the passed instance.
     *
     * @param ctx
     * @param instance
     */
    protected void setAttributes(FaceletContext ctx, Object instance) {
        if (instance != null) {
            Class type = instance.getClass();
            if (mapper == null || !this.lastType.equals(type)) {
                this.lastType = type;
                this.mapper = this.createMetaRuleset(type).finish();
            }
            this.mapper.applyMetadata(ctx, instance);
        }
    }


    private static class BeanPropertyTagRule extends MetaRule {

        final static class LiteralPropertyMetadata extends Metadata {

            private final Method method;

            private final TagAttribute attribute;

            private Object[] value;

            public LiteralPropertyMetadata(Method method,
                                           TagAttribute attribute) {
                this.method = method;
                this.attribute = attribute;
            }

            public void applyMetadata(FaceletContext ctx, Object instance) {
                if (value == null) {
                    String str = this.attribute.getValue();
                    value = new Object[] { ctx.getExpressionFactory().coerceToType(str,
                                                       method.getParameterTypes()[0]) };
                }
                try {
                    method.invoke(instance, this.value);
                } catch (InvocationTargetException e) {
                    throw new TagAttributeException(this.attribute,
                                                    e.getCause());
                } catch (Exception e) {
                    throw new TagAttributeException(this.attribute, e);
                }
            }

        }

        final static class DynamicPropertyMetadata extends Metadata {

            private final Method method;

            private final TagAttribute attribute;

            private final Class type;

            public DynamicPropertyMetadata(Method method,
                                           TagAttribute attribute) {
                this.method = method;
                this.type = method.getParameterTypes()[0];
                this.attribute = attribute;
            }

            public void applyMetadata(FaceletContext ctx, Object instance) {
                try {
                    this.method.invoke(instance,
                                       new Object[] { this.attribute.getObject(ctx,
                                                                               this.type) });
                } catch (InvocationTargetException e) {
                    throw new TagAttributeException(this.attribute,
                                                    e.getCause());
                } catch (Exception e) {
                    throw new TagAttributeException(this.attribute, e);
                }
            }
        }

        public final static BeanPropertyTagRule Instance =
            new BeanPropertyTagRule();

        public Metadata applyRule(String name, TagAttribute attribute,
                                  MetadataTarget meta) {
            Method m = meta.getWriteMethod(name);

            // if the property is writable
            if (m != null) {
                if (attribute.isLiteral()) {
                    return new LiteralPropertyMetadata(m, attribute);
                } else {
                    return new DynamicPropertyMetadata(m, attribute);
                }
            }

            return null;
        }

    }

    private static class MetaRulesetImpl extends MetaRuleset {

        private final static WeakHashMap metadata = new WeakHashMap();

        static final private TrinidadLogger log =
            TrinidadLogger.createTrinidadLogger(MetaRulesetImpl.class);

        private final Tag tag;

        private final Class type;

        private final Map attributes;

        private final List mappers;

        private final List rules;

        public MetaRulesetImpl(Tag tag, Class type) {
            this.tag = tag;
            this.type = type;
            this.attributes = new HashMap();
            this.mappers = new ArrayList();
            this.rules = new ArrayList();

            // setup attributes
            TagAttribute[] attrs = this.tag.getAttributes().getAll();
            for (int i = 0; i < attrs.length; i++) {
                attributes.put(attrs[i].getLocalName(), attrs[i]);
            }

            // add default rules
            this.rules.add(BeanPropertyTagRule.Instance);
        }

        public MetaRuleset ignore(String attribute) {
            assert (attribute != null);
            this.attributes.remove(attribute);
            return this;
        }

        public MetaRuleset alias(String attribute, String property) {
            assert (attribute != null);
            assert (property != null);
            TagAttribute attr =
                (TagAttribute)this.attributes.remove(attribute);
            if (attr != null) {
                this.attributes.put(property, attr);
            }
            return this;
        }

        public MetaRuleset add(Metadata mapper) {
            assert (mapper != null);
            if (!this.mappers.contains(mapper)) {
                this.mappers.add(mapper);
            }
            return this;
        }

        public MetaRuleset addRule(MetaRule rule) {
            assert (rule != null);
            this.rules.add(rule);
            return this;
        }

        private final MetadataTarget getMetadataTarget() {
            String key = this.type.getName();
            MetadataTarget meta = (MetadataTarget)metadata.get(key);
            if (meta == null) {
                try {
                    meta = new MetadataTargetImpl(type);
                } catch (IntrospectionException e) {
                    throw new TagException(this.tag, "Error Creating TargetMetadata", e);
                }
                metadata.put(key, meta);
            }
            return meta;
        }

        public Metadata finish() {
            if (!this.attributes.isEmpty()) {
                if (this.rules.isEmpty()) {
                    if (log.isLoggable(Level.SEVERE)) {
                        for (Iterator itr =
                             this.attributes.values().iterator();
                             itr.hasNext(); ) {
                            log.severe(itr.next() +
                                       " Unhandled by MetaTagHandler for type " +
                                       this.type.getName());
                        }
                    }
                } else {
                    MetadataTarget target = this.getMetadataTarget();
                    // now iterate over attributes
                    Map.Entry entry;
                    MetaRule rule;
                    Metadata data;
                    int ruleEnd = this.rules.size() - 1;
                    for (Iterator itr = this.attributes.entrySet().iterator();
                         itr.hasNext(); ) {
                        entry = (Map.Entry)itr.next();
                        data = null;
                        int i = ruleEnd;
                        while (data == null && i >= 0) {
                            rule = (MetaRule)this.rules.get(i);
                            data = rule.applyRule((String)entry.getKey(), (TagAttribute)entry.getValue(), target);
                            i--;
                        }
                        if (data == null) {
                            if (log.isLoggable(Level.SEVERE)) {
                                log.severe(entry.getValue() +
                                           " Unhandled by MetaTagHandler for type " +
                                           this.type.getName());
                            }
                        } else {
                            this.mappers.add(data);
                        }
                    }
                }
            }

            if (this.mappers.isEmpty()) {
                return NONE;
            } else {
                return new MetadataImpl((Metadata[])this.mappers.toArray(new Metadata[this.mappers.size()]));
            }
        }

        public MetaRuleset ignoreAll() {
            this.attributes.clear();
            return this;
        }

        private final static Metadata NONE = new Metadata() {
            public void applyMetadata(FaceletContext ctx, Object instance) {
                // do nothing
            }
        };

        final static class MetadataImpl extends Metadata {

            private final Metadata[] mappers;
            private final int size;

            public MetadataImpl(Metadata[] mappers) {
                this.mappers = mappers;
                this.size = mappers.length;
            }

            public void applyMetadata(FaceletContext ctx, Object instance) {
                for (int i = 0; i < size; i++) {
                    this.mappers[i].applyMetadata(ctx, instance);
                }
            }

        }
    }

    private static class MetadataTargetImpl extends MetadataTarget {

        private final Map pd;
        private final Class type;


        public MetadataTargetImpl(Class type) throws IntrospectionException {
            this.type = type;
            this.pd = new HashMap();
            BeanInfo info = Introspector.getBeanInfo(type);
            PropertyDescriptor[] pda = info.getPropertyDescriptors();
            for (int i = 0; i < pda.length; i++) {
                this.pd.put(pda[i].getName(), pda[i]);
            }
        }

        public PropertyDescriptor getProperty(String name) {
            return (PropertyDescriptor)this.pd.get(name);
        }

        public boolean isTargetInstanceOf(Class type) {
            return type.isAssignableFrom(this.type);
        }

        public Class getTargetClass() {
            return this.type;
        }

        public Class getPropertyType(String name) {
            PropertyDescriptor pd = this.getProperty(name);
            if (pd != null) {
                return pd.getPropertyType();
            }
            return null;
        }

        public Method getWriteMethod(String name) {
            PropertyDescriptor pd = this.getProperty(name);
            if (pd != null) {
                return pd.getWriteMethod();
            }
            return null;
        }

        public Method getReadMethod(String name) {
            PropertyDescriptor pd = this.getProperty(name);
            if (pd != null) {
                return pd.getReadMethod();
            }
            return null;
        }

    }

}
TOP

Related Classes of org.apache.myfaces.trinidad.facelets.MetaTagHandler$MetaRulesetImpl$MetadataImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.