@Override
  public void setCWMDocument(String path) {
    try {
      // Create a fresh unaltered document from the path
      // which resembles the content saved inside
      // the CWM XML file
      cwmDocument = new CWMDocument(path);
      document = cwmDocument.getDocument();

      // XMLOutputter outputter = new
      // XMLOutputter(Format.getPrettyFormat());
      // ByteArrayOutputStream bout = new ByteArrayOutputStream();
      // try {
      // outputter.output(document.getRootElement(), bout);
      // bout.write("\n".getBytes());
      // log.trace(bout.toString());
      // } catch (IOException e) {
      // e.printStackTrace();
      // }

      // This looses namespaces
      // document = cwmDocument.getOriginal();

      // Document is altered severly once loaded into the
      // editor so cwmDocument.getDocument() gives you a
      // completely different CWMDocument than what has
      // been read from file
      // document = cwmDocument.getDocument();
    } catch (JDOMException e) {
      log.error(e.getMessage(), e);
    } catch (IOException e) {
      log.error(e.getMessage(), e);
    }
  }
  @Override
  public void setCWMDocument(CWMDocument cwmDocument) {

    this.document = cwmDocument.getDocument();
    this.cwmDocument = cwmDocument;

    // XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
    // ByteArrayOutputStream bout = new ByteArrayOutputStream();
    // try {
    // outputter.output(cwmDocument.getDocument().getRootElement(), bout);
    // bout.write("\n".getBytes());
    // log.trace(bout.toString());
    // } catch (IOException e) {
    // e.printStackTrace();
    // }

    // To set the document directly is a mistake as the
    // document is altered via the editor from it´s
    // original state once it is loaded into the editor
    // this.cwmDocument = cwmDocument;

    // This looses namespaces
    // Requesting the original document is also a mistake
    // as the original document is also altered once loaded
    // document = cwmDocument.getOriginal();
  }
  private void searchForSemanticAnnotations(
      List<SemanticAnnotationImpl> list,
      Element element,
      String path,
      String parentNamespaceURI,
      String schema,
      HashMap<String, String> namespaceNames,
      HashMap<String, HashMap<String, Integer>> namespaceCounts) {

    KeyValuePair<String, String> namespaceNamePair = new KeyValuePair();
    KeyValuePair<String, Integer> indexPair = new KeyValuePair();

    // In java references are copied and passed by value! Integer objects
    // do not have a setter. This means a Integer object cannot be used
    // to simulate call by ref semantics. A KeyValuePair class has been
    // introduced for that purpose. It has a setter method.
    estimateNamespaceAndIndex(
        element, indexPair, namespaceNamePair, parentNamespaceURI, namespaceCounts, namespaceNames);

    // update XPath
    String selfPath;
    if (null == path) {

      if ((null != namespaceNamePair.getValue()) && (0 != namespaceNamePair.getValue().length())) {
        selfPath =
            "/descendant::"
                + namespaceNamePair.getValue()
                + ":"
                + element.getName()
                + "["
                + indexPair.getValue()
                + "]";
      } else {
        selfPath = "/descendant::" + element.getName() + "[" + indexPair.getValue() + "]";
      }

    } else {

      if ((null != namespaceNamePair.getValue()) && (0 != namespaceNamePair.getValue().length())) {
        selfPath =
            path
                + "/descendant::"
                + namespaceNamePair.getValue()
                + ":"
                + element.getName()
                + "["
                + indexPair.getValue()
                + "]";
      } else {
        selfPath = path + "/descendant::" + element.getName() + "[" + indexPair.getValue() + "]";
      }
    }

    // search for semantic annotation among the attributes
    for (Object o : element.getAttributes()) {

      Attribute att = (Attribute) o;

      // TODO: this is dependent on attribute order! If the value
      // attribute
      // precedes it´s tag attribute, this wont work any more!

      // process modelReference which is stored as attribute combination
      // of a tag and a value attribute inside a CWM:TaggedValue
      // XML element
      if ((att.getName().equalsIgnoreCase("tag"))
          && att.getValue().equalsIgnoreCase("modelReference")) {
        readingModelReference = true;
      }
      if (att.getName().equalsIgnoreCase("value") && readingModelReference) {
        modelReference = att.getValue();
        readingModelReference = false;
      }

      // liftingSchemaMapping
      if ((att.getName().equalsIgnoreCase("tag"))
          && att.getValue().equalsIgnoreCase("liftingSchemaMapping")) {
        readingLiftingSchemaMapping = true;
      }
      if (att.getName().equalsIgnoreCase("value") && readingLiftingSchemaMapping) {
        liftingSchemaMapping = att.getValue();
        readingLiftingSchemaMapping = false;
      }

      // loweringSchemaMapping
      if ((att.getName().equalsIgnoreCase("tag"))
          && att.getValue().equalsIgnoreCase("loweringSchemaMapping")) {
        readingLoweringSchemaMapping = true;
      }
      if (att.getName().equalsIgnoreCase("value") && readingLoweringSchemaMapping) {
        loweringSchemaMapping = att.getValue();
        readingLoweringSchemaMapping = false;
      }
    }

    if (null == modelType) {
      modelType = "";
    }
    if (null == schemaType) {
      schemaType = "";
    }

    // if the recursion runs into the scope of a new schema,
    // store the schema name so that it can be put into the
    // annotations created by this method
    String localSchema = null;
    if (null != schema) {
      localSchema = new String(schema);
    }

    // log.trace(element.getName());

    if (element.getName().toLowerCase().contains("Schema".toLowerCase())) {
      localSchema = element.getAttributeValue("name");
    } else if (element.getName().toLowerCase().contains("Stereotype".toLowerCase())) {
      String nameAttributeValue = element.getAttributeValue("name");
      if ("OWL".equalsIgnoreCase(nameAttributeValue)) {
        modelType = "OWL";
      } else if ("WSML".equalsIgnoreCase(nameAttributeValue)) {
        modelType = "WSML";
      }
    } else if (element.getName().toLowerCase().contains("Table".toLowerCase())) {
      // must be field of class as this step of the recursion does
      // not create the annotation object and hence any local variables
      // get lost
      this.schemaType = "Table";
      this.tableName = element.getAttributeValue("name");
    } else if (element.getName().toLowerCase().contains("Column".toLowerCase())) {
      this.schemaType = "Column";
      this.columnName = element.getAttributeValue("name");
    }

    List elementList = element.getContent(DWHSemanticAnnotationFactoryImpl.filter);

    // this mappings stores how many elements already belong to
    // a specific namespace inside this parent element
    // pass a copy to all sub elements but
    // leave the parameters unchanged for subsequent siblings,
    // so this mapping has to be cloned.

    HashMap<String, HashMap<String, Integer>> localNamespaceCounts =
        new HashMap<String, HashMap<String, Integer>>();

    if (null != namespaceNames) {

      // set all counts to zero
      for (Map.Entry<String, String> entry : namespaceNames.entrySet()) {
        localNamespaceCounts.put(entry.getKey(), null);
      }
    }

    if ((null != elementList) && (0 != elementList.size())) {
      for (Object o : elementList) {
        searchForSemanticAnnotations(
            list,
            ((Element) o),
            selfPath,
            namespaceNamePair.getValue(),
            localSchema,
            namespaceNames,
            localNamespaceCounts);
      }
    }

    if (element.getName().equalsIgnoreCase("ModelElement.taggedValue")) {
      // if modelReference is found, the method stores all information
      // about the semantic annotation inside a annotation and puts
      // that annotation in the list of found annotations
      if ((null != modelReference)
          || (null != liftingSchemaMapping)
          || (null != loweringSchemaMapping)) {

        CWMDocumentSemanticAnnotationImpl ann = new CWMDocumentSemanticAnnotationImpl();

        // from SemanticAnnotation
        ann.setSourceType("CWMDocument");

        // conceptGroup has to be set by first phase of algorithm
        ann.setModelRef(modelReference);
        ann.setLiftingSchemaMapping(liftingSchemaMapping);
        // Lowering Schema Mapping is ignored but stored anyways
        ann.setLoweringSchemaMapping(loweringSchemaMapping);
        ann.setModelType(this.modelType);
        // store xpath to this annotation
        ann.setXPath(selfPath);
        ann.setNamespaceNames(namespaceNames);
        ann.setDocument(document);

        // from DWHSemanticAnnotation
        ann.setAnnotationType(schemaType);
        ann.setTableName(tableName);
        if (!schemaType.equalsIgnoreCase("Table")) {
          // if the annotation concerns a table, do not store
          // a column name
          ann.setColumnName(columnName);
        }
        ann.setSchema(localSchema);

        // from CWMDocumentSemanticAnnotation
        ann.setCWMDocument(cwmDocument);
        ann.setCWMDocumentPath(cwmDocument.getPath());

        list.add(ann);
      }

      modelReference = null;
      liftingSchemaMapping = null;
      loweringSchemaMapping = null;
    }
  }