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;
  }