/*******************************************************************************
* Copyright (c) 2011, 2012 Red Hat, Inc.
* All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*
* @author Bob Brodt
******************************************************************************/
package org.eclipse.bpmn2.modeler.core.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.namespace.QName;
import org.eclipse.bpmn2.Definitions;
import org.eclipse.bpmn2.DocumentRoot;
import org.eclipse.bpmn2.modeler.core.adapters.AdapterRegistry;
import org.eclipse.bpmn2.modeler.core.adapters.INamespaceMap;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jdt.core.IType;
import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.Message;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDSchema;
/**
* @author Bob Brodt
*
*/
public class NamespaceUtil {
public static Map<String,String> getXMLNSPrefixMap(Resource resource) {
if (resource!=null) {
EList<EObject> contents = resource.getContents();
if (!contents.isEmpty() && contents.get(0) instanceof DocumentRoot) {
return ((DocumentRoot)contents.get(0)).getXMLNSPrefixMap();
}
}
return null;
}
public static String getNamespaceForPrefix(Resource resource, String prefix) {
Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null)
return map.get(prefix);
return null;
}
public static String getPrefixForNamespace(Resource resource, String namespace) {
Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null) {
for (Entry<String, String> e : map.entrySet()) {
String value = e.getValue();
if (value!=null && value.equals(namespace))
return e.getKey();
}
}
return null;
}
public static String normalizeQName(Resource resource, QName qname) {
String localPart = qname.getLocalPart();
String namespace = qname.getNamespaceURI();
String prefix = getPrefixForNamespace(resource, namespace);
if (prefix!=null && !prefix.isEmpty()) {
return prefix + ":" + localPart; //$NON-NLS-1$
}
prefix = qname.getPrefix();
if (prefix!=null && !prefix.isEmpty()) {
return prefix + ":" + localPart; //$NON-NLS-1$
}
return localPart;
}
public static boolean hasNamespace(Resource resource, String namespace) {
Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null) {
for (Entry<String, String> e : map.entrySet()) {
String value = e.getValue();
if (value!=null && value.equals(namespace))
return true;
}
}
return false;
}
public static boolean hasPrefix(Resource resource, String prefix) {
Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null) {
return map.containsKey(prefix);
}
return false;
}
public static String addNamespace(Resource resource, String namespace) {
if (hasNamespace(resource,namespace))
return null;
// generate a prefix
String prefix = null;
Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null) {
prefix = createUniquePrefix(map, "ns"); //$NON-NLS-1$
addNamespace(resource, prefix, namespace);
}
return prefix;
}
public static String createUniquePrefix(Map<String,String> map, String prefix) {
if (map!=null) {
if (map.containsKey(prefix)) {
int index = 1;
while (map.containsKey(prefix+index))
++index;
prefix = prefix + index;
}
}
return prefix;
}
public static String addNamespace(final Resource resource, String prefix, final String namespace) {
final Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null) {
if (prefix==null) {
prefix = "ns"; //$NON-NLS-1$
}
map.put(prefix, namespace);
return prefix;
}
return null;
}
/**
* Remove the namespace prefix mapping for a given namespace.
*
* @param object - any EObject in the BPMN2 Resource
* @param namespace - the namespace to be removed
* @return the namespace prefix if the mapping was successfully removed
* or null otherwise
*/
public static String removeNamespace(final Resource resource, final String namespace) {
final Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null) {
String prefix = null;
for (Entry<String, String> e : map.entrySet()) {
String value = e.getValue();
if (value!=null && value.equals(namespace)) {
prefix = e.getKey();
break;
}
}
if (prefix!=null && map.containsKey(prefix)) {
TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(resource);
if (domain != null) {
final String p = prefix;
domain.getCommandStack().execute(new RecordingCommand(domain) {
@Override
protected void doExecute() {
map.remove(p);
}
});
}
return prefix;
}
}
return null;
}
/**
* Remove the namespace prefix mapping for a given prefix.
*
* @param object - any EObject in the BPMN2 Resource
* @param prefix - the namespace prefix to be removed
* @return the namespace if the mapping was successfully removed
* or null otherwise
*/
public static String removeNamespaceForPrefix(final Resource resource, final String prefix) {
final Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null && map.containsKey(prefix)) {
TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(resource);
if (domain != null) {
String ns = map.get(prefix);
domain.getCommandStack().execute(new RecordingCommand(domain) {
@Override
protected void doExecute() {
map.remove(prefix);
}
});
return ns;
}
}
return null;
}
/**
* @param eObject
* @return the namespace map for the given object.
*/
@SuppressWarnings("unchecked")
static public INamespaceMap<String, String> getNamespaceMap(EObject eObject) {
if (eObject == null) {
throw new NullPointerException(
"eObject cannot be null in getNamespaceMap()"); //$NON-NLS-1$
}
INamespaceMap<String, String> nsMap = null;
// Bug 120110 - this eObject may not have a namespace map, but its
// ancestors might, so keep searching until we find one or until
// we run out of ancestors.
while (nsMap==null && eObject!=null) {
nsMap = AdapterRegistry.INSTANCE.adapt(
eObject, INamespaceMap.class);
if (nsMap==null)
eObject = eObject.eContainer();
}
if (nsMap == null) {
throw new IllegalStateException(
"INamespaceMap cannot be attached to an eObject"); //$NON-NLS-1$
}
return nsMap;
}
public static String getNamespacePrefix(EObject eObject, String namespace) {
for (EObject context = eObject; context != null; context = context
.eContainer()) {
List<String> pfxList = getNamespaceMap(context).getReverse(
namespace);
if (pfxList.size() > 0) {
return pfxList.get(0);
}
}
return null;
}
///////
public static List<String> getAllPrefixesForNamespace(Resource resource, String namespace) {
List<String> result = new ArrayList<String>();
Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null) {
for (Entry<String, String> e : map.entrySet()) {
String value = e.getValue();
if (value!=null && value.equals(namespace))
result.add(e.getKey());
}
}
return result;
}
public static String getNamespaceForObject(Object object) {
String namespace = null;
// find the root container for this EObject
if (object instanceof EObject) {
EObject root = (EObject)object;
while ((namespace==null ||namespace.isEmpty()) && root!=null) {
if (root instanceof Definition) {
namespace = ((Definition)root).getTargetNamespace();
}
else if (root instanceof XSDNamedComponent) {
namespace = ((XSDNamedComponent)root).getTargetNamespace();
}
else if (root instanceof Definitions) {
namespace = ((Definitions)root).getTargetNamespace();
}
else if (root instanceof Message) {
namespace = ((Message)root).getQName().getNamespaceURI();
}
root = root.eContainer();
}
}
else if (object instanceof IType) {
namespace = "http://www.java.com/java"; //$NON-NLS-1$
}
return (namespace == null || namespace.isEmpty()) ? null : namespace;
}
public static String getQualifier(Object object) {
String qualifier = null;
// find the root container for this EObject
if (object instanceof EObject) {
EObject root = (EObject)object;
while (qualifier==null && root!=null) {
if (root instanceof Definition) {
qualifier = "wsdl"; //$NON-NLS-1$
}
else if (root instanceof XSDSchema) {
qualifier = "xsd"; //$NON-NLS-1$
}
else if (root instanceof Definitions) {
qualifier = "bpmn2"; //$NON-NLS-1$
}
root = root.eContainer();
}
}
else if (object instanceof IType) {
qualifier = "java"; //$NON-NLS-1$
}
return qualifier;
}
public static String getPrefixForObject(Resource resource, Object object) {
String prefix = ""; //$NON-NLS-1$
String namespace = getNamespaceForObject(object);
String qualifier = getQualifier(object);
if (namespace!=null) {
for (String s : getAllPrefixesForNamespace(resource, namespace)) {
if (s.endsWith("."+qualifier)) //$NON-NLS-1$
return s;
}
}
Map<String,String> map = getXMLNSPrefixMap(resource);
if (map!=null) {
prefix = createUniquePrefix(map, "ns"); //$NON-NLS-1$
}
if (prefix!=null) {
return prefix + "." + qualifier; //$NON-NLS-1$
}
return prefix;
}
public static String addNamespaceForObject(Resource resource, Object object) {
String namespace = getNamespaceForObject(object);
String prefix = getPrefixForObject(resource, object);
if (namespace==null || hasPrefix(resource,prefix))
return null;
// generate a prefix
addNamespace(resource, prefix, namespace);
return namespace;
}
}