Package com.sun.faces.facelets.tag

Source Code of com.sun.faces.facelets.tag.DefaultTagDecorator$ElementConverter

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDLGPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.faces.facelets.tag;

import com.sun.faces.facelets.tag.jsf.PassThroughAttributeLibrary;
import com.sun.faces.facelets.tag.jsf.PassThroughElementLibrary;
import com.sun.faces.facelets.tag.jsf.html.HtmlLibrary;

import javax.faces.render.Renderer;
import javax.faces.view.Location;
import javax.faces.view.facelets.FaceletException;
import javax.faces.view.facelets.Tag;
import javax.faces.view.facelets.TagAttribute;
import javax.faces.view.facelets.TagAttributes;
import javax.faces.view.facelets.TagDecorator;
import java.util.HashMap;
import java.util.Map;

/**
* A simple tag decorator to enable jsf: syntax
*/
class DefaultTagDecorator implements TagDecorator {

    private static enum Mapper {
        a(
                new ElementConverter("h:commandLink", "jsf:action"),
                new ElementConverter("h:commandLink", "jsf:actionListener"),
                new ElementConverter("h:outputLink", "jsf:value"),
                new ElementConverter("h:link", "jsf:outcome")),

        img("h:graphicImage"), body("h:body"), head("h:head"), label("h:outputLabel"), script("h:outputScript"),
        link("h:outputStylesheet"),

        form("h:form"), textarea("h:inputTextarea"),
        // TODO if we want the name of the button to become the id, we have to do .id("name")
        button(new ElementConverter("h:button", "jsf:outcome"), new ElementConverter("h:commandButton")),

        select(new ElementConverter("h:selectManyListbox", "multiple").id("name"),
                // TODO this is a little bit ugly to handle the name as if it were jsf:id. we should not support this
                new ElementConverter("h:selectOneListbox").id("name")),

        input(new ElementConverter("h:inputText", "type")
                // TODO this is a little bit ugly to handle the name as if it were jsf:id. we should not support this
                .id("name")
                .map("hidden", "inputHidden")
                .map("password", "inputSecret")
                .map("number", "inputText")
                .map("search", "inputText")
                .map("email", "inputText")
                .map("datetime", "inputText")
                .map("date", "inputText")
                .map("month", "inputText")
                .map("week", "inputText")
                .map("time", "inputText")
                .map("datetime-local", "inputText")
                .map("range", "inputText")
                .map("color", "inputText")
                .map("url", "inputText")
                .map("checkbox", "selectBooleanCheckbox")
                .map("file", "inputFile")
                .map("submit", "commandButton")
                .map("reset", "commandButton")
                .map("button", "button"));

        private ElementConverter elementConverter;

        private Mapper(final ElementConverter... elementConverters) {
            if (elementConverters.length == 1) {
                this.elementConverter = elementConverters[0];
            } else {
                this.elementConverter = new ElementConverter() {
                    @Override
                    public Tag decorate(Tag tag) {
                        for (ElementConverter converter : elementConverters) {
                            Tag decorated = converter.decorate(tag);
                            if (decorated != null) {
                                return decorated;
                            }
                        }
                        return null;
                    }
                };
            }
        }

        private Mapper(String faceletTag) {
            elementConverter = new ElementConverter(faceletTag);
        }
    }

    private static enum Namespace {
        p(PassThroughAttributeLibrary.Namespace),
        jsf(PassThroughElementLibrary.Namespace),
        h(HtmlLibrary.Namespace);

        private String uri;

        Namespace(String uri) {
            this.uri = uri;
        }
    }

    private ElementConverter defaultElementConverter = new ElementConverter("jsf:element");

    public Tag decorate(Tag tag) {
        String ns = tag.getNamespace();
        if (!hasJsfAttribute(tag)) {
            // return immediately, if we have no jsf: attribute
            return null;
        }
        // we only handle html tags!
        if (!("".equals(ns) || "http://www.w3.org/1999/xhtml".equals(ns))) {
            throw new FaceletException("Elements with namespace " +
                    ns + " may not have attributes in namespace " +
                    Namespace.jsf.uri + "." +
                    " Namespace " + Namespace.jsf.uri +
                    " is intended for otherwise non-JSF-aware markup, such as <input type=\"text\" jsf:id >" +
                    " It is not valid to have <h:commandButton jsf:id=\"button\" />.");
        }
        for (Mapper mapper : Mapper.values()) {
            if (tag.getLocalName().equals(mapper.name())) {
                return mapper.elementConverter.decorate(tag);
            }
        }

        return defaultElementConverter.decorate(tag);
    }

    private boolean hasJsfAttribute(Tag tag) {
        for (String ns : tag.getAttributes().getNamespaces()) {
            if (Namespace.jsf.uri.equals(ns)) {
                return true;
            }
        }
        return false;
    }

    private static class ElementConverter implements TagDecorator {
        private String localName;
        private Namespace namespace;
        private String arbiterAttributeName;
        private String arbiterAttributeNamespace = "";
        private Map<String, String> additionalMappings = new HashMap<String, String>();
        private String otherHtmlIdAttribute;

        private ElementConverter() {
            super();
        }

        private ElementConverter(String faceletsTag) {
            this(faceletsTag, null);
        }

        private ElementConverter(String faceletsTag, String arbiterAttributeName) {
            String[] strings = faceletsTag.split(":");
            this.namespace = Namespace.valueOf(strings[0]);
            this.localName = strings[1];
            this.arbiterAttributeName = arbiterAttributeName;

            if (arbiterAttributeName != null && arbiterAttributeName.indexOf(':') > 0) {
                strings = arbiterAttributeName.split(":");
                this.arbiterAttributeNamespace = Namespace.valueOf(strings[0]).uri;
                this.arbiterAttributeName = strings[1];
            }
        }

        private ElementConverter map(String arbiterAttributeValue, String faceletsTagLocalName) {
            additionalMappings.put(arbiterAttributeValue, faceletsTagLocalName);
            return this;
        }

        private ElementConverter id(String otherHtmlIdAttribute) {
            this.otherHtmlIdAttribute = otherHtmlIdAttribute;
            return this;
        }

        public Tag decorate(Tag tag) {
            if (arbiterAttributeName == null) {
                // no arbiter
                return convertTag(tag, namespace, localName);
            }

            TagAttribute arbiterAttribute = tag.getAttributes().get(arbiterAttributeNamespace, arbiterAttributeName);

            if (arbiterAttribute == null) {
                // no arbiter
                return null;//convertTag(tag, namespace, localName);
            }

            // PENDING
            /**
             if (!arbiterAttribute.isLiteral()) {
             // TODO should we throw an exception here?
             }
             **/

            String myLocalName = additionalMappings.get(arbiterAttribute.getValue());

            if (myLocalName == null) {
                myLocalName = this.localName;
            }

            return convertTag(tag, namespace, myLocalName);
        }

        protected Tag convertTag(Tag tag, Namespace namespace, String localName) {
            Location location = tag.getLocation();
            String ns = namespace.uri;
            String qName = namespace.name() + ":" + localName;

            TagAttributes attributes = convertAttributes(tag.getAttributes());

            Tag converted = new Tag(location, ns, localName, qName, attributes);

            for (TagAttribute tagAttribute : attributes.getAll()) {
                // set the correct tag
                tagAttribute.setTag(converted);
            }

            return converted;
        }

        protected TagAttributes convertAttributes(TagAttributes original) {
            Map<String, TagAttribute> attributes = new HashMap<String, TagAttribute>();
            TagAttribute elementName = createElementName(original.getTag());
            attributes.put(elementName.getQName(), elementName);

            for (TagAttribute attribute : original.getAll()) {
                TagAttribute converted = convertTagAttribute(attribute);
                // avoid duplicates
                attributes.put(converted.getQName(), converted);
            }

            return new TagAttributesImpl(attributes.values().toArray(new TagAttribute[attributes.size()]));
        }

        private TagAttribute createElementName(Tag tag) {
            Location location = tag.getLocation();
            String ns = Namespace.p.uri;
            String myLocalName = Renderer.PASSTHROUGH_RENDERER_LOCALNAME_KEY;
            String qName = "p:" + myLocalName;
            String value = tag.getLocalName();

            return new TagAttributeImpl(location, ns, myLocalName, qName, value);
        }


        protected TagAttribute convertTagAttribute(TagAttribute attribute) {
            Location location = attribute.getLocation();
            String ns = attribute.getNamespace();
            String myLocalName = attribute.getLocalName();
            String qName;
            String value = attribute.getValue();

            if (Namespace.jsf.uri.equals(attribute.getNamespace())) {
                // make this a component attribute
                qName = myLocalName;
                ns = "";
            } else {
                if (ns.length() != 0 && !ns.equals(attribute.getTag().getNamespace())) {
                    // the attribute has a different namespace than the tag. preserve it.
                    return attribute;
                }
                if (attribute.getLocalName().equals(otherHtmlIdAttribute)) {
                    // special case for input name
                    qName = "id";
                    myLocalName = "id";
                } else {
                    // make this a pass through attribute
                    qName = "p:" + myLocalName;
                    ns = Namespace.p.uri;
                }
            }
            return new TagAttributeImpl(location, ns, myLocalName, qName, value);
        }
    }

}
TOP

Related Classes of com.sun.faces.facelets.tag.DefaultTagDecorator$ElementConverter

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.