/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.camunda.bpm.model.xml.impl.util;

import org.camunda.bpm.model.xml.instance.DomDocument;
import org.camunda.bpm.model.xml.instance.DomElement;

import java.util.HashMap;
import java.util.Map;

import static javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI;

/**
 * @author Sebastian Menski
 */
public class XmlQName {

  public static final Map<String, String> KNOWN_PREFIXES;
  static
  {
    KNOWN_PREFIXES = new HashMap<String, String>();
    KNOWN_PREFIXES.put("http://www.camunda.com/fox", "fox");
    KNOWN_PREFIXES.put("http://activiti.org/bpmn", "camunda");
    KNOWN_PREFIXES.put("http://www.omg.org/spec/BPMN/20100524/MODEL", "bpmn2");
    KNOWN_PREFIXES.put("http://www.omg.org/spec/BPMN/20100524/DI", "bpmndi");
    KNOWN_PREFIXES.put(XMLNS_ATTRIBUTE_NS_URI, "");
  }

  private final DomElement rootElement;
  private final DomElement element;

  private final String localName;
  private final String namespaceUri;
  private final String prefix;

  public XmlQName(DomDocument document, String namespaceUri, String localName) {
    this(document, null, namespaceUri, localName);
  }

  public XmlQName(DomElement element, String namespaceUri, String localName) {
    this(element.getDocument(), element, namespaceUri, localName);
  }

  public XmlQName(DomDocument document, DomElement element, String namespaceUri, String localName) {
    this.rootElement = document.getRootElement();
    this.element = element;
    this.localName = localName;
    this.namespaceUri = namespaceUri;
    this.prefix = determinePrefixAndNamespaceUri();
  }

  public String getNamespaceUri() {
    return namespaceUri;
  }

  public String getLocalName() {
    return localName;
  }

  public String getPrefixedName() {
    return QName.combine(prefix, localName);
  }

  public boolean hasLocalNamespace() {
    if (element != null) {
      return element.getNamespaceURI().equals(namespaceUri);
    }
    else {
      return false;
    }
  }

  private String determinePrefixAndNamespaceUri() {
    if (namespaceUri != null) {
      if (rootElement != null && namespaceUri.equals(rootElement.getNamespaceURI())) {
        // global namespaces do not have a prefix or namespace URI
        return null;
      }
      else {
        // lookup for prefix
        String lookupPrefix = lookupPrefix();
        if (lookupPrefix == null && rootElement != null) {
          // if no prefix is found we generate a new one
          // search for known prefixes
          lookupPrefix = KNOWN_PREFIXES.get(namespaceUri);
          if (lookupPrefix == "") {
            // ignored namespace
            return null;
          }
          else if (lookupPrefix != null) {
            rootElement.registerNamespace(lookupPrefix, namespaceUri);
            return lookupPrefix;
          }
          else {
            return rootElement.registerNamespace(namespaceUri);
          }
        }
        else {
          return lookupPrefix;
        }
      }
    }
    else {
      // no namespace so no prefix
      return null;
    }
  }

  private String lookupPrefix() {
    if (namespaceUri != null) {
      String lookupPrefix = null;
      if (element != null) {
        lookupPrefix = element.lookupPrefix(namespaceUri);
      }
      else if (rootElement != null) {
        lookupPrefix = rootElement.lookupPrefix(namespaceUri);
      }
      return lookupPrefix;
    }
    else {
      return null;
    }
  }

}

@@ -3019,31 +3019,36 @@
 es%0A         
- lookup
+String known
 Prefix = KNO
@@ -3084,38 +3084,37 @@
 ;%0A          if (
-lookup
+known
 Prefix == %22%22) %7B%0A
@@ -3107,18 +3107,20 @@
 efix == 
-%22%22
+null
 ) %7B%0A    
@@ -3134,15 +3134,16 @@
  // 
-ignored
+generate
  nam
@@ -3172,124 +3172,131 @@
 urn 
-null;%0A          %7D%0A          else if (lookupPrefix != null) %7B%0A            rootElement.registerNamespace(lookupPrefix,
+rootElement.registerNamespace(namespaceUri);%0A          %7D%0A          else if (knownPrefix.isEmpty()) %7B%0A            // ignored
  nam
@@ -3293,37 +3293,32 @@
 gnored namespace
-Uri);
 %0A            ret
@@ -3317,36 +3317,28 @@
      return 
-lookupPrefix
+null
 ;%0A          
@@ -3372,58 +3372,133 @@
     
-return rootElement.registerNamespace(namespaceUri)
+// register known prefix%0A            rootElement.registerNamespace(knownPrefix, namespaceUri);%0A            return knownPrefix
 ;%0A  

rearrange the namespace registration