// Connect all input ports to their sources and return all connections formed. public List<ConnectionValue> connect() throws UndeclaredIdentifierException, UndeclaredAttributeException, InvalidAttributeException, TypeMismatchException { List<ConnectionValue> connections = new LinkedList<>(); for (Map.Entry<String, FuturePortValue> e : futureInputPorts.entrySet()) { String inputPortName = e.getKey(); FuturePortValue source = e.getValue(); PortValue sourcePort = source.getPort(); PortValue targetPort = node.getPort(inputPortName); // TODO connection attributes; for now we assume none Map<String, Value> attrs = new HashMap<>(); ConnectionValue conn = new ConnectionValue(sourcePort, targetPort, attrs); connections.add(conn); } return connections; }
@Override public void elaborate() throws Exception { // prevent infinite recursive elaboration if (futureOutputPorts != null) { return; } log.debug("type signature is " + signature.toString()); // decompose signature into (input) -> (output) TupleTypeValue inputType = (TupleTypeValue) signature.getInputType(); TupleTypeValue outputType = (TupleTypeValue) signature.getOutputType(); // construct values for all future output ports // simultaneously build a collection of all input port names Set<String> inputPortNames = new HashSet<>(); Set<String> outputPortNames = new HashSet<>(); inputPortNames.addAll(nodeType.getPorts().keySet()); MappedArray<String, Value> futurePortMap = new MappedArray<>(); for (MappedArray<String, TypeValue>.Entry typeEntry : outputType.getSubtypes()) { String outputPortName = typeEntry.getKey(); PortTypeValue outputPortType = nodeType.getPorts().get(outputPortName); FuturePortValue futurePort = new FuturePortValue(this, outputPortName, outputPortType); futurePortMap.put(outputPortName, futurePort); inputPortNames.remove(outputPortName); outputPortNames.add(outputPortName); } futureOutputPorts = new TupleValue(outputType, futurePortMap); inputEdge.getSource().elaborate(); Value inputValue = inputEdge.getSource().getValue(); TupleValue input = (TupleValue) inputValue; // now we have enough information to disassemble `input` // into attributes and (future) input ports Map<String, Value> nodeAttrs = new HashMap<>(); Map<String, Map<String, Value>> portAttrs = new HashMap<>(); for (String inputPortName : inputPortNames) { PortTypeValue inputPortType = nodeType.getPorts().get(inputPortName); Value inputPortValue = input.getEntry(inputPortName); // if the port has attributes, this is a tuple // (0: FuturePortValue, 1: (attributes)) // otherwise, this is just a FuturePortValue FuturePortValue futurePort; Map<String, Value> inputPortAttrs; if (inputPortType.getAttributes().isEmpty()) { // in the case where a single output port is directly used as input, // this is a tuple of size 1 that needs to be "unwrapped" first futurePort = unwrapPort(inputPortValue); futureInputPorts.put(inputPortName, futurePort); inputPortAttrs = new HashMap<>(); // no attributes } else { TupleValue inputPortTuple = (TupleValue) inputPortValue; // same story here about unwrapping the port futurePort = unwrapPort(inputPortTuple.getEntry(0)); TupleValue attributesValue = (TupleValue) inputPortTuple.getEntry(1); // TODO this can probably be done better, it assumes that all tuple values are named inputPortAttrs = MappedArray.toMap(attributesValue.getEntries()); } futureInputPorts.put(inputPortName, futurePort); portAttrs.put(inputPortName, inputPortAttrs); } // we must also get output port attributes, which appear as function inputs for (String outputPortName : outputPortNames) { PortTypeValue outputPortType = nodeType.getPorts().get(outputPortName); Map<String, Value> outputPortAttrs; if (outputPortType.getAttributes().isEmpty()) { outputPortAttrs = new HashMap<>(); // no attributes } else { TupleValue attributesValue = (TupleValue) input.getEntry(outputPortName); outputPortAttrs = MappedArray.toMap(attributesValue.getEntries()); } portAttrs.put(outputPortName, outputPortAttrs); } for (String attrName : nodeType.getAttributes().keySet()) { Value attrValue = input.getEntry(attrName); nodeAttrs.put(attrName, attrValue); } node = new NodeValue(nodeType, nodeAttrs, portAttrs); }
@Override public ExpressionVertex copy(ExpressionGraph g, Map<ExpressionEdge, ExpressionEdge> edgeMap) { Preconditions.checkArgument(edgeMap.containsKey(inputEdge)); return new NodeValueVertex(g, nodeType, signature, edgeMap.get(inputEdge)); }