/* * 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. */ /* * OutputPolicy.java * Created: Jan 19, 2004 at 12:15:01 PM * By: Raymond Cypher */ package org.openquark.cal.compiler.io; import org.openquark.cal.compiler.QualifiedName; import org.openquark.cal.compiler.SourceModel; import org.openquark.cal.compiler.SourceModelUtilities; import org.openquark.cal.compiler.SourceModel.Expr; import org.openquark.cal.module.Cal.Collections.CAL_List; import org.openquark.cal.module.Cal.Core.CAL_Prelude; /** * The OutputPolicy class contains the information necessary for * the runtime to marshal a CAL output value into to the Java * domain. * @author RCypher * @author mbyne */ public final class OutputPolicy { /** * This is the source model expression for outputting to an Iterator: (Prelude.output # List.toJIterator) */ private static final SourceModel.Expr iteratorValueOutputExpr = SourceModel.Expr.BinaryOp.Compose.make( SourceModel.Expr.makeGemCall(CAL_Prelude.Functions.output), SourceModel.Expr.makeGemCall(CAL_List.Functions.toJIterator)); /** * This is the source model expression for outputting to a CAL value: * (Prelude.output # Prelude.toCalValue) */ private static final SourceModel.Expr calValueOutputExpr = SourceModel.Expr.BinaryOp.Compose.make( SourceModel.Expr.makeGemCall(CAL_Prelude.Functions.output), SourceModel.Expr.makeGemCall(CAL_Prelude.Functions.toCalValue)); /** * This is the source model for outputting a CAL value strictly (i.e. the value is evaluated to * weak-head normal form). This is sometimes needed when the external Java client wants to control the * order of side effects in a series of CAL computations. * * (Prelude.outputCalValueStrict # Prelude.toCalValue) */ private static final SourceModel.Expr strictCalValueOutputExpr = SourceModel.Expr.BinaryOp.Compose.make( SourceModel.Expr.makeGemCall(CAL_Prelude.Functions.outputCalValueStrict), SourceModel.Expr.makeGemCall(CAL_Prelude.Functions.toCalValue)); /** Compose the output with the Prelude.output function */ public static final OutputPolicy DEFAULT_OUTPUT_POLICY = make(SourceModel.Expr.makeGemCall(CAL_Prelude.Functions.output)); /** * Compose the output with (Prelude.output # List.toJIterator). * This will output a CAL list to a Java Object that can then be cast to a java.util.Iterator. * The iterator can then be used to allow the Java client to marshal the elements of the CAL list under Java's control. */ public static final OutputPolicy ITERATOR_OUTPUT_POLICY = make (iteratorValueOutputExpr); /** * Compose the output with ((Prelude.output :: Prelude.CalValue -> Prelude.JObject) # Prelude.toCalValue). * This has the effect of outputting the CAL value to Java code without modification as an "opaque" value. * This value can then be passed back into CAL at some later point for further computations. * The value itself is not evaluated i.e. is "untouched". */ public static final OutputPolicy CAL_VALUE_OUTPUT_POLICY = make (calValueOutputExpr); /** * Compose the output with ((Prelude.outputCalValueStrict # Prelude.toCalValue). * This has the effect of outputting the CAL value to Java code without modification as an "opaque" value. * This value can then be passed back into CAL at some later point for further computations. * The value itself is first evaluated to weak-head normal form. This is in contrast to the CAL_VALUE_OUTPUT_POLICY * which is purely lazy. This is sometimes needed when the external Java client wants to control the * order of side effects in a series of CAL computations. */ public static final OutputPolicy STRICT_CAL_VALUE_OUTPUT_POLICY = make (strictCalValueOutputExpr); /** * This is a typed output policy for Prelude.Boolean values. It should be used instead of * the default output policy when the functionalAgent is polymorphic * and it needs to be bound to a Boolean. */ public static final OutputPolicy BOOLEAN_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Boolean)); /** * This is a typed output policy for Prelude.Char values. It should be used instead of * the default output policy when the functionalAgent is polymorphic * and it needs to be bound to a Char. */ public static final OutputPolicy CHAR_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Char)); /** * This is a typed output policy for Prelude.Byte values. It should be used instead of * the default output policy when the functionalAgent is polymorphic * and it needs to be bound to a Byte. */ public static final OutputPolicy BYTE_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Byte)); /** * This is a typed output policy for Prelude.Short values. It should be used instead of * the default output policy when the functionalAgent is polymorphic * and it needs to be bound to a Short. */ public static final OutputPolicy SHORT_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Short)); /** * This is a typed output policy for Prelude.Int values. It should be used instead of * the default output policy when the functionalAgent is polymorphic * and it needs to be bound to an Int. */ public static final OutputPolicy INT_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Int)); /** * This is a typed input policy for Prelude.Long values. It should be used instead of * the default input policy when the functionalAgent is polymorphic * and it needs to be bound to a Long. */ public static final OutputPolicy LONG_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Long)); /** * This is a typed input policy for Prelude.Float values. It should be used instead of * the default input policy when the functionalAgent is polymorphic * and it needs to be bound to a Double. */ public static final OutputPolicy FLOAT_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Float)); /** * This is a typed input policy for Prelude.Double values. It should be used instead of * the default input policy when the functionalAgent is polymorphic * and it needs to be bound to a Double. */ public static final OutputPolicy DOUBLE_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Double)); /** * This is a typed output policy for Prelude.Double values. It should be used instead of * the default output policy when the functionalAgent is polymorphic * and it needs to be bound to a Integer. */ public static final OutputPolicy INTEGER_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Integer)); /** * This is a typed output policy for Prelude.Decimal values. It should be used instead of * the default output policy when the functionalAgent is polymorphic * and it needs to be bound to a Decimal. */ public static final OutputPolicy DECIMAL_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Decimal)); /** * This is a typed input policy for Prelude.String values. It should be used instead of * the default input policy when the functionalAgent is polymorphic * and it needs to be bound to a String. */ public static final OutputPolicy STRING_OUTPUT_POLICY = makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.String)); /** * This is the source model expression for the marshaler. It cannot be null. */ private final SourceModel.Expr marshaler; /** * Constructs an OutputPolicy with an expression in source model * representation specifying the marshaler. * * @param marshaler * the marshaler that converts a CAL output value into the Java * domain */ private OutputPolicy (SourceModel.Expr marshaler) { if (marshaler == null) { throw (new NullPointerException ("The marshaler must be non-null for an OutputPolicy.")); } this.marshaler = marshaler; } /** * This is a factory method for creating a typed default output policy * It should be used when the output is ambiguous (e.g [a]) and an explicit type is required. * If the output is non-ambiguous it is easier to use DEFAULT_OUTPUT_POLICY * @param typeSignature the CAL type of the input * @return the input policy * * @see #DEFAULT_OUTPUT_POLICY */ public static OutputPolicy makeTypedDefaultOutputPolicy(SourceModel.TypeExprDefn typeSignature) { return make(SourceModel.Expr.ExprTypeSignature.make( SourceModel.Expr.makeGemCall(CAL_Prelude.Functions.output), SourceModel.TypeSignature.make( SourceModel.TypeExprDefn.Function.make( typeSignature, SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.JObject))))); } /** * This is a factory method for creating a typed CAL_VALUE_OUTPUT_POLICY. * It should be used when the output is ambiguous (requires type class overloading resolution) * and an explicit type is required. * If the output is non-ambiguous it is easier to use CAL_VALUE_OUTPUT_POLICY * @param type the CAL type of the output * @return the input policy * * @see #CAL_VALUE_OUTPUT_POLICY */ public static OutputPolicy makeTypedCalValueOutputPolicy(SourceModel.TypeExprDefn type) { return make(SourceModel.Expr.ExprTypeSignature.make( calValueOutputExpr, SourceModel.TypeSignature.make( SourceModel.TypeExprDefn.Function.make( type, SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.JObject) )))); } /** * This is a factory method for creating a typed STRICT_CAL_VALUE_OUTPUT_POLICY * It should be used when the output is ambiguous (requires type class overloading resolution) * and an explicit type is required. * If the output is non-ambiguous it is easier to use STRICT_CAL_VALUE_OUTPUT_POLICY * @param type the CAL type of the output * @return the input policy * * @see #STRICT_CAL_VALUE_OUTPUT_POLICY */ public static OutputPolicy makeTypedStrictCalValueOutputPolicy(SourceModel.TypeExprDefn type) { return make(SourceModel.Expr.ExprTypeSignature.make( strictCalValueOutputExpr, SourceModel.TypeSignature.make( SourceModel.TypeExprDefn.Function.make( type, SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.JObject) )))); } /** * This is a factory method for creating a typed Iterator output policy * It should be used when the output is ambiguous (e.g [a]) and an explicit type is required. * If the output is non-ambiguous it is easier to use ITERATOR_OUTPUT_POLICY * @param type the CAL type of the input * @return the output policy * * @see #ITERATOR_OUTPUT_POLICY */ public static OutputPolicy makeTypedIteratorOutputPolicy(SourceModel.TypeExprDefn type) { return make(SourceModel.Expr.ExprTypeSignature.make( iteratorValueOutputExpr, SourceModel.TypeSignature.make( SourceModel.TypeExprDefn.Function.make( type, SourceModel.TypeExprDefn.TypeCons.make(CAL_List.TypeConstructors.JIterator))))); } /** * Makes an output policy by parsing a string representing the marshaler * @param marshaler a string representing the marshaler * @return the new output policy. */ public static OutputPolicy make(String marshaler) { if (marshaler == null) { throw (new NullPointerException ("The marshaler must be non-null for an OutputPolicy.")); } //parse the marshaler Expr marshalerExpr = SourceModelUtilities.TextParsing.parseExprIntoSourceModel(marshaler); if (marshalerExpr == null) { throw (new IllegalArgumentException("The marshaler cannot be parsed: " + marshaler)); } return new OutputPolicy(marshalerExpr); } /** * * Makes an OutputPolicy with specified marshaler. * @param marshaler source model expression describing how to marshal a CAL output to a Java object * @return the new output policy */ public static OutputPolicy make(Expr marshaler) { return new OutputPolicy(marshaler); } /** * Makes an OutputPolicy with a qualified name specifying the marshaler. * * @param marshaler * the marshaler that converts a CAL output value into the Java domain */ public static OutputPolicy makeWithNamedMarshaler(QualifiedName marshaler) { return make(marshaler.getQualifiedName()); } /** * Get the marshaler. This cannot be null. * @return the marshaler */ public SourceModel.Expr getMarshaler() { return marshaler; } /** * {@inheritDoc} */ @Override public String toString () { return "OutputPolicy: marshaler = " + getMarshaler(); } }