/* * 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. */ /* * ArgumentValueContext.java * Creation date: May 1, 2003. * By: Edward Lam */ package org.openquark.gems.client; import java.util.HashMap; import java.util.Map; import org.openquark.cal.compiler.TypeExpr; import org.openquark.cal.valuenode.ValueNode; import org.openquark.cal.valuenode.ValueNodeBuilderHelper; import org.openquark.cal.valuenode.ValueNodeCommitHelper; import org.openquark.cal.valuenode.ValueNodeTransformer; import org.openquark.gems.client.Gem.PartInput; /** * This is a helper class for switching value nodes associated with free inputs. * To use, create an instance of this class with the appropriate mappings from input to valuenode, for the inputs under consideration. * Ensure that the inputs are disconnected, then call getInputSwitchValues() to obtain the value nodes appropriate to a value commit. * @author Edward Lam */ public class InputValueTypeSwitchHelper { /** The value node commit helper for this class. */ private final ValueNodeCommitHelper valueNodeCommitHelper; /** * Constructor for an InputValueTypeSwitchHelper * @param valueNodeCommitHelper the ValueNodeCommitHelper that will be used by this class. */ public InputValueTypeSwitchHelper(ValueNodeCommitHelper valueNodeCommitHelper) { this.valueNodeCommitHelper = valueNodeCommitHelper; } /** * Constructor for an InputValueTypeSwitchHelper * @param valueNodeBuilderHelper * @param valueNodeTransformer */ public InputValueTypeSwitchHelper(ValueNodeBuilderHelper valueNodeBuilderHelper, ValueNodeTransformer valueNodeTransformer) { this.valueNodeCommitHelper = new ValueNodeCommitHelper(valueNodeBuilderHelper, valueNodeTransformer); } /** * Get the new values that gem inputs would hold on a value switch. * * @param oldValueNode the top-level value node (held by an input) whose type is being switched * @param newValueNode the value node to which oldValueNode is being switched. * @param inputToValueNodeMap For inputs with which value nodes are associated, the mapping from input to * its value node. * @return Map A map from affected inputs to the new valuenodes they would have on switch. */ public Map<PartInput, ValueNode> getInputSwitchValues(ValueNode oldValueNode, ValueNode newValueNode, Map<PartInput, ValueNode> inputToValueNodeMap) { return getInputSwitchValues(oldValueNode, newValueNode, inputToValueNodeMap, null); } /** * Get the new values that gem inputs would hold on a value switch. * * @param oldValueNode the top-level value node (held by an input) whose type is being switched * @param newValueNode the value node to which oldValueNode is being switched. * @param inputToValueNodeMap For inputs with which value nodes are associated, the mapping from input to * its value node. * @param inputToUnconstrainedTypeMap Mapping from input to its associated unconstrained type. * If null, the input's type will be used directly. * @return Map A map from affected inputs to the new valuenodes they would have on switch. */ public Map<PartInput, ValueNode> getInputSwitchValues(ValueNode oldValueNode, ValueNode newValueNode, Map<PartInput, ValueNode> inputToValueNodeMap, Map<PartInput, TypeExpr> inputToUnconstrainedTypeMap) { // Mapping between inputs and their corresponding value nodes. Map<PartInput, ValueNode> inputValueNodeMap = new HashMap<PartInput, ValueNode>(inputToValueNodeMap); // Construct the reverse map. // Mapping between value nodes and their corresponding inputs. Map<ValueNode, Gem.PartInput> valueNodeInputMap = new HashMap<ValueNode, Gem.PartInput>(); for (final Map.Entry<PartInput, ValueNode> mapEntry : inputValueNodeMap.entrySet()) { PartInput nextInput = mapEntry.getKey(); valueNodeInputMap.put(mapEntry.getValue(), nextInput); } // Construct a map from value node to unconstrained type Map<ValueNode, TypeExpr> valueNodeToUnconstrainedTypeMap = new HashMap<ValueNode, TypeExpr>(); if (inputToUnconstrainedTypeMap == null) { for (final Map.Entry<PartInput, ValueNode> mapEntry : inputValueNodeMap.entrySet()) { Gem.PartInput nextInput = mapEntry.getKey(); valueNodeToUnconstrainedTypeMap.put(mapEntry.getValue(), nextInput.getType()); } } else { for (final Map.Entry<PartInput, ValueNode> mapEntry : inputValueNodeMap.entrySet()) { Gem.PartInput nextInput = mapEntry.getKey(); valueNodeToUnconstrainedTypeMap.put(mapEntry.getValue(), inputToUnconstrainedTypeMap.get(nextInput)); } } // Call a commit helper to do the grunt work. Map<ValueNode, ValueNode> commitValueMap = valueNodeCommitHelper.getCommitValues(oldValueNode, newValueNode, valueNodeToUnconstrainedTypeMap); // Construct the return map giving new values to the affected inputs. Map<PartInput, ValueNode> inputToNewValueMap = new HashMap<PartInput, ValueNode>(); for (final Map.Entry<ValueNode, ValueNode> mapEntry : commitValueMap.entrySet()){ ValueNode affectedValueNode = mapEntry.getKey(); Gem.PartInput affectedInput = valueNodeInputMap.get(affectedValueNode); ValueNode newInputValue = mapEntry.getValue(); inputToNewValueMap.put(affectedInput, newInputValue); } return inputToNewValueMap; } }