Package org.eclipse.jst.jsf.designtime.internal.view

Source Code of org.eclipse.jst.jsf.designtime.internal.view.XMLViewObjectConstructionStrategy

/*******************************************************************************
* Copyright (c) 2001, 2008 Oracle Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Oracle Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.designtime.internal.view;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdt.core.Signature;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jst.jsf.common.internal.types.TypeConstants;
import org.eclipse.jst.jsf.common.runtime.internal.model.ViewObject;
import org.eclipse.jst.jsf.common.runtime.internal.model.behavioural.ActionSourceInfo;
import org.eclipse.jst.jsf.common.runtime.internal.model.behavioural.ActionSourceInfo2;
import org.eclipse.jst.jsf.common.runtime.internal.model.behavioural.EditableValueHolderInfo;
import org.eclipse.jst.jsf.common.runtime.internal.model.behavioural.INamingContainerInfo;
import org.eclipse.jst.jsf.common.runtime.internal.model.behavioural.ValueHolderInfo;
import org.eclipse.jst.jsf.common.runtime.internal.model.component.ComponentFactory;
import org.eclipse.jst.jsf.common.runtime.internal.model.component.ComponentInfo;
import org.eclipse.jst.jsf.common.runtime.internal.model.component.ComponentTypeInfo;
import org.eclipse.jst.jsf.common.runtime.internal.model.decorator.ConverterDecorator;
import org.eclipse.jst.jsf.common.runtime.internal.model.decorator.ConverterTypeInfo;
import org.eclipse.jst.jsf.common.runtime.internal.model.decorator.ValidatorDecorator;
import org.eclipse.jst.jsf.common.runtime.internal.model.decorator.ValidatorTypeInfo;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.IComponentPropertyHandler;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.IComponentTagElement;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.IConverterTagElement;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.ITagAttributeHandler;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.ITagElement;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.IValidatorTagElement;
import org.eclipse.jst.jsf.common.util.JDTBeanProperty;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContextFactory;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.designtime.internal.view.XMLViewObjectMappingService.ElementData;
import org.eclipse.jst.jsf.designtime.internal.view.mapping.ICustomViewMapper;
import org.eclipse.jst.jsf.designtime.internal.view.mapping.ICustomViewMapper.PropertyMapping;
import org.eclipse.jst.jsf.designtime.internal.view.mapping.viewmapping.CustomViewMapperExtensionLoader;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;

/**
* A strategy for constructing view objects.
*
* @author cbateman
*
*/
public class XMLViewObjectConstructionStrategy extends
        ViewObjectConstructionStrategy<Element>
{
    private static final String               GENERATED_ID = "_generatedId"; //$NON-NLS-1$
    private final ComponentConstructionData   _constructionData;
    private final XMLViewDefnAdapter          _adapter;
    private final XMLViewObjectMappingService _mappingService;

    /**
     * @param adapter
     *            MUST NOT BE NULL
     * @param constructionData
     *            MUST NOT BE NULL
     * @param mappingService
     *            MAY BE NULL
     */
    public XMLViewObjectConstructionStrategy(final XMLViewDefnAdapter adapter,
            final ComponentConstructionData constructionData,
            final XMLViewObjectMappingService mappingService)
    {
        super();
        if (adapter == null || constructionData == null)
        {
            throw new IllegalArgumentException(
                    "adapter and constructionData must not be null"); //$NON-NLS-1$
        }
        _constructionData = constructionData;
        _adapter = adapter;
        _mappingService = mappingService;
    }

    @Override
    public ViewObject createViewObject(final Element element,
            final ITagElement tagElement)
    {
        try
        {
            if (tagElement instanceof IComponentTagElement)
            {
                String id = null;

                // only generate ids for non-viewroot components. This will
                // make the generated id's more faithful to runtime since the
                // running count won't be incremented for view roots (as they
                // won't at runtime).
                final ComponentTypeInfo typeInfo = ((IComponentTagElement) tagElement)
                        .getComponent();

                if (!"javax.faces.ViewRoot".equals(typeInfo.getComponentType())) //$NON-NLS-1$
                {
                    id = calculateId(element, _constructionData);
                }
                return findBestComponent(tagElement.getUri(), element, id,
                        (IComponentTagElement) tagElement);
            }
            else if (tagElement instanceof IConverterTagElement)
            {
                final ConverterTypeInfo typeInfo = ((IConverterTagElement) tagElement)
                        .getConverter();
                // TODO: validate when no parent
                ComponentInfo parent = _constructionData.getParent();
                parent = findFirstParent(
                        ComponentFactory.INTERFACE_VALUEHOLDER, parent);
                if (parent != null)
                {
                    parent.addDecorator(
                            new ConverterDecorator(parent, typeInfo),
                            ComponentFactory.CONVERTER);
                }
                // TODO: else validate problem
            }
            else if (tagElement instanceof IValidatorTagElement)
            {
                final ValidatorTypeInfo typeInfo = ((IValidatorTagElement) tagElement)
                        .getValidator();
                ComponentInfo parent = _constructionData.getParent();
                parent = findFirstParent(
                        ComponentFactory.INTERFACE_EDITABLEVALUEHOLDER, parent);
                if (parent != null)
                {
                    parent.addDecorator(
                            new ValidatorDecorator(parent, typeInfo),
                            ComponentFactory.VALIDATOR);
                }
                // TODO :else validate problem
            }
        }
        catch (final Exception e)
        {
            // log and ignore if an individual construction fails
            JSFCorePlugin.log(e, "Error constructing view object"); //$NON-NLS-1$
        }
        return null;
    }

    private ComponentInfo findFirstParent(final String matchingType,
            final ComponentInfo start)
    {
        ComponentInfo parent = start;

        while (parent != null && parent.getComponentTypeInfo() != null
                && !parent.getComponentTypeInfo().isInstanceOf(matchingType))
        {
            parent = parent.getParent();
        }
        return parent;
    }

    private ComponentInfo findBestComponent(final String uri,
            final Element srcElement, final String id,
            final IComponentTagElement tagElement)
    {
        ComponentInfo bestComponent = null;

        final ComponentInfo parent = _constructionData.getParent();

        final Map<String, Object> initMap = new HashMap<String, Object>();
        final Map<String, String> attributeToPropertyMap = new HashMap<String, String>();
        populateInitMap(uri, initMap, srcElement, tagElement,
                attributeToPropertyMap);

        if (initMap.get("id") == null) //$NON-NLS-1$
        {
            // id must be set
            initMap.put("id", id); //$NON-NLS-1$
        }

        final ComponentTypeInfo typeInfo = tagElement.getComponent();

        // if we have a well-established base type, try that first
        // sub-classes must occur before superclasses to ensure most accurate
        // detection.
        if (typeInfo.isInstanceOf(ComponentFactory.BASE_CLASS_UIINPUT))
        {
            bestComponent = ComponentFactory.createUIInputInfo(parent,
                    typeInfo, initMap);
        }
        else if (typeInfo.isInstanceOf(ComponentFactory.BASE_CLASS_UIOUTPUT))
        {
            bestComponent = ComponentFactory.createUIOutputInfo(parent,
                    typeInfo, initMap);
        }
        else if (typeInfo.isInstanceOf(ComponentFactory.BASE_CLASS_UICOMMAND))
        {
            bestComponent = ComponentFactory.createUICommandInfo(parent,
                    typeInfo, initMap);
        }
        else if (typeInfo.isInstanceOf(ComponentFactory.BASE_CLASS_UIDATA))
        {
            bestComponent = ComponentFactory.createUIDataInfo(parent, typeInfo,
                    initMap);
        }
        else if (typeInfo.isInstanceOf(ComponentFactory.BASE_CLASS_UIFORM))
        {
            // TODO: how handle prepend ids?
            bestComponent = ComponentFactory.createUIFormInfo(parent, typeInfo,
                    initMap);
        }
        else
        {
            // default
            bestComponent = ComponentFactory.createComponentInfo(
                    _constructionData.getParent(), typeInfo, initMap);
        }

        addTypeAdapters(bestComponent);
        maybeMapXMLToViewObjects(bestComponent, srcElement,
                attributeToPropertyMap, _constructionData.getDocument());
        maybeUpdateViewObject(bestComponent, srcElement, tagElement);
        return bestComponent;
    }

    // TODO: move to view definition adapter?
    private void populateInitMap(final String uri,
            final Map<String, Object> initMap, final Element srcElement,
            final IComponentTagElement tagElement,
            final Map<String, String> attributeToPropertyMap)
    {
        final ComponentTypeInfo typeInfo = tagElement.getComponent();
        final Map<String, ITagAttributeHandler> attributeHandlers = tagElement
                .getAttributeHandlers();

        final NamedNodeMap nodeMap = srcElement.getAttributes();

        if (nodeMap != null && attributeHandlers != null)
        {
            Map<String, JDTBeanProperty> properties = null;

            for (int i = 0; i < nodeMap.getLength(); i++)
            {
                final Attr attr = (Attr) nodeMap.item(i);
                if (attr != null)
                {
                    final String name = attr.getLocalName();

                    if (name != null)
                    {
                        final ITagAttributeHandler attrHandler = attributeHandlers
                                .get(name);
                        if (attrHandler instanceof IComponentPropertyHandler)
                        {
                            if (properties == null)
                            {
                                properties = DTComponentIntrospector.getBeanProperties(typeInfo, _constructionData.getProject());
                            }
                            mapComponentProperty(uri, srcElement, properties,
                                    (IComponentPropertyHandler) attrHandler,
                                    attr, name, initMap, attributeHandlers,
                                    attributeToPropertyMap);
                        }
                    }
                }
            }
        }
    }

    private void mapComponentProperty(final String uri,
            final Element srcElement,
            final Map<String, JDTBeanProperty> properties,
            final IComponentPropertyHandler attrHandler, final Attr attr,
            final String attributeName, final Map initMap,
            final Map<String, ITagAttributeHandler> attributeHandlers,
            final Map<String, String> attributeToPropertyMap)
    {
        final String propertyName = attrHandler.getPropertyName();
        if (properties.containsKey(propertyName))
        {
            final String id = attrHandler.getCustomHandler();

            ICustomViewMapper mapper = null;

            if (id != null)
            {
                mapper = CustomViewMapperExtensionLoader
                        .getCustomViewMapper(id);
                if (mapper != null)
                {
                    final PropertyMapping mapping = mapper
                            .mapToComponentProperty(uri, srcElement, attr);
                    if (mapping != null)
                    {
                        initMap.put(mapping.getName(), mapping.getProperty());
                        attributeToPropertyMap.put(attributeName, mapping
                                .getName());
                        return;
                    }
                }
            }

            final String value = attr.getValue();
            if (value != null)
            {
                final Object convertedValue = convertFromString(value,
                        properties.get(propertyName));
                initMap.put(propertyName, convertedValue);
            }
            attributeToPropertyMap.put(attributeName, propertyName);
        }
    }

    private void maybeMapXMLToViewObjects(final ViewObject mappedObject,
            final Element node,
            final Map<String, String> attributeToProperties,
            final IDocument document)
    {
        if (mappedObject != null && _mappingService != null)
        {
            final String uri = _adapter.getNamespace(node, document);
            final IStructuredDocumentContext context = IStructuredDocumentContextFactory.INSTANCE
                    .getContext(document, node);
            final ElementData elementData = XMLViewObjectMappingService
                    .createElementData(uri, node.getLocalName(), context,
                            attributeToProperties);
            //Bug 269050 - IllegalArgumentException in createMapping() method
            if (elementData != null) {
              _mappingService.createMapping(elementData, mappedObject);
            }
        }
    }

    private void maybeUpdateViewObject(final ComponentInfo bestComponent,
            final Element srcElement, final ITagElement tagElement)
    {
        if (srcElement.getAttributes() == null)
            return;

        for (int i = 0; i < srcElement.getAttributes().getLength(); i++)
        {
            final Attr attr = (Attr) srcElement.getAttributes().item(i);
            final Map<String, ITagAttributeHandler> attributeHandlers = tagElement
                    .getAttributeHandlers();

            if (attributeHandlers != null)
            {
                final ITagAttributeHandler handler = attributeHandlers.get(attr
                        .getLocalName());

                if (handler != null)
                {
                    final String id = handler.getCustomHandler();

                    ICustomViewMapper mapper = null;

                    if (id != null)
                    {
                        mapper = CustomViewMapperExtensionLoader
                                .getCustomViewMapper(id);
                        if (mapper != null)
                        {
                            mapper.doAttributeActions(bestComponent,
                                    srcElement, attr);
                        }
                    }
                }
            }
        }
    }

    private Object convertFromString(final String convertValue,
            final JDTBeanProperty ofThisType)
    {
        final String signature = ofThisType.getTypeSignature();

        Object result = null;
        switch (Signature.getTypeSignatureKind(signature))
        {
            case Signature.BASE_TYPE_SIGNATURE:
                result = convertFromBaseType(convertValue, signature);
            break;

            case Signature.CLASS_TYPE_SIGNATURE:
                if (TypeConstants.TYPE_STRING.equals(signature))
                {
                    result = convertValue;
                }
                else if (TypeConstants.TYPE_JAVAOBJECT.equals(signature))
                {
                    result = convertValue;
                }
            break;
        }

        return result;
    }

    // TODO: does this belong somewhere else?
    private Object convertFromBaseType(final String convertValue,
            final String signature)
    {
        if (Signature.SIG_BOOLEAN.equals(signature))
        {
            return Boolean.valueOf(convertValue);
        }
        else if (Signature.SIG_INT.equals(signature)
                || Signature.SIG_BYTE.equals(signature)
                || Signature.SIG_SHORT.equals(signature))
        {
            try
            {
                return Integer.valueOf(convertValue);
            }
            catch (final NumberFormatException nfe)
            {
                return null;
            }
        }
        else if (Signature.SIG_LONG.equals(convertValue))
        {
            try
            {
                return Long.valueOf(convertValue);
            }
            catch (final NumberFormatException nfe)
            {
                return null;
            }
        }

        return null;
    }

    private void addTypeAdapters(final ComponentInfo component)
    {
        final String[] interfaceNames = component.getComponentTypeInfo()
                .getInterfaces();
        final Set interfaceNameSets = new HashSet();

        for (final String interfaceName : interfaceNames)
        {
            interfaceNameSets.add(interfaceName);
        }

        // don't replace intrinsic adapters
        if (interfaceNameSets.contains(ComponentFactory.INTERFACE_ACTIONSOURCE))
        {
            // an ActionSource2 is-a ActionSource
            if (interfaceNameSets
                    .contains(ComponentFactory.INTERFACE_ACTIONSOURCE2)
                    && component.getAdapter(ComponentFactory.ACTION_SOURCE2) == null)
            {
                component.addAdapter(ComponentFactory.ACTION_SOURCE2,
                        new ActionSourceInfo2(null, null, false, null));
            }

            if (component.getAdapter(ComponentFactory.ACTION_SOURCE) == null)
            {
                component.addAdapter(ComponentFactory.ACTION_SOURCE,
                        new ActionSourceInfo(null, null, false));
            }
        }

        if (interfaceNameSets.contains(ComponentFactory.INTERFACE_VALUEHOLDER))
        {
            // a EditableValueHolder is-a ValueHolder
            if (interfaceNameSets
                    .contains(ComponentFactory.INTERFACE_EDITABLEVALUEHOLDER)
                    && component
                            .getAdapter(ComponentFactory.EDITABLE_VALUE_HOLDER) == null)
            {
                component.addAdapter(ComponentFactory.EDITABLE_VALUE_HOLDER,
                        new EditableValueHolderInfo(null, null, null, false,
                                false, true, false, null, null, null));
            }

            if (component.getAdapter(ComponentFactory.VALUE_HOLDER) == null)
            {
                component.addAdapter(ComponentFactory.VALUE_HOLDER,
                        new ValueHolderInfo(null, null, null));
            }
        }

        if (interfaceNameSets
                .contains(ComponentFactory.INTERFACE_NAMINGCONTAINER)
                && component.getAdapter(ComponentFactory.NAMING_CONTAINER) == null)
        {
            component.addAdapter(ComponentFactory.NAMING_CONTAINER,
                    INamingContainerInfo.ADAPTER);
        }
    }

    /**
     * @param element
     * @param constructionData
     * @return the id for element either derived from the element using getId or
     *         if not present, using a generation algorithm
     */
    protected String calculateId(final Element element,
            final ComponentConstructionData constructionData)
    {
        final String id = _adapter.getId(element);
        if (id != null)
        {
            return id;
        }
        // TODO: improve this
        final String prefix = _adapter.getGeneratedIdPrefix();
        return (prefix != null ? prefix : GENERATED_ID)
                + constructionData.increment();
    }

    /**
     * @return the construction data for this strategy
     */
    public final ComponentConstructionData getConstructionData()
    {
        return _constructionData;
    }
}
TOP

Related Classes of org.eclipse.jst.jsf.designtime.internal.view.XMLViewObjectConstructionStrategy

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.