/** * Copyright 2011-2017 Asakusa Framework Team. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.asakusafw.vocabulary.flow.graph; import java.text.MessageFormat; /** * Represents a connection between {@link FlowElementPort}s. */ public final class PortConnection { private final FlowElementOutput upstream; private final FlowElementInput downstream; private boolean connected; private PortConnection(FlowElementOutput upstream, FlowElementInput downstream) { if (upstream == null) { throw new IllegalArgumentException("upstream must not be null"); //$NON-NLS-1$ } if (downstream == null) { throw new IllegalArgumentException("downstream must not be null"); //$NON-NLS-1$ } FlowElementPortDescription up = upstream.getDescription(); FlowElementPortDescription down = downstream.getDescription(); if (down.getDataType().equals(up.getDataType()) == false) { throw new IllegalArgumentException(MessageFormat.format( "Invalid data type {0} ({1}) -> {2} ({3})", //$NON-NLS-1$ up.getName(), up.getDataType(), down.getName(), down.getDataType())); } this.upstream = upstream; this.downstream = downstream; } /** * Connects between the two ports. * @param upstream the upstream port * @param downstream the downstream port * @throws IllegalArgumentException if the data type is not consistent, or some parameters are {@code null} */ public static void connect(FlowElementOutput upstream, FlowElementInput downstream) { if (upstream == null) { throw new IllegalArgumentException("upstream must not be null"); //$NON-NLS-1$ } if (downstream == null) { throw new IllegalArgumentException("downstream must not be null"); //$NON-NLS-1$ } if (isConnected(upstream, downstream)) { return; } connect0(upstream, downstream); } private static boolean isConnected(FlowElementOutput upstream, FlowElementInput downstream) { assert upstream != null; assert downstream != null; if (upstream.getConnected().size() > downstream.getConnected().size()) { for (PortConnection c : downstream.getConnected()) { if (c.getUpstream() == upstream) { return true; } } } else { for (PortConnection c : upstream.getConnected()) { if (c.getDownstream() == downstream) { return true; } } } return false; } private static void connect0(FlowElementOutput upstream, FlowElementInput downstream) { assert upstream != null; assert downstream != null; PortConnection connection = new PortConnection(upstream, downstream); upstream.register(connection); downstream.register(connection); connection.connected = true; } /** * Disposes this connection. * If this has been already disposed, this method will have no effects. */ public void disconnect() { if (isValid() == false) { return; } upstream.unregister(this); downstream.unregister(this); } /** * Returns whether this connection is valid or not. * @return {@code true} if this connection is valid, or {@code false} if this is {@link #disconnect() disposed} */ public boolean isValid() { return connected; } /** * Returns the upstream port. * @return the upstream port */ public FlowElementOutput getUpstream() { return upstream; } /** * Returns the downstream port. * @return the downstream port */ public FlowElementInput getDownstream() { return downstream; } @Override public String toString() { return MessageFormat.format( "{0} => {1}", //$NON-NLS-1$ getUpstream(), getDownstream()); } }