/**
   * Read the {@link Property} from the given {@link XMLStreamReader}
   *
   * @param r The {@link XMLStreamReader}
   * @param nsMap The {@link INamespaceMap} holding all data
   * @return The {@link Property}
   * @throws MalformedTLGLSyntaxException
   */
  private static Property readInProperty(XMLStreamReader r, INamespaceMap<String, String> nsMap)
      throws MalformedTLGLSyntaxException {
    String prName = null;
    QName prWSDLproperty = null;

    prName = BPEL4ChorReader.getStrAttribute(r, "name", true).toString();

    prWSDLproperty = BPEL4ChorReader.getQNAttribute(r, "WSDLproperty", nsMap, true);

    Property property = new Property(prName, prWSDLproperty);
    return property;
  }
  /**
   * Read the MessageLink from the given {@link XMLStreamReader}
   *
   * @param r The {@link XMLStreamReader}
   * @param nsMap The {@link INamespaceMap} holding all data
   * @return The {@link MessageLink}
   * @throws MalformedTLGLSyntaxException
   */
  private static MessageLink readInMessageLinkTL(
      XMLStreamReader r, INamespaceMap<String, String> nsMap) throws MalformedTLGLSyntaxException {
    MessageLink messageLink = new MessageLink();

    Object temp = BPEL4ChorReader.getStrAttribute(r, "name", false);
    if (temp != null) {
      messageLink.setName(temp.toString());
    }
    temp = null;
    temp = BPEL4ChorReader.getStrAttribute(r, "sender", false);
    if (temp != null) {
      messageLink.setSender(temp.toString());
    }

    List<String> tempList = BPEL4ChorReader.getStrsAttribute(r, "senders", false);
    if (tempList != null) {
      messageLink.setSenders(tempList);
    }
    temp = null;
    temp = BPEL4ChorReader.getStrAttribute(r, "sendActivity", false);
    if (temp != null) {
      messageLink.setSendActivity(temp.toString());
    }

    messageLink.setReceiver(BPEL4ChorReader.getStrAttribute(r, "receiver", true).toString());
    temp = null;
    temp = BPEL4ChorReader.getStrAttribute(r, "receiveActivity", false);
    if (temp != null) {
      messageLink.setReceiveActivity(temp.toString());
    }
    temp = null;
    temp = BPEL4ChorReader.getStrAttribute(r, "bindSenderTo", false);
    if (temp != null) {
      messageLink.setBindSenderTo(temp.toString());
    }

    messageLink.setMessageName(BPEL4ChorReader.getStrAttribute(r, "messageName", true).toString());

    tempList = BPEL4ChorReader.getStrsAttribute(r, "participantRefs", false);
    if (tempList != null) {
      messageLink.setParticipantRefs(tempList);
    }

    tempList = BPEL4ChorReader.getStrsAttribute(r, "copyParticipantRefsTo", false);
    if (tempList != null) {
      messageLink.setCopyParticipantRefsTo(tempList);
    }
    return messageLink;
  }
  /**
   * Read the ParticipantType from the given {@link XMLStreamReader}
   *
   * @param r The {@link XMLStreamReader}
   * @param nsMap The {@link INamespaceMap} holding all data
   * @return The read {@link ParticipantType}
   * @throws MalformedTLGLSyntaxException
   */
  private static ParticipantType readInParticipantType(
      XMLStreamReader r, INamespaceMap<String, String> nsMap) throws MalformedTLGLSyntaxException {
    ParticipantType participantType = new ParticipantType();
    participantType.setName(BPEL4ChorReader.getStrAttribute(r, "name", true).toString());

    QName pbd = BPEL4ChorReader.getQNAttribute(r, "participantBehaviorDescription", nsMap, false);
    if (pbd != null) {
      participantType.setParticipantBehaviorDescription(pbd);
    }

    Object pLang = BPEL4ChorReader.getStrAttribute(r, "processLanguage", false);
    if (pLang != null) {
      participantType.setProcessLanguage(pLang.toString());
    }
    return participantType;
  }
  /**
   * Read the {@link org.bpel4chor.model.grounding.impl.MessageLink} from the given {@link
   * XMLStreamReader}
   *
   * @param r The {@link XMLStreamReader}
   * @param nsMap The {@link INamespaceMap} holding all data
   * @param topology The {@link Topology}
   * @return The {@link org.bpel4chor.model.grounding.impl.MessageLink}
   * @throws MalformedTLGLSyntaxException
   */
  private static org.bpel4chor.model.grounding.impl.MessageLink readInMessageLinkGD(
      XMLStreamReader r, INamespaceMap<String, String> nsMap, Topology topology)
      throws MalformedTLGLSyntaxException {
    String mlName = null;
    QName mlportType = null;
    String mlOperationName = null;

    mlName = BPEL4ChorReader.getStrAttribute(r, "name", true).toString();

    mlOperationName = BPEL4ChorReader.getStrAttribute(r, "operation", true).toString();

    mlportType = BPEL4ChorReader.getQNAttribute(r, "portType", nsMap, true);

    org.bpel4chor.model.grounding.impl.MessageLink messageLink =
        new org.bpel4chor.model.grounding.impl.MessageLink(
            BPEL4ChorUtil.resolveTopologyMessageLinkByName(topology, mlName),
            mlportType,
            mlOperationName);
    return messageLink;
  }
  /**
   * Read ParticipantSet from given parser (also recursive)
   *
   * @param r The given {@link XMLStreamReader}
   * @param nsMap The used namespacemap
   * @return ParticipantSet
   * @throws MalformedTLGLSyntaxException
   * @throws XMLStreamException
   */
  private static ParticipantSet readInParticipantSet(
      XMLStreamReader r, INamespaceMap<String, String> nsMap)
      throws MalformedTLGLSyntaxException, XMLStreamException {
    ParticipantSet participantSet = null;

    String psName = null;
    String psType = null;
    if (!(r.getEventType() == XMLStreamConstants.END_ELEMENT)) {

      psName = BPEL4ChorReader.getStrAttribute(r, "name", true).toString();
      psType = BPEL4ChorReader.getStrAttribute(r, "type", true).toString();

      participantSet = new ParticipantSet(psName, psType);

      QName scope = BPEL4ChorReader.getQNAttribute(r, "scope", nsMap, false);
      if (scope != null) {
        participantSet.setScope(scope);
      }

      List<QName> forEachs = BPEL4ChorReader.getQNsAttribute(r, "forEach", nsMap, false);
      if ((forEachs != null) && (forEachs.size() > 0)) {
        participantSet.setForEach(forEachs);
      }
    }

    r.nextTag();
    // Read (sub)participantSet(s)
    if (r.hasNext() && r.getLocalName().equals("participantSet")) {
      while (r.hasNext() && r.getLocalName().equals("participantSet")) {
        ParticipantSet participantSetSub = BPEL4ChorReader.readInParticipantSet(r, nsMap);
        participantSet.getParticipantSetList().add(participantSetSub);
      }
      r.nextTag();
    }

    // Read (sub)participant(s)
    if (r.hasNext() && r.getLocalName().equals("participant")) {
      while (r.hasNext() && r.getLocalName().equals("participant")) {

        Participant participant = BPEL4ChorReader.readInParticipant(r, nsMap, true);
        participantSet.getParticipantList().add(participant);
      }
      r.nextTag();
    }
    return participantSet;
  }
  /**
   * Read Participant from given {@link XMLStreamReader}
   *
   * @param r The {@link XMLStreamReader}
   * @param nsMap the Namespace map with all needed data
   * @param contained Flag indicating if participant is contained in {@link ParticipantSet}
   * @return {@link Participant}
   * @throws MalformedTLGLSyntaxException
   * @throws XMLStreamException
   */
  private static Participant readInParticipant(
      XMLStreamReader r, INamespaceMap<String, String> nsMap, boolean contained)
      throws MalformedTLGLSyntaxException, XMLStreamException {
    Participant participant = new Participant();
    if (!(r.getEventType() == XMLStreamConstants.END_ELEMENT)) {
      participant.setName(BPEL4ChorReader.getStrAttribute(r, "name", true).toString());

      participant.setType(BPEL4ChorReader.getStrAttribute(r, "type", true).toString());
      if (!contained) {

        List<String> selects = BPEL4ChorReader.getStrsAttribute(r, "selects", false);
        if (selects != null) {
          participant.setSelects(selects);
        }
      } else {
        // Our Participant is contained in a Participant Set
        List<QName> forEachs = BPEL4ChorReader.getQNsAttribute(r, "forEach", nsMap, false);
        if (forEachs != null) {
          participant.setForEach(forEachs);
        }

        ContainmentValue value =
            (ContainmentValue) BPEL4ChorReader.getStrAttribute(r, "containment", false);
        if (value != null) {
          participant.setContainment(value);
        }
      }

      QName scope = BPEL4ChorReader.getQNAttribute(r, "scope", nsMap, false);
      if (scope != null) {
        participant.setScope(scope);
      }
    }
    r.nextTag();
    r.nextTag();
    return participant;
  }
  /**
   * Read in the grounding file from the given InputStream
   *
   * @param inputStream The {@link InputStream} for reading
   * @param topology The {@link Topology} belonging to the Grounding
   * @return The read {@link Grounding}
   */
  public static Grounding readGrounding(InputStream inputStream, Topology topology) {
    XMLInputFactory factory = XMLInputFactory.newInstance();
    XMLStreamReader parser;
    Grounding grounding = null;

    try {
      parser = factory.createXMLStreamReader(inputStream);

      if ((parser.getEventType() == XMLStreamConstants.START_DOCUMENT)) {
        parser.nextTag();
      }

      if (parser.getLocalName().equals("grounding")
          && !(parser.getEventType() == XMLStreamConstants.END_ELEMENT)) {

        grounding = new Grounding(topology);
        for (int i = 0; i < parser.getNamespaceCount(); i++) {
          if (parser.getNamespacePrefix(i) != null) {
            grounding
                .getNamespaceMap()
                .addNamespace(parser.getNamespaceURI(i), parser.getNamespacePrefix(i));
          }
        }

        grounding.setTargetNamespace(
            BPEL4ChorReader.getStrAttribute(parser, "targetNamespace", true).toString());

        parser.nextTag();
      }
      if (parser.getLocalName().equals("messageLinks")) {

        parser.nextTag();
        while (parser.hasNext() && parser.getLocalName().equals("messageLink")) {
          if (!(parser.getEventType() == XMLStreamConstants.END_ELEMENT)) {

            grounding
                .getMessageLinks()
                .add(
                    BPEL4ChorReader.readInMessageLinkGD(
                        parser, grounding.getNamespaceMap(), topology));
          }
          parser.nextTag();
        }
        parser.nextTag();
      }

      if (parser.getLocalName().equals("participantRefs")) {
        parser.nextTag();
        while (parser.hasNext() && parser.getLocalName().equals("participantRef")) {
          if (!(parser.getEventType() == XMLStreamConstants.END_ELEMENT)) {

            grounding
                .getParticipantRefs()
                .add(BPEL4ChorReader.readInParticipantRef(parser, grounding.getNamespaceMap()));
          }
          parser.nextTag();
        }
        parser.nextTag();
      }

      if (parser.getLocalName().equals("properties")) {
        parser.nextTag();
        while (parser.hasNext() && parser.getLocalName().equals("property")) {

          if (!(parser.getEventType() == XMLStreamConstants.END_ELEMENT)) {

            grounding
                .getProperties()
                .add(BPEL4ChorReader.readInProperty(parser, grounding.getNamespaceMap()));
          }
          parser.nextTag();
        }
        parser.nextTag();
      }

    } catch (XMLStreamException e) {
      e.printStackTrace();

    } catch (MalformedTLGLSyntaxException e) {
      e.printStackTrace();
    }

    return grounding;
  }
  /**
   * Read in the topology file from the given InputStream
   *
   * @param inputStream The {@link InputStream} for reading
   * @return read {@link Topology}
   */
  public static Topology readTopology(InputStream inputStream) {

    XMLInputFactory factory = XMLInputFactory.newInstance();
    XMLStreamReader parser;
    Topology topology = null;
    try {
      parser = factory.createXMLStreamReader(inputStream);
      if ((parser.getEventType() == XMLStreamConstants.START_DOCUMENT)) {
        parser.nextTag();
      }

      // Read Topology Head
      if (parser.getLocalName().equals("topology")
          && !(parser.getEventType() == XMLStreamConstants.END_ELEMENT)) {

        topology = new Topology();
        for (int i = 0; i < parser.getNamespaceCount(); i++) {
          if (parser.getNamespacePrefix(i) != null) {
            topology
                .getNamespaceMap()
                .addNamespace(parser.getNamespaceURI(i), parser.getNamespacePrefix(i));
          }
        }

        topology.setName(BPEL4ChorReader.getStrAttribute(parser, "name", true).toString());

        topology.setTargetNamespace(
            BPEL4ChorReader.getStrAttribute(parser, "targetNamespace", true).toString());

        parser.nextTag();
      }

      // Read participantTypes
      if (parser.getLocalName().equals("participantTypes")) {

        parser.nextTag();

        // Read participantType(s)
        while (parser.hasNext() && parser.getLocalName().equals("participantType")) {
          if (!(parser.getEventType() == XMLStreamConstants.END_ELEMENT)) {

            ParticipantType participantType =
                BPEL4ChorReader.readInParticipantType(parser, topology.getNamespaceMap());
            topology.getParticipantTypes().add(participantType);
          }
          parser.nextTag();
        }
        parser.nextTag();
      }

      // Read participants
      if (parser.getLocalName().equals("participants")) {

        parser.nextTag();

        // Read participant(s)
        if (parser.hasNext() && parser.getLocalName().equals("participant")) {
          while (parser.hasNext() && parser.getLocalName().equals("participant")) {
            Participant participant =
                BPEL4ChorReader.readInParticipant(parser, topology.getNamespaceMap(), false);
            topology.getParticipants().add(participant);
          }
          if (parser.getLocalName() != "participantSet") {
            parser.nextTag();
          }
        }
        // Read participantSet(s)
        if (parser.hasNext() && parser.getLocalName().equals("participantSet")) {
          while (parser.hasNext() && parser.getLocalName().equals("participantSet")) {
            ParticipantSet participantSet =
                BPEL4ChorReader.readInParticipantSet(parser, topology.getNamespaceMap());
            topology.getParticipantSets().add(participantSet);
          }
          parser.nextTag();
        }
      }

      // Read messageLinks
      if (parser.getLocalName().equals("messageLinks")) {

        parser.nextTag();

        // Read messageLink(s)
        while (parser.hasNext() && parser.getLocalName().equals("messageLink")) {
          if (!(parser.getEventType() == XMLStreamConstants.END_ELEMENT)) {

            MessageLink messageLink =
                BPEL4ChorReader.readInMessageLinkTL(parser, topology.getNamespaceMap());

            topology.getMessageLinks().add(messageLink);
          }
          parser.nextTag();
        }
        parser.nextTag();
      }

      int event = parser.next();
      if (event == XMLStreamConstants.END_DOCUMENT) {
        parser.close();
      }
    } catch (XMLStreamException e) {
      e.printStackTrace();
    } catch (MalformedTLGLSyntaxException e) {
      e.printStackTrace();
    }

    return topology;
  }