/** * If the argument is true, make the port an output port. If the argument is false, make the port * not an output port. In addition, if the container is an instance of Refinement, and the * argument is true, find the corresponding port of the controller and make it an input and not an * output. This makes it possible for the controller to see the outputs of the refinements. This * method overrides the base class to make the same change on the mirror ports in the controller * and state refinments. This method invalidates the schedule and resolved types of the director * of the container, if there is one. It is write-synchronized on the workspace, and increments * the version of the workspace. * * @param isOutput True to make the port an output. * @exception IllegalActionException If changing the port status is not permitted. */ public void setOutput(boolean isOutput) throws IllegalActionException { boolean disableStatus = _mirrorDisable; // check first that this isn't an input sibling port, // if it is then it *cannot* be set as an output too if (_hasSibling && isInput() && !isOutput()) { if (isOutput) { throw new InternalErrorException( "TransitionRefinementPort.setOutput:" + " cannot set input sibling port to be an output"); } else { return; } } try { _workspace.getWriteAccess(); if (_mirrorDisable || (getContainer() == null)) { // Have already called the super class. // This time, process the request. super.setOutput(isOutput); // now create a sibling if we // don't otherwise have one if (!_hasSibling && isOutput) { try { TransitionRefinement container = (TransitionRefinement) getContainer(); TransitionRefinementPort sibling = new TransitionRefinementPort(container, getName() + "_in"); sibling._hasSibling = true; sibling._mirrorDisable = true; // set attributes of sibling sibling.setInput(true); sibling.setMultiport(isMultiport()); sibling._mirrorDisable = false; // link the port relation should already exist // from this port's creation in newPort() String relationName = getName() + "Relation"; ModalModel model = (ModalModel) container.getContainer(); Relation relation = model.getRelation(relationName); if (relation != null) { sibling.link(relation); } _hasSibling = true; } catch (IllegalActionException ex) { throw new InternalErrorException( "TransitionRefinementPort.setOutput: Internal error: " + ex.getMessage()); } catch (NameDuplicationException ex) { throw new InternalErrorException( "TransitionRefinementPort.setOutput: Internal error: " + ex.getMessage()); } } } else { _mirrorDisable = true; boolean success = false; Nameable container = getContainer(); if (container != null) { Nameable modal = container.getContainer(); if (modal instanceof ModalModel) { Port port = ((ModalModel) modal).getPort(getName()); if (port instanceof IOPort) { ((IOPort) port).setOutput(isOutput); success = true; } } } if (!success) { super.setOutput(isOutput); } } } finally { _mirrorDisable = disableStatus; _workspace.doneWriting(); } }
/** * Create a new port with the specified name in the container of this controller, which in turn * creates a port in this controller and all the refinements. This method is write-synchronized on * the workspace. * * @param name The name to assign to the newly created port. * @return The new port. * @exception NameDuplicationException If the entity already has a port with the specified name. */ public Port newPort(String name) throws NameDuplicationException { try { _workspace.getWriteAccess(); ModalModel container = (ModalModel) getContainer(); if (_mirrorDisable == 1 || container == null) { // We are mirroring a change above in the hierarchy // (or there is no above in the hierarchy), // so we should not mirror this change upwards. // But we should mirror it downwards. ModalRefinementPort port = new ModalRefinementPort(this, name); // Create the links on the outside of the new port. if (container != null) { String relationName = name + "Relation"; Relation relation = container.getRelation(relationName); if (relation == null) { relation = container.newRelation(relationName); Port containerPort = container.getPort(name); containerPort.link(relation); } port.link(relation); } // Mirror the change downwards in the hierarchy. Iterator entities = entityList().iterator(); while (entities.hasNext()) { Entity entity = (Entity) entities.next(); if (entity instanceof RefinementActor) { if (entity.getPort(name) == null) { try { ((RefinementActor) entity).setMirrorDisable(1); entity.newPort(name); } finally { ((RefinementActor) entity).setMirrorDisable(0); } } } } return port; } else { // We are originating the change, or it originated from // below us in the hierarchy, and hence should delegate // it upwards. This will cause this newPort() method // to be called again by the container after it has // created its own port. That will result in the code // above executing because it will set _mirrorPort to 1 // on this port before doing the call. ModalRefinementPort containerPort = container == null ? null : (ModalRefinementPort) container.getPort(name); if (containerPort == null) { // The container does not have a mirror port. // Delegate upwards. // Note that this will result in the container // creating the port here by calling this // newPort() method. It will set my // _mirrorDisable to 1 before doing that, // and set it back to 0 after. container.newPort(name); return getPort(name); } else { // The container already has a mirror port, so // we cannot use it to create our port. // This can happen if the container was created first // and populated with its ports before this refinement // was created. ModalRefinementPort port = new ModalRefinementPort(this, name); // Create the link on the outside of the port. String relationName = name + "Relation"; Relation relation = container.getRelation(relationName); // The container should already have this relation, // but in case not, we create it. if (relation == null) { relation = container.newRelation(relationName); containerPort.link(relation); } port.link(relation); // Mirror the change downwards in the hierarchy. Iterator entities = entityList().iterator(); while (entities.hasNext()) { Entity entity = (Entity) entities.next(); if (entity instanceof RefinementActor) { if (entity.getPort(name) == null) { try { ((RefinementActor) entity).setMirrorDisable(1); entity.newPort(name); } finally { ((RefinementActor) entity).setMirrorDisable(0); } } } } return port; } } } catch (IllegalActionException ex) { // This exception should not occur, so we throw a runtime // exception. throw new InternalErrorException( "ModalRefinement.newPort: Internal error: " + ex.getMessage()); } finally { _mirrorDisable = 0; _workspace.doneWriting(); } }