2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.ext
.geo
;
11 import java
.io
.ByteArrayInputStream
;
12 import java
.io
.IOException
;
13 import java
.io
.InputStream
;
14 import java
.io
.StringWriter
;
16 import java
.util
.ArrayList
;
17 import java
.util
.HashMap
;
18 import java
.util
.List
;
20 import java
.util
.TreeSet
;
22 import javax
.xml
.stream
.XMLOutputFactory
;
23 import javax
.xml
.stream
.XMLStreamException
;
24 import javax
.xml
.stream
.XMLStreamWriter
;
26 import org
.apache
.logging
.log4j
.LogManager
;
27 import org
.apache
.logging
.log4j
.Logger
;
28 import org
.jdom
.Element
;
29 import org
.jdom
.JDOMException
;
30 import org
.jdom
.Namespace
;
32 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
33 import eu
.etaxonomy
.cdm
.common
.XmlHelp
;
36 * Holds all values to map an NamedArea to a geo service area.
38 * TODO it must be possible to distinguish mappings for multiple layers in the same map service,
39 * that is the combination of GeoServiceType, URL and layer would be a unique key.
40 * This is however conflicting with the concept of the subAreas which allows to combine multiple
41 * polygons from different layers.
43 * see also https://dev.e-taxonomy.eu/redmine/issues/4263
48 public class GeoServiceArea
{
49 @SuppressWarnings("unused")
50 private static final Logger logger
= LogManager
.getLogger(GeoServiceArea
.class);
52 private static final String VALUE
= "value";
53 private static final String FIELD
= "field";
54 private static final String LAYER
= "layer";
55 private static final String AREA
= "area";
56 private static final String MAP_SERVICE_NAMESPACE
= "http://www.etaxonomy.eu/cdm";
57 private static final String MAP_SERVICE
= "mapService";
60 public enum GeoServiceType
{
61 EDIT("Edit Geo Service"),
64 private final String label
;
66 private GeoServiceType(String label
){
70 public String
getLabel(){
75 private final TreeSet
<SubArea
> subAreas
= new TreeSet
<>();
76 private URL serviceUri
;
77 private GeoServiceType type
;
80 public class SubArea
implements Comparable
<SubArea
>{
86 public int hashCode() {
89 hash
+= layer
!= null ? layer
.hashCode() * 29 : 32;
90 hash
+= field
!= null ? field
.hashCode() * 31 : 32;
91 hash
+= value
!= null ? value
.hashCode() * 37 : 32;
96 public boolean equals(Object otherArea
) {
97 if (! (otherArea
instanceof SubArea
)){
100 SubArea subArea
= (SubArea
)otherArea
;
101 if (CdmUtils
.nullSafeEqual(layer
, subArea
.layer
)
102 && CdmUtils
.nullSafeEqual(field
, subArea
.field
)
103 && CdmUtils
.nullSafeEqual(value
, subArea
.value
)
111 public int compareTo(SubArea otherArea
) {
112 int compareLayer
= CdmUtils
.Nz(this.layer
).compareToIgnoreCase(CdmUtils
.Nz(otherArea
.layer
));
113 int compareField
= CdmUtils
.Nz(this.field
).compareToIgnoreCase(CdmUtils
.Nz(otherArea
.field
));
114 int compareValue
= CdmUtils
.Nz(this.value
).compareToIgnoreCase(CdmUtils
.Nz(otherArea
.value
));
116 if (compareLayer
!= 0){
118 }else if (compareField
!= 0 ){
126 public void add(String layer
, String field
, String value
){
127 SubArea newArea
= new SubArea();
128 newArea
.layer
= layer
;
129 newArea
.field
= field
;
130 newArea
.value
= value
;
131 subAreas
.add(newArea
);
135 * Returns the areas as a layer, field, area nested map.
138 public Map
<String
, Map
<String
, List
<String
>>> getAreasMap(){
139 Map
<String
, Map
<String
, List
<String
>>> result
= new HashMap
<>();
141 for (SubArea area
: subAreas
){
143 Map
<String
, List
<String
>> layer
= result
.get(area
.layer
);
145 layer
= new HashMap
<>();
146 result
.put(area
.layer
, layer
);
149 List
<String
> field
= layer
.get(area
.field
);
151 field
= new ArrayList
<>();
152 layer
.put(area
.field
, field
);
155 if (! field
.contains(area
.value
)){
156 field
.add(area
.value
);
162 public List
<SubArea
> getAreasList(){
163 List
<SubArea
> result
= new ArrayList
<>();
164 for (SubArea area
: subAreas
){
171 public static boolean isAreaMapping(String xml
){
172 //TODO check by parsing or only testing root + namespace
173 GeoServiceArea mapping
= valueOf(xml
);
174 if (mapping
!= null){
181 public static GeoServiceArea
valueOf (String xml
){
186 // StringReader reader = new StringReader (xml);
187 // (new InputSource(reader));
188 // InputStream is = new java.io.StringBufferInputStream(xml);
189 InputStream is
= new ByteArrayInputStream(xml
.getBytes());
190 GeoServiceArea result
= new GeoServiceArea();
193 Element root
= XmlHelp
.getRoot(is
);
194 if (! root
.getName().equals(MAP_SERVICE
) || ! root
.getNamespace().getURI().equals(MAP_SERVICE_NAMESPACE
) ){
197 //TODO schema validation
199 Namespace ns
= root
.getNamespace();
200 List
<Element
> elAreas
= root
.getChildren(AREA
, ns
);
201 for (Element elArea
: elAreas
){
202 Element layer
= elArea
.getChild(LAYER
, ns
);
203 Element field
= elArea
.getChild(FIELD
, ns
);
204 //TODO multiple values
205 List
<Element
> values
= elArea
.getChildren(VALUE
, ns
);
206 for (Element value
: values
){
207 result
.add(layer
.getTextTrim(), field
.getTextTrim(), value
.getTextTrim());
212 } catch (JDOMException e
) {
213 throw new RuntimeException(e
);
214 } catch (IOException e
) {
215 throw new RuntimeException(e
);
219 //TODO use JAXB or other marshalling techniques
220 public String
toXml() throws XMLStreamException
{
221 XMLStreamWriter writer
= null;
222 XMLOutputFactory factory
= XMLOutputFactory
.newInstance();
223 StringWriter stringWriter
= new StringWriter();
224 writer
= factory
.createXMLStreamWriter(stringWriter
);
226 String rootNamespace
= MAP_SERVICE_NAMESPACE
;
227 String rootName
= MAP_SERVICE
;
230 writer
.writeStartDocument();
231 writer
.setDefaultNamespace(rootNamespace
);
233 // create root element
234 writer
.writeStartElement(rootName
);
236 writer
.writeNamespace(null, rootNamespace
);
237 writer
.writeAttribute("type", "editMapService");
241 writer
.writeEndElement();
242 writer
.writeEndDocument();
244 return stringWriter
.getBuffer().toString();
247 private void writeAreas(XMLStreamWriter writer
) throws XMLStreamException
{
248 Map
<String
, Map
<String
, List
<String
>>> areaMap
= getAreasMap();
250 for (String layerKey
: areaMap
.keySet()){
251 Map
<String
, List
<String
>> layer
= areaMap
.get(layerKey
);
252 for (String fieldKey
: layer
.keySet()){
253 List
<String
> field
= layer
.get(fieldKey
);
255 writer
.writeStartElement(AREA
);
257 writer
.writeStartElement(LAYER
);
258 writer
.writeCharacters(layerKey
);
259 writer
.writeEndElement();
261 writer
.writeStartElement(FIELD
);
262 writer
.writeCharacters(fieldKey
);
263 writer
.writeEndElement();
265 for (String value
: field
){
266 writer
.writeStartElement(VALUE
);
267 writer
.writeCharacters(value
);
268 writer
.writeEndElement();
270 writer
.writeEndElement();
276 return this.subAreas
.size();