public boolean addNode(T node) {
   if (mProcessNodes.add(node)) {
     node.setOwnerModel(this.asM());
     return true;
   }
   return false;
 }
  public static <T extends ProcessNode<T, M>, M extends ProcessModelBase<T, M>> M deserialize(
      final DeserializationFactory<T, M> factory, final M processModel, final XmlReader in)
      throws XmlException {

    XmlReaderUtil.skipPreamble(in);
    final QName elementName = ELEMENTNAME;
    assert XmlReaderUtil.isElement(in, elementName)
        : "Expected " + elementName + " but found " + in.getLocalName();
    for (int i = in.getAttributeCount() - 1; i >= 0; --i) {
      processModel.deserializeAttribute(
          in.getAttributeNamespace(i), in.getAttributeLocalName(i), in.getAttributeValue(i));
    }

    EventType event = null;
    loop:
    while (in.hasNext() && event != XmlStreaming.END_ELEMENT) {
      switch ((event = in.next())) {
        case START_ELEMENT:
          if (processModel.deserializeChild(factory, in)) {
            continue loop;
          }
          XmlReaderUtil.unhandledEvent(in);
          break;
        case TEXT:
        case CDSECT:
          if (false) {
            continue loop;
          }
        default:
          XmlReaderUtil.unhandledEvent(in);
      }
    }

    for (final T node : processModel.getModelNodes()) {
      for (final Identifiable pred : node.getPredecessors()) {
        final T predNode = processModel.getNode(pred);
        if (predNode != null) {
          predNode.addSuccessor(node);
        }
      }
    }
    return processModel;
  }
 public T setNode(final int pos, final T newValue) {
   final T oldValue = mProcessNodes.set(pos, newValue);
   newValue.setOwnerModel(asM());
   oldValue.setSuccessors(Collections.<Identifiable>emptySet());
   oldValue.setPredecessors(Collections.<Identifiable>emptySet());
   oldValue.setOwnerModel(null);
   newValue.resolveRefs();
   for (Identifiable pred : newValue.getPredecessors()) {
     getNode(pred).addSuccessor(newValue);
   }
   for (Identifiable suc : newValue.getSuccessors()) {
     getNode(suc).addPredecessor(newValue);
   }
   return oldValue;
 }
 /**
  * Normalize the process model. By default this may do nothing.
  *
  * @return The model (this).
  */
 public M normalize(SplitFactory<? extends T, M> splitFactory) {
   ensureIds();
   // Make all nodes directly refer to other nodes.
   for (T childNode : mProcessNodes) {
     childNode.resolveRefs();
   }
   for (T childNode : mProcessNodes) {
     // Create a copy as we are actually going to remove all successors, but need to keep the list
     ArrayList<Identifiable> successors = new ArrayList<>(childNode.getSuccessors());
     if (successors.size() > 1 && !(childNode instanceof Split)) {
       for (Identifiable suc2 : successors) { // Remove the current node as predecessor.
         ProcessNode<?, ?> suc = (ProcessNode) suc2;
         suc.removePredecessor(childNode);
         childNode.removeSuccessor(suc); // remove the predecessor from the current node
       }
       // create a new join, this should
       Split<? extends T, M> newSplit = splitFactory.createSplit(asM(), successors);
       childNode.addSuccessor(newSplit);
     }
   }
   return this.asM();
 }