com.evolveum.midpoint.prism.xml.GlobalDynamicNamespacePrefixMapper.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.prism.xml.GlobalDynamicNamespacePrefixMapper.java

Source

/*
 * Copyright (c) 2010-2013 Evolveum
 *
 * 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 com.evolveum.midpoint.prism.xml;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;

import javax.xml.namespace.QName;

import org.apache.commons.lang.StringUtils;

import com.evolveum.midpoint.prism.xml.DynamicNamespacePrefixMapper;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;

/**
 * Maps namespaces to preferred prefixes. Should be used through the code to
 * avoid generation of prefixes.
 * 
 * Although this is usually used as singleton (static), it can also be instantiated to locally
 * override some namespace mappings. This is useful for prefixes like "tns" (schema) or "ri" (resource schema).
 * 
 * @see MID-349
 * 
 * @author Igor Farinic
 * @author Radovan Semancik
 * 
 */
public class GlobalDynamicNamespacePrefixMapper extends NamespacePrefixMapper
        implements DynamicNamespacePrefixMapper, DebugDumpable {

    private static final Map<String, String> globalNamespacePrefixMap = new HashMap<String, String>();
    private Map<String, String> localNamespacePrefixMap = new HashMap<String, String>();
    private String defaultNamespace = null;
    private boolean alwaysExplicit = false;
    private final Set<String> prefixesDeclaredByDefault = new HashSet<>();

    public String getDefaultNamespace() {
        return defaultNamespace;
    }

    public synchronized void setDefaultNamespace(String defaultNamespace) {
        this.defaultNamespace = defaultNamespace;
    }

    @Override
    public boolean isAlwaysExplicit() {
        return alwaysExplicit;
    }

    @Override
    public void setAlwaysExplicit(boolean alwaysExplicit) {
        this.alwaysExplicit = alwaysExplicit;
    }

    @Override
    public void addDeclaredByDefault(String prefix) {
        prefixesDeclaredByDefault.add(prefix);
    }

    @Override
    public synchronized Map<String, String> getNamespacesDeclaredByDefault() {
        Map<String, String> retval = new HashMap<>();
        for (Map.Entry<String, String> entry : globalNamespacePrefixMap.entrySet()) {
            String prefix = entry.getValue();
            if (prefixesDeclaredByDefault.contains(prefix)) {
                retval.put(prefix, entry.getKey());
            }
        }
        return retval;
    }

    @Override
    public synchronized void registerPrefix(String namespace, String prefix, boolean isDefaultNamespace) {
        registerPrefixGlobal(namespace, prefix);
        if (isDefaultNamespace || prefix == null) {
            defaultNamespace = namespace;
        }
    }

    private static synchronized void registerPrefixGlobal(String namespace, String prefix) {
        globalNamespacePrefixMap.put(namespace, prefix);
    }

    @Override
    public synchronized void registerPrefixLocal(String namespace, String prefix) {
        localNamespacePrefixMap.put(namespace, prefix);
    }

    @Override
    public String getPrefix(String namespace) {
        if (defaultNamespace != null && defaultNamespace.equals(namespace) && !alwaysExplicit) {
            return "";
        }
        return getPrefixExplicit(namespace);
    }

    public synchronized String getPrefixExplicit(String namespace) {
        String prefix = localNamespacePrefixMap.get(namespace);
        if (prefix == null) {
            return getPreferredPrefix(namespace);
        }
        return prefix;
    }

    @Override
    public QName setQNamePrefix(QName qname) {
        String namespace = qname.getNamespaceURI();
        String prefix = getPrefix(namespace);
        if (prefix == null) {
            return qname;
        }
        return new QName(qname.getNamespaceURI(), qname.getLocalPart(), prefix);
    }

    @Override
    public QName setQNamePrefixExplicit(QName qname) {
        String namespace = qname.getNamespaceURI();
        String prefix = getPrefixExplicit(namespace);
        if (prefix == null) {
            return qname;
        }
        return new QName(qname.getNamespaceURI(), qname.getLocalPart(), prefix);
    }

    @Override
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
        //for JAXB we are mapping midpoint common namespace to default namespace
        if (defaultNamespace != null && defaultNamespace.equals(namespaceUri) && !alwaysExplicit) {
            return "";
        }
        return getPreferredPrefix(namespaceUri, suggestion);
    }

    /**
     * 
     * @param namespace
     * @return preferred prefix for the namespace, if no prefix is assigned yet,
     *         then it will assign a prefix and return it.
     */
    public static synchronized String getPreferredPrefix(String namespace) {
        return getPreferredPrefix(namespace, null);
    }

    /**
     * @param namespace
     * @param hintPrefix
     * @return preferred prefix for the namespace, if no prefix is assigned yet,
     *         then it assign hint prefix (if it is not assigned yet) or assign
     *         a new prefix and return it (if hint prefix is already assigned to
     *         other namespace).
     */
    public static synchronized String getPreferredPrefix(String namespace, String hintPrefix) {
        String prefix = globalNamespacePrefixMap.get(namespace);

        if (StringUtils.isEmpty(prefix)) {
            if (StringUtils.isEmpty(hintPrefix)) {
                // FIXME: improve new prefix assignment
                prefix = "gen" + (new Random()).nextInt(999);
            } else {
                if (globalNamespacePrefixMap.containsValue(hintPrefix)) {
                    // FIXME: improve new prefix assignment
                    prefix = "gen" + (new Random()).nextInt(999);
                } else {
                    prefix = hintPrefix;
                }
            }
            globalNamespacePrefixMap.put(namespace, prefix);
        }

        return prefix;

    }

    @Override
    public synchronized GlobalDynamicNamespacePrefixMapper clone() {
        GlobalDynamicNamespacePrefixMapper clone = new GlobalDynamicNamespacePrefixMapper();
        clone.defaultNamespace = this.defaultNamespace;
        clone.localNamespacePrefixMap = clonePrefixMap(this.localNamespacePrefixMap);
        clone.alwaysExplicit = this.alwaysExplicit;
        return clone;
    }

    private Map<String, String> clonePrefixMap(Map<String, String> map) {
        if (map == null) {
            return null;
        }
        Map<String, String> clone = new HashMap<String, String>();
        for (Entry<String, String> entry : map.entrySet()) {
            clone.put(entry.getKey(), entry.getValue());
        }
        return clone;
    }

    @Override
    public String debugDump() {
        return debugDump(0);
    }

    @Override
    public String debugDump(int indent) {
        StringBuilder sb = new StringBuilder();
        DebugUtil.indentDebugDump(sb, indent);
        sb.append("GlobalDynamicNamespacePrefixMapper(");
        sb.append(defaultNamespace);
        sb.append("):\n");
        DebugUtil.indentDebugDump(sb, indent + 1);
        sb.append("Global map:\n");
        DebugUtil.debugDumpMapMultiLine(sb, globalNamespacePrefixMap, indent + 2);
        sb.append("\n");
        DebugUtil.indentDebugDump(sb, indent + 1);
        sb.append("Local map:\n");
        DebugUtil.debugDumpMapMultiLine(sb, localNamespacePrefixMap, indent + 2);
        return sb.toString();
    }

}