//$HeadURL$
/*----------------------------------------------------------------------------
This file is part of deegree, http://deegree.org/
Copyright (C) 2001-2009 by:
Department of Geography, University of Bonn
and
lat/lon GmbH
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option)
any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact information:
lat/lon GmbH
Aennchenstr. 19, 53177 Bonn
Germany
http://lat-lon.de/
Department of Geography, University of Bonn
Prof. Dr. Klaus Greve
Postfach 1147, 53001 Bonn
Germany
http://www.geographie.uni-bonn.de/deegree/
e-mail: info@deegree.org
----------------------------------------------------------------------------*/
package org.deegree.framework.utils;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.deegree.datatypes.Code;
import org.deegree.datatypes.QualifiedName;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.Pair;
import org.deegree.framework.xml.NamespaceContext;
import org.deegree.framework.xml.XMLFragment;
import org.deegree.framework.xml.XMLParsingException;
import org.deegree.framework.xml.XMLTools;
import org.deegree.ogcbase.CommonNamespaces;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* The <code></code> class TODO add class documentation here.
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
*
* @author last edited by: $Author$
*
* @version $Revision$, $Date$
*
*/
public class Dictionary {
private static final ILogger LOG = LoggerFactory.getLogger( Dictionary.class );
private static final NamespaceContext nsc = CommonNamespaces.getNamespaceContext();
private XMLFragment xml;
private String description;
private List<Code> names;
private boolean cached = true;
private static Map<QualifiedName, List<Pair<String, String>>> codeLists;
static {
if ( codeLists == null ) {
codeLists = new HashMap<QualifiedName, List<Pair<String, String>>>();
}
}
/**
*
* @param xml
*/
public Dictionary( XMLFragment xml ) {
this.xml = xml;
}
/**
*
* @param xml
* @param cached
*/
public Dictionary( XMLFragment xml, boolean cached ) {
this.xml = xml;
this.cached = cached;
}
/**
*
* @return some description of a dictionary
*/
public String getDescription() {
if ( description == null || !cached ) {
try {
description = XMLTools.getNodeAsString( xml.getRootElement(), "gml:description", nsc, null );
} catch ( XMLParsingException e ) {
LOG.logError( e );
}
}
return description;
}
/**
* Each dictionary must have at least one name. and each name may have a codeSpace
*
* @return name(s) of a dictionary.
*/
public List<Code> getNames() {
if ( names == null || !cached ) {
names = new ArrayList<Code>();
try {
List<Node> nodes = XMLTools.getNodes( xml.getRootElement(), "gml:name", nsc );
for ( Node node : nodes ) {
Element elem = (Element) node;
String name = XMLTools.getStringValue( elem );
String codeSpace = elem.getAttribute( "codeSpace" );
if ( codeSpace == null ) {
names.add( new Code( name ) );
} else {
names.add( new Code( name, URI.create( codeSpace ) ) );
}
}
} catch ( XMLParsingException e ) {
LOG.logError( e );
}
}
return names;
}
/**
*
* @param qn
* {@link QualifiedName} a code list is assigned to
* @param langague
* desired code value language
* @return list of code - value pairs for a {@link QualifiedName}
*/
public List<Pair<String, String>> getCodelist( QualifiedName qn, String langague ) {
List<Pair<String, String>> list = codeLists.get( qn );
if ( list == null ) {
Node tmp = null;
try {
tmp = XMLTools.getNode( xml.getRootElement(), "gml:indirectEntry", nsc );
} catch ( XMLParsingException e1 ) {
e1.printStackTrace();
}
if ( tmp != null ) {
// read dictionary from a remote location
list = handleIndirect( tmp, qn, langague );
} else {
list = readCodeList( xml.getRootElement(), qn, langague );
}
}
return list;
}
/**
*
* @param root
* @param qn
* @param language
* @return @return list of code mappings for passed name and desired language
*/
private List<Pair<String, String>> readCodeList( Element root, QualifiedName qn, String language ) {
if ( language == null ) {
language = Locale.getDefault().getLanguage();
}
List<Pair<String, String>> list = new ArrayList<Pair<String, String>>( 50 );
String c = "["
+ ( qn.getNamespace() != null ? ( "gml:csName/@codeSpace = '" + qn.getNamespace().toASCIIString() + "' and " )
: "" ) + "gml:csName = '" + qn.getLocalName() + "']";
String xpath = "//gml:DefinitionCollection" + c + "/gml:dictionaryEntry/gml:Definition";
try {
List<Node> nodes = XMLTools.getNodes( root, xpath, nsc );
if ( nodes == null || nodes.size() == 0 ) {
c = "[gml:name/@codeSpace = '" + qn.getNamespace().toASCIIString() + "' and gml:name = '"
+ qn.getLocalName() + "']";
xpath = "//gml:DefinitionCollection" + c + "/gml:dictionaryEntry/gml:Definition";
nodes = XMLTools.getNodes( root, xpath, nsc );
}
for ( Node node : nodes ) {
Element elem = (Element) node;
List<Node> names = XMLTools.getNodes( elem, "gml:name", nsc );
Pair<String, String> pair = new Pair<String, String>();
String en = null;
String deflt = null;
for ( Node node2 : names ) {
Element name = (Element) node2;
String cs = name.getAttribute( "codeSpace" );
if ( "urn:org:deegree:igeodesktop:code".equals( cs ) ) {
// is machine readable code?
pair.first = XMLTools.getStringValue( name );
} else if ( ( "urn:org:deegree:igeodesktop:" + language ).equals( cs ) ) {
// is human readable value in desired language
pair.second = XMLTools.getStringValue( name );
}
if ( pair.second == null ) {
if ( "urn:org:deegree:igeodesktop:en".equals( cs ) ) {
// is human readable value in english language
en = pair.second = XMLTools.getStringValue( name );
} else if ( cs == null || cs.length() == 0 ) {
// is human readable value without language code
deflt = XMLTools.getStringValue( name );
}
}
}
if ( pair.second == null && deflt != null ) {
pair.second = deflt;
}
if ( pair.second == null && en != null ) {
pair.second = en;
}
if ( pair.second == null ) {
pair.second = pair.first;
}
list.add( pair );
}
if ( cached ) {
codeLists.put( qn, list );
}
} catch ( XMLParsingException e ) {
LOG.logError( e );
}
return list;
}
/**
* read dictionary from a remote location
*
* @param tmp
* @param qn
* @param langague
* @return list of code mappings for passed name and desired language
*/
private List<Pair<String, String>> handleIndirect( Node tmp, QualifiedName qn, String langague ) {
List<Pair<String, String>> list = new ArrayList<Pair<String, String>>( 50 );
try {
String xpath = "gml:DefinitionProxy/gml:definitionRef/@xlink:href";
String url = XMLTools.getRequiredNodeAsString( tmp, xpath, nsc );
String s = "name=" + URLEncoder.encode( qn.getLocalName(), Charset.defaultCharset().displayName() )
+ "&codespace="
+ URLEncoder.encode( qn.getNamespace().toASCIIString(), Charset.defaultCharset().displayName() );
URL u = new URL( url + "?" + s );
XMLFragment tXml = new XMLFragment( u );
list = readCodeList( tXml.getRootElement(), qn, langague );
} catch ( Exception e ) {
LOG.logError( e );
}
return list;
}
}