Package org.openquark.gems.client

Source Code of org.openquark.gems.client.ValueGem

/*
* 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.
*/


/*
* ValueGem.java
* Creation date: (10/18/00 1:03:35 PM)
* By: Luke Evans
*/
package org.openquark.gems.client;

import java.util.List;

import org.openquark.cal.compiler.CompositionNode;
import org.openquark.cal.compiler.ModuleName;
import org.openquark.cal.compiler.SourceModel;
import org.openquark.cal.compiler.TypeExpr;
import org.openquark.cal.valuenode.ParametricValueNode;
import org.openquark.cal.valuenode.Target;
import org.openquark.cal.valuenode.TargetRunner;
import org.openquark.cal.valuenode.ValueNode;
import org.openquark.util.xml.BadXMLDocumentException;
import org.openquark.util.xml.XMLPersistenceHelper;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


/**
* A ValueGem which we are using to build our supercombinator (compound Gem).
* Creation date: (10/18/00 1:03:35 PM)
* @author Luke Evans
*/
public final class ValueGem extends Gem implements CompositionNode.Value {

    /** The value node representing the value of this value gem */
    private ValueNode valueNode;
   
    /**
     * Construct a default ValueGem.
     */
    public ValueGem() {
        // The default value is a parametric value node with an unconstrained type variable.
        // TODOEL: this assumes that parametric value nodes will always be present, and that 
        //   they are the best type to use.  This will be true for (at least) a while though..
        this(new ParametricValueNode(TypeExpr.makeParametricType()));
    }

    /**
     * Construct a ValueGem from a value node
     * @param valueNode ValueNode the initial value of this value gem
     */
    public ValueGem(ValueNode valueNode) {
        // Initialize with no input parts.
        super(0);
        this.valueNode = valueNode;
    }

    /**
    protected PartOutput createOutputPart() {
        return new PartOutput();
    }
     * {@inheritDoc}
     */
    @Override
    protected PartOutput createOutputPart() {
        return new ValuePart();
    }

    /**
     * Obtain the string value of this CompositionNode
     * @return the string value
     */
    public final String getStringValue() {
        return valueNode.getCALValue();
    }
   
    /**
     * Obtain the source model of this CompositionNode
     * @return the source model
     */
    public final SourceModel.Expr getSourceModel() {
        return valueNode.getCALSourceModel();
    }
   
    /**
     * Returns true if this ValueGem contains parametric values.
     * Otherwise, returns false.
     * @return boolean
     */
    public boolean containsParametricValues() {
        return valueNode.containsParametricValue();
    }

    /**
     * Change the value of this gem.
     * @param newValue the new value of this gem.
     */
    public void changeValue(ValueNode newValue) {
        ValueNode oldValue = valueNode;
        this.valueNode = newValue;
       
        fireValueChangeEvent(oldValue);
    }
   
    /**
     * Adds the specified listener to receive value change events from this gem.
     * @param l the value change listener
     */
    public void addValueChangeListener(ValueGemChangeListener l) {
        listenerList.add(ValueGemChangeListener.class, l);
    }

    /**
     * Removes the specified value change listener so that it no longer receives value change events from this gem.
     * @param l the value change listener
     */
    public void removeValueChangeListener(ValueGemChangeListener l) {
        listenerList.remove(ValueGemChangeListener.class, l);
    }

    /**
     * Fires a value change event.
     * @param oldValue the old input parts.
     */
    private void fireValueChangeEvent(ValueNode oldValue) {
       
        Object[] listeners = listenerList.getListenerList();
       
        ValueGemChangeEvent e = null;
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == ValueGemChangeListener.class) {
                if (e == null) {
                    // Lazily create the event:
                    e = new ValueGemChangeEvent(this, oldValue, valueNode);
                }
                ((ValueGemChangeListener)listeners[i + 1]).valueChanged(e);
            }
        }
    }

    /**
     * Get the value of this gem.
     * @return ValueNode the value node represented by this gem.
     */
    public final ValueNode getValueNode() {
        return valueNode;
    }

    /**
     * Return whether this target is runnable
     * @return boolean whether this target is runnable
     */
    @Override
    public final boolean isRunnable(){
        // additional constraint: can't be parametric
        return (super.isRunnable());
    }

    /**
     * Describe this Gem
     * @return the description
     */
    @Override
    public String toString() {
        return "Value: " + getTextValue();
    }
   
    /**
     * Return the textual representation of the value that this gem is storing
     * @return String
     */
    public String getTextValue() {
        return getValueNode().getTextValue();
    }

    /*
     * Methods supporting XMLPersistable                 ********************************************
     */

    /**
     * {@inheritDoc}
     */
    @Override
    public void saveXML(Node parentNode, GemContext gemContext) throws XMLPersistenceHelper.StateNotPersistableException {
       
        Document document = (parentNode instanceof Document) ? (Document)parentNode : parentNode.getOwnerDocument();

        // Create the value gem element
        Element resultElement = document.createElementNS(GemPersistenceConstants.GEM_NS, GemPersistenceConstants.VALUE_GEM_TAG);
        resultElement.setPrefix(GemPersistenceConstants.GEM_NS_PREFIX);
        parentNode.appendChild(resultElement);

        // Add info for the superclass gem.
        super.saveXML(resultElement, gemContext);


        // Now add ValueGem-specific info

        // Add info for the value

        // Add a value gem element
        Element valueElement = document.createElement(GemPersistenceConstants.VALUE_GEM_VALUE_TAG);
        resultElement.appendChild(valueElement);

//        // Add the value text to the value gem element
//        if (containsParametricValues()) {
//            throw new StateNotPersistableException("Value gem has parametric values.");
//        }
        String valueString = valueNode.getCALValue();
        CDATASection valueStringChild = XMLPersistenceHelper.createCDATASection(document, valueString);
        valueElement.appendChild(valueStringChild);
    }

    /**
     * Create a new ValueGem and loads its state from the specified XML element.
     * @param gemElement Element the element representing the structure to deserialize.
     * @param gemContext the context in which the gem is being instantiated.
     * @param valueRunner ValueRunner the ValueRunner used to get the value node from the value.
     * @param loadModuleName the name of the module in which this value node was saved
     * @return ValueGem
     * @throws BadXMLDocumentException
     */
    public static ValueGem getFromXML(Element gemElement, GemContext gemContext,
                                      ValueRunner valueRunner, ModuleName loadModuleName) throws BadXMLDocumentException {
        ValueGem gem = new ValueGem();
        gem.loadXML(gemElement, gemContext, valueRunner, loadModuleName);
        return gem;
    }

    /**
     * Load this object's state.
     * @param gemElement Element the element representing the structure to deserialize.
     * @param gemContext the context in which the gem is being instantiated.
     * @param valueRunner ValueRunner the ValueRunner used to get the value node from the value.
     * @param loadModuleName the name of the module in which this value node was saved
     */
    void loadXML(Element gemElement, GemContext gemContext,
                 ValueRunner valueRunner, ModuleName loadModuleName) throws BadXMLDocumentException {

        XMLPersistenceHelper.checkTag(gemElement, GemPersistenceConstants.VALUE_GEM_TAG);
        XMLPersistenceHelper.checkPrefix(gemElement, GemPersistenceConstants.GEM_NS_PREFIX);

        List<Element> childElems = XMLPersistenceHelper.getChildElements(gemElement);

        // Get info for the underlying gem.       
        Element superGemElem = (childElems.size() < 1) ? null : (Element) childElems.get(0);
        XMLPersistenceHelper.checkIsElement(superGemElem);
        super.loadXML(superGemElem, gemContext);

        // figure out the value node
        Element valueChildElem = (childElems.size() < 2) ? null : (Element) childElems.get(1);
        XMLPersistenceHelper.checkIsElement(valueChildElem);
        this.valueNode = getValueNodeFromXML(valueChildElem, valueRunner, loadModuleName);
    }

    /**
     * Get a value node from its corresponding XML element.
     * @param valueElement the element representing the structure to deserialize.
     * @param valueRunner the ValueRunner used to get the value node from the value.
     * @param loadModuleName the name of the module in which this value node was saved
     * @return ValueNode a new value node corresponding the to XML element.  Null if evaluation fails, or
     * if the value node system can't handle the output.
     */
    public static ValueNode getValueNodeFromXML(Element valueElement, ValueRunner valueRunner, ModuleName loadModuleName)
            throws BadXMLDocumentException {

        XMLPersistenceHelper.checkTag(valueElement, GemPersistenceConstants.VALUE_GEM_VALUE_TAG);

        // Get the value text
        StringBuilder valueText = new StringBuilder();
        Node valueChild = valueElement.getFirstChild();
        XMLPersistenceHelper.getAdjacentCharacterData(valueChild, valueText);

        // Create a target to be run by a value runner, and return the result
        Target valueTarget = new Target.SimpleTarget(valueText.toString());

        ValueNode targetValue = null;
        try {
            targetValue = valueRunner.getValue(valueTarget, loadModuleName);
        } catch (TargetRunner.ProgramCompileException pce) {
            XMLPersistenceHelper.handleBadDocument(valueElement, "Can't compile program: \"" + valueText + "\".");
        }
       
        // What to do?
        if (targetValue == null) {
            XMLPersistenceHelper.handleBadDocument(valueElement, "Can't convert to a value node: \"" + valueText + "\".");
        }
        return targetValue;
    }

    /**
     * The PartConnectable representing the output part of a ValueGem
     * Creation date: (Jul 26, 2002 5:04:03 PM)
     * @author Edward Lam
     */
    class ValuePart extends PartOutput {
        /**
         * Default constructor for an emitting part
         */
        private ValuePart(){
            super();
        }

        /**
         * Get the type of this part
         * @return the type expression
         */
        @Override
        public final TypeExpr getType() {
            return valueNode.getTypeExpr();
        }

        /**
         * Set the type of this part
         * @param newType TypeExpr the type expression to set
         */
        @Override
        void setType(TypeExpr newType) {
            throw new UnsupportedOperationException("Can't set the type of a value gem.");
        }
    }
}


TOP

Related Classes of org.openquark.gems.client.ValueGem

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.