/**
   * 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();
    }
  }
Exemple #2
0
  /**
   * 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();
    }
  }