eu.esdihumboldt.hale.io.wfs.ui.KVPUtil.java Source code

Java tutorial

Introduction

Here is the source code for eu.esdihumboldt.hale.io.wfs.ui.KVPUtil.java

Source

/*
 * Copyright (c) 2015 Data Harmonisation Panel
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     Data Harmonisation Panel <http://www.dhpanel.eu>
 */

package eu.esdihumboldt.hale.io.wfs.ui;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;

import org.apache.http.client.utils.URIBuilder;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Maps.EntryTransformer;

import eu.esdihumboldt.hale.io.wfs.WFSVersion;

/**
 * Utilities related to KVP encoded WFS requests.
 * 
 * @author Simon Templer
 */
public class KVPUtil {

    /**
     * Add typename and namespace parameters for a WFS request to the given URI
     * builder.
     * 
     * @param builder the builder for the WFS request URI
     * @param selected the type names to include
     * @param version the targeted WFS version
     */
    public static void addTypeNameParameter(URIBuilder builder, Iterable<QName> selected, WFSVersion version) {
        // namespaces mapped to prefixes
        Map<String, String> namespaces = new HashMap<>();
        // type names with updated prefix
        Set<QName> typeNames = new HashSet<>();

        for (QName type : selected) {
            String prefix;
            if (type.getNamespaceURI() != null && !type.getNamespaceURI().isEmpty()) {
                prefix = namespaces.get(type.getNamespaceURI());
                if (prefix == null) {
                    // no mapping yet for namespace
                    String candidate = type.getPrefix();
                    prefix = addPrefix(candidate, type.getNamespaceURI(), namespaces);
                }
            } else {
                // default namespace
                prefix = XMLConstants.DEFAULT_NS_PREFIX;
            }

            // add updated type
            typeNames.add(new QName(type.getNamespaceURI(), type.getLocalPart(), prefix));
        }

        final String paramNamespaces;
        final String paramTypenames;
        final String prefixNamespaceDelim;
        switch (version) {
        case V1_1_0:
            paramNamespaces = "NAMESPACE";
            paramTypenames = "TYPENAME";
            prefixNamespaceDelim = "=";
            break;
        case V2_0_0:
        case V2_0_2:
            /*
             * XXX below are the values as defined in the WFS 2 specification.
             * There have been problems with some GeoServer instances if used in
             * that manner.
             */
            paramNamespaces = "NAMESPACES";
            paramTypenames = "TYPENAMES";
            prefixNamespaceDelim = ",";
            break;
        default:
            // fall-back to WFS 1.1
            paramNamespaces = "NAMESPACE";
            paramTypenames = "TYPENAME";
            prefixNamespaceDelim = "=";
        }

        // add namespace prefix definitions
        if (!namespaces.isEmpty()) {
            builder.addParameter(paramNamespaces, Joiner.on(',')
                    .join(Maps.transformEntries(namespaces, new EntryTransformer<String, String, String>() {

                        @Override
                        public String transformEntry(String namespace, String prefix) {
                            StringBuilder sb = new StringBuilder();
                            sb.append("xmlns(");
                            sb.append(prefix);
                            sb.append(prefixNamespaceDelim);
                            sb.append(namespace);
                            sb.append(")");
                            return sb.toString();
                        }

                    }).values()));
        }
        // add type names
        if (!typeNames.isEmpty()) {
            builder.addParameter(paramTypenames,
                    Joiner.on(',').join(Iterables.transform(typeNames, new Function<QName, String>() {

                        @Override
                        public String apply(QName typeName) {
                            String prefix = typeName.getPrefix();
                            if (prefix == null || prefix.isEmpty()) {
                                return typeName.getLocalPart();
                            }
                            return prefix + ":" + typeName.getLocalPart();
                        }
                    })));
        }
    }

    /**
     * Add a new prefix.
     * 
     * @param candidate the prefix candidate
     * @param namespace the namespace to be associated to the prefix
     * @param namespaces the current namespaces mapped to prefixes
     * @return the prefix to use
     */
    private static String addPrefix(String candidate, final String namespace,
            final Map<String, String> namespaces) {
        int num = 1;
        while (namespaces.values().contains(candidate)) {
            candidate = "ns" + num;
            num++;
        }
        namespaces.put(namespace, candidate);
        return candidate;
    }

}