Package org.openquark.cal.valuenode

Source Code of org.openquark.cal.valuenode.ValueNodeBuilderHelper

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/


/*
* ValueNodeBuilderHelper.java
* Created: June 11, 2001
* By: Michael Cheng
*/

package org.openquark.cal.valuenode;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

import org.openquark.cal.compiler.DataConstructor;
import org.openquark.cal.compiler.ModuleTypeInfo;
import org.openquark.cal.compiler.PreludeTypeConstants;
import org.openquark.cal.compiler.QualifiedName;
import org.openquark.cal.compiler.TypeConsApp;
import org.openquark.cal.compiler.TypeConstructor;
import org.openquark.cal.compiler.TypeExpr;
import org.openquark.cal.module.Cal.Core.CAL_Prelude;
import org.openquark.cal.services.Perspective;
import org.openquark.util.UnsafeCast;


/**
* This class is used to help during the construction of ValueNodes (primarily during output mechanism).
* @author Michael Cheng
*/
public class ValueNodeBuilderHelper {

    /** The perspective from which to gather info to help build stuff. */
    private final Perspective perspective;

    /** Instances of ValueNodeProviders registered with this builder helper. */
    private final List<ValueNodeProvider<?>> providerList = new ArrayList<ValueNodeProvider<?>>();
    
    /** handy TypeExpr constants for common Prelude types. */
    private PreludeTypeConstants preludeTypeConstants;   
   
    /** The module type info for the prelude which the prelude type constants were constructed.
     *  Used to check that the returned constants object is not out of date (eg. after a recompile) .*/
    private ModuleTypeInfo preludeTypeInfo;
   
    /**
     * ValueNodeBuilderHelper constructor.
     * @param perspective the Perspective this builder helper is used in
     */
    public ValueNodeBuilderHelper(Perspective perspective) {

        if (perspective == null) {
            throw new NullPointerException();
        }
       
        this.perspective = perspective;
    }
   
    /**    
     * @return handy TypeExpr constants for common Prelude types.
     */
    public PreludeTypeConstants getPreludeTypeConstants() {
       
        ModuleTypeInfo currentPreludeTypeInfo;
        ModuleTypeInfo workingModuleTypeInfo = perspective.getWorkingModuleTypeInfo();
       
        if (workingModuleTypeInfo.getModuleName().equals(CAL_Prelude.MODULE_NAME)){
            currentPreludeTypeInfo = workingModuleTypeInfo;
       
        } else {
            currentPreludeTypeInfo = workingModuleTypeInfo.getDependeeModuleTypeInfo(CAL_Prelude.MODULE_NAME);
        }
       
        if (currentPreludeTypeInfo != preludeTypeInfo) {   // also handles if info == null.
            this.preludeTypeInfo = currentPreludeTypeInfo;
            this.preludeTypeConstants = new PreludeTypeConstants(preludeTypeInfo);
        }
       
        return preludeTypeConstants;
    }
       
    /**
     * Get a default value node for the given type expr.
     * @param typeExpr the type expression to get a value node for
     * @return the value node most appropriate for the given type expression, or null if a value could not be constructed.
     */
    public ValueNode getValueNodeForTypeExpr(TypeExpr typeExpr) {
        return buildValueNode(null, null, typeExpr);
    }

    /**
     * Builds a new value node to represent the given information.
     * @param value the value for the value node, or null to return a default value for the given data constructor and type expr.
     * @param dataConstructor the data constructor for the value node
     * @param typeExpr the type expression for the value node
     * @return a new value node for the given information, or null if a value node could not be built to represent the given value.
     */
    public ValueNode buildValueNode(Object value, DataConstructor dataConstructor, TypeExpr typeExpr) {
        // Go in reverse order since more important providers are added last.
        for (int i = providerList.size() - 1; i >= 0; i--) {
           
            ValueNodeProvider<?> provider = providerList.get(i);
            ValueNode nodeInstance = provider.getNodeInstance(value, dataConstructor, typeExpr);
           
            if (nodeInstance != null) {
                return nodeInstance;
            }
        }
       
        return null;
    }   
   
    /**
     * Returns the class of the value node associated with a TypeExpr.
     * @param typeExpr the typeExpr to ask about.
     * @return the class of the provider which provides the value node which would handle a value of the given type.
     */
    public Class<? extends ValueNode> getValueNodeClass(TypeExpr typeExpr) {
        // Go in reverse order since more important providers are added last.
        for (int i = providerList.size() - 1; i >= 0; i--) {
           
            ValueNodeProvider<? extends ValueNode> provider = providerList.get(i);
            ValueNode nodeInstance = provider.getNodeInstance(typeExpr);
           
            if (nodeInstance != null) {
                return provider.getValueNodeClass();
            }
        }
       
        return null;
    }
   
    /**
     * @param typeExpr the type expression to check
     * @return true if the type can be handled for output.
     * This is true for everything except function types and if the type expression is null.
     */
    public static boolean canHandleOutput(TypeExpr typeExpr) {
        return typeExpr != null && !typeExpr.isFunctionType();
    }
   
    /**
     * @return the perspective used by this builder helper
     */
    public Perspective getPerspective() {
        return perspective;
    }

    /**
     * Registers a new value node provider with this builder helper and adds it to the internal
     * list of available providers. A newly registered provider takes precedence over previously
     * registered providers.
     * @param providerClass the class of the provider
     */
    public void registerValueNodeProvider(Class<? extends ValueNodeProvider<?>> providerClass) {

        if (!ValueNodeProvider.class.isAssignableFrom(providerClass)) {
            throw new IllegalArgumentException("given class is not a ValueNodeProvider: " + providerClass);
        }

        try {
            Constructor<? extends ValueNodeProvider<?>> providerConstructor = providerClass.getConstructor(new Class[] {ValueNodeBuilderHelper.class});
                   
            providerConstructor.setAccessible(true);
               
            ValueNodeProvider<?> editorProvider = providerConstructor.newInstance(new Object[] {this});
               
            providerList.add(editorProvider);
       
        } catch (Exception ex) {
            throw new IllegalArgumentException("error instantiating ValueEditorProvider: " + providerClass);
        } catch (LinkageError ex) {
            throw new IllegalArgumentException("error instantiating ValueEditorProvider: " + providerClass);
        }
    }

    /**
     * Get the provider to provide value nodes of a given class.
     * @param valueNodeClass the class of the value node.
     * @return the corresponding registered ValueNodeProvider, or null if no corresponding provider is registered.
     */
    public <T extends ValueNode> ValueNodeProvider<T> getValueNodeProvider(Class<T> valueNodeClass) {
        // Iterate through the provider list, asking each one whether it handles the given class.
        for (final ValueNodeProvider<?> editorProvider : providerList) {
            if (editorProvider.getValueNodeClass() == valueNodeClass) {
                return UnsafeCast.unsafeCast(editorProvider);
            }
        }
        return null;
    }
   
    /**
     * @param typeCons the entity to get a type constructor for
     * @return the type constructor for the entity or null if the entity is not supported
     * An entity is not supported if it is a function type.
     */
    public TypeConsApp getTypeConstructorForEntity(TypeConstructor typeCons) {
       
        if (typeCons.getNDataConstructors() > 0) {
            return typeCons.getNthDataConstructor(0).getTypeConsApp();

            // For everything below, there are no data constructors
           
        } else if (typeCons.getTypeArity() == 0) {
            // This is a non-parametric type i.e. does not involve type parameters.
            return TypeExpr.makeNonParametricType(typeCons).rootTypeConsApp();

        } else if (typeCons.getName().equals(CAL_Prelude.TypeConstructors.Function)) {

            // We don't allow the user to choose the function type for a value gem.
            // However, it is trivial to enable the functionality using the line below.

            //return (TypeConsApp) TypeExpr.makeFunType(TypeExpr.makeParametricType(), TypeExpr.makeParametricType());

            return null;
           
        } else {

            // This is an unknown built-in type and is not handled.
            return null;
        }
    }
   
    /**
     * @param typeConsName the name of the type constructor to return
     * @return the type constructor with the given name if it is visible and supported, null otherwise
     */
    public TypeConsApp getTypeConstructorForName(QualifiedName typeConsName) {
       
        TypeConstructor typeCons = perspective.getTypeConstructor(typeConsName);
       
        if (typeCons != null) {
            return getTypeConstructorForEntity(typeCons);
        }
       
        return null;
    }
}
TOP

Related Classes of org.openquark.cal.valuenode.ValueNodeBuilderHelper

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.