Package org.openquark.cal.valuenode

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

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


/*
* AbstractRecordValueNode.java
* Creation date: Oct 4, 2006.
* By: Edward Lam
*/
package org.openquark.cal.valuenode;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.openquark.cal.compiler.FieldName;
import org.openquark.cal.compiler.RecordType;
import org.openquark.cal.compiler.TypeExpr;



/**
* Abstract AlgebraicValueNode for handling values whose type expr is a RecordType.
*
* @author Edward Lam
*/
public abstract class AbstractRecordValueNode extends AlgebraicValueNode {
   
    /**
     * Constructor for an AbstractRecordValueNode.
     * @param typeExpr the TypeExpr of the data value which this ValueNode represents.
     */
    public AbstractRecordValueNode(TypeExpr typeExpr) {
        super(typeExpr);
    }

    /**
     * Retrieve the value node representing the nth field in the record.
     * Note: Fields are indexed alphabetically
     * 
     * @param n number of field
     * @return ValueNode
     */
    public abstract ValueNode getValueAt(int n);
   
    /**
     * @return the number of fields that the record is asserted to have.
     */
    public abstract int getNFieldNames();
   
    /**
     * Get the name of the ith field in the record
     * Note: Fields are indexed by the ordering on the FieldName class.
     *
     * @param i index of field to retrieve
     * @return FieldName
     */
    public abstract FieldName getFieldName(int i);
   
    /**
     * @return of record field names
     */
    public abstract List<FieldName> getFieldNames();
   
    /**
     * Get the type expression of the ith field
     * @param fieldName
     * @return TypeExpr
     */
    public abstract TypeExpr getFieldTypeExpr(FieldName fieldName);
   
    /**
     * Set the value node of the ith field.
     * @param i the index for the field within the record.
     * @param valueNode the new value node for the ith field in the record.
     */
    public abstract void setValueNodeAt(int i, ValueNode valueNode);

    /**
     * Renames a field of this value node.
     *
     * This function transmutes the record value node to a new type which contains the new field but
     * not the old. The value of this field is preserved in the process.
     *
     * Ex: Rename field "age" to "height" in record {age=1.0, code="Ras"} produces record {code="Ras", height=1.0}
     *
     * @param fieldName name of field to rename
     * @param newFieldName new name of field
     * @param builderHelper
     * @param transformer
     * @return RecordValueNode with the field renamed
     */
    public AbstractRecordValueNode renameField(FieldName fieldName, FieldName newFieldName, ValueNodeBuilderHelper builderHelper, ValueNodeTransformer transformer) {

        // Create the new record type.
        RecordType newRecordType = getRecordTypeForRenamedField(getTypeExpr(), fieldName, newFieldName);
       
        // Create new record value node by transmuting ourselves to the new record type
       
        AbstractRecordValueNode newRecordNode = (RecordValueNode)this.transmuteValueNode(builderHelper, transformer, newRecordType);
       
        // Now, the new record value node contains a brand new node for the new field.
        // We will now place the old field value in this node.
       
        ValueNode oldFieldNode = getValueAt(getFieldNames().indexOf(fieldName));
        newRecordNode.setValueNodeAt(newRecordNode.getFieldNames().indexOf(newFieldName), oldFieldNode.copyValueNode());
       
        return newRecordNode;
    }
   

    /**
     * this returns the type of the record as a non parametric type.
     * It is used for the value node input policies, as there is no reason to input a parametric input
     * @return non parametric record type
     */
    protected final TypeExpr getNonParametricType() {
        return getNonParametricType( getTypeExpr());
    }

    /**
     * converts all records types - including nested records to non parametric version
     * @param typeExpr the type to convert
     * @return non parametric version of the type
     */
    private TypeExpr getNonParametricType(TypeExpr typeExpr) {
        if (typeExpr instanceof RecordType) {
            Map<FieldName, TypeExpr> fieldsMap = ((RecordType)typeExpr).getHasFieldsMap();
            Map<FieldName, TypeExpr> newFieldsMap = new HashMap<FieldName, TypeExpr>();
            for(final Map.Entry<FieldName, TypeExpr> entry : fieldsMap.entrySet()) {
                newFieldsMap.put(entry.getKey(), getNonParametricType(entry.getValue()));
            }
           
            return TypeExpr.makeNonPolymorphicRecordType(newFieldsMap);

        } else {
            return typeExpr;
        }
    }

    /**
     * Create a new record type from the current type,
     * but having extra field newFieldName, and missing the field oldFieldName.
     * @param typeExpr the record type on which the new type will be based.
     * @param oldFieldName the field name to be replaced.
     * @param newFieldName the field name with which to replace the old field name.
     * @return the new record type.
     */
    public static RecordType getRecordTypeForRenamedField(TypeExpr typeExpr, FieldName oldFieldName, FieldName newFieldName) {

        Map<FieldName, TypeExpr> fieldNamesToTypeMap = new HashMap<FieldName, TypeExpr>();
        List<FieldName> existingFields = typeExpr.rootRecordType().getHasFieldNames();
        for (final FieldName existingFieldName : existingFields) {
            TypeExpr existingFieldType = typeExpr.rootRecordType().getHasFieldType(existingFieldName);

            fieldNamesToTypeMap.put(existingFieldName, existingFieldType);
        }
       
        TypeExpr fieldTypeExpr = fieldNamesToTypeMap.remove(oldFieldName);
        fieldNamesToTypeMap.put(newFieldName, fieldTypeExpr);

        return TypeExpr.makeNonPolymorphicRecordType(fieldNamesToTypeMap);
    }

}
TOP

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

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.