Project

General

Profile

Download (9.09 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2009 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.ext.geo;
11

    
12
import java.io.ByteArrayInputStream;
13
import java.io.IOException;
14
import java.io.InputStream;
15
import java.io.StringWriter;
16
import java.net.URL;
17
import java.util.ArrayList;
18
import java.util.HashMap;
19
import java.util.List;
20
import java.util.Map;
21
import java.util.TreeSet;
22

    
23
import javax.xml.stream.XMLOutputFactory;
24
import javax.xml.stream.XMLStreamException;
25
import javax.xml.stream.XMLStreamWriter;
26

    
27
import org.apache.log4j.Logger;
28
import org.jdom.Element;
29
import org.jdom.JDOMException;
30
import org.jdom.Namespace;
31

    
32
import eu.etaxonomy.cdm.common.CdmUtils;
33
import eu.etaxonomy.cdm.common.XmlHelp;
34

    
35
/**
36
 * Holds all values to map an NamedArea to a geo service area.
37
 *
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.
42
 *      see also http://dev.e-taxonomy.eu/trac/ticket/4263
43
 *
44
 * @author a.mueller
45
 * @date 11.08.2011
46
 *
47
 */
48
public class GeoServiceArea {
49
    @SuppressWarnings("unused")
50
    private static final Logger logger = Logger.getLogger(GeoServiceArea.class);
51

    
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";
58

    
59

    
60
    public enum GeoServiceType{
61
        EDIT("Edit Geo Service"),
62
        WMS("WMS Service");
63

    
64
        private final String label;
65

    
66
        private GeoServiceType(String label){
67
            this.label = label;
68
        }
69

    
70
        public String getLabel(){
71
            return label;
72
        }
73
    }
74

    
75
    private final TreeSet<SubArea> subAreas = new TreeSet<SubArea>();
76
    private URL serviceUri;
77
    private GeoServiceType type;
78

    
79

    
80
    public class SubArea implements Comparable<SubArea>{
81
        private String layer;
82
        private String field;
83
        private String value;
84

    
85
        @Override
86
        public int hashCode() {
87
            int hash;
88
            hash = 236435;
89
            hash += layer != null ? layer.hashCode() * 29 : 32;
90
            hash += field != null ? field.hashCode() * 31 : 32;
91
            hash += value != null ? value.hashCode() * 37 : 32;
92
            return hash;
93
        }
94

    
95
        @Override
96
        public boolean equals(Object otherArea) {
97
            if (! (otherArea instanceof SubArea)){
98
                return false;
99
            }
100
            SubArea subArea = (SubArea)otherArea;
101
            if (CdmUtils.nullSafeEqual(layer, subArea.layer)
102
                    && CdmUtils.nullSafeEqual(field, subArea.field)
103
                    && CdmUtils.nullSafeEqual(value, subArea.value)
104
            ){
105
                return true;
106
            }else{
107
                return false;
108
            }
109
        }
110
        @Override
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));
115

    
116
            if (compareLayer != 0){
117
                return compareLayer;
118
            }else if (compareField != 0 ){
119
                return compareField;
120
            }else {
121
                return compareValue;
122
            }
123
        }
124

    
125

    
126
    }
127

    
128
    public void add(String layer, String field, String value){
129
        SubArea newArea = new SubArea();
130
        newArea.layer = layer;
131
        newArea.field = field;
132
        newArea.value = value;
133
        subAreas.add(newArea);
134
    }
135

    
136
    /**
137
     * Returns the areas as a layer, field, area nested map.
138
     * @return
139
     */
140
    public Map<String, Map<String, List<String>>> getAreasMap(){
141
        Map<String, Map<String, List<String>>> result = new HashMap<String, Map<String,List<String>>>();
142

    
143
        for (SubArea area : subAreas){
144
            //layer
145
            Map<String, List<String>> layer = result.get(area.layer);
146
            if (layer == null ){
147
                layer = new HashMap<String, List<String>>();
148
                result.put(area.layer, layer);
149
            }
150
            //field
151
            List<String> field = layer.get(area.field);
152
            if (field == null ){
153
                field = new ArrayList<String>();
154
                layer.put(area.field, field);
155
            }
156
            //value
157
            if (! field.contains(area.value)){
158
                field.add(area.value);
159
            }
160

    
161
        }
162
        return result;
163
    }
164

    
165
    public List<SubArea> getAreasList(){
166
        List<SubArea> result = new ArrayList<SubArea>();
167
        for (SubArea area : subAreas){
168
            result.add(area);
169
        }
170
        return result;
171
    }
172

    
173

    
174
    public static boolean isAreaMapping(String xml){
175
        //TODO check by parsing or only testing root + namespace
176
        GeoServiceArea mapping = valueOf(xml);
177
        if (mapping != null){
178
            return true;
179
        }else{
180
            return false;
181
        }
182
    }
183

    
184
    public static GeoServiceArea valueOf (String xml){
185
        if (xml == null){
186
            return null;
187
        }
188

    
189
//		StringReader reader = new StringReader (xml);
190
//		(new InputSource(reader));
191
//		InputStream is = new java.io.StringBufferInputStream(xml);
192
        InputStream is = new ByteArrayInputStream(xml.getBytes());
193
        GeoServiceArea result = new GeoServiceArea();
194

    
195
        try {
196
            Element root = XmlHelp.getRoot(is);
197
            if (! root.getName().equals(MAP_SERVICE) || ! root.getNamespace().getURI().equals(MAP_SERVICE_NAMESPACE)   ){
198
                return null;
199
            }else{
200
                //TODO schema validation
201

    
202
                Namespace ns = root.getNamespace();
203
                List<Element> elAreas = root.getChildren(AREA, ns);
204
                for (Element elArea : elAreas){
205
                    Element layer = elArea.getChild(LAYER, ns);
206
                    Element field = elArea.getChild(FIELD, ns);
207
                    //TODO multiple values
208
                    List<Element> values = elArea.getChildren(VALUE, ns);
209
                    for (Element value : values){
210
                        result.add(layer.getTextTrim(), field.getTextTrim(), value.getTextTrim());
211
                    }
212
                }
213
                return result;
214
            }
215

    
216

    
217
        } catch (JDOMException e) {
218
            throw new RuntimeException(e);
219
        } catch (IOException e) {
220
            throw new RuntimeException(e);
221
        }
222
    }
223

    
224
    /**
225
     * @return
226
     * @throws XMLStreamException
227
     */
228
    //TODO use JAXB or other marshalling techniques
229
    public String toXml() throws XMLStreamException{
230
        XMLStreamWriter writer = null;
231
            XMLOutputFactory factory = XMLOutputFactory.newInstance();
232
            StringWriter stringWriter = new StringWriter();
233
            writer = factory.createXMLStreamWriter(stringWriter);
234

    
235
            String rootNamespace = MAP_SERVICE_NAMESPACE;
236
            String rootName = MAP_SERVICE;
237

    
238

    
239
            // create header
240
            writer.writeStartDocument();
241
            writer.setDefaultNamespace(rootNamespace);
242

    
243
                // create root element
244
                writer.writeStartElement(rootName);
245

    
246
                writer.writeNamespace(null, rootNamespace);
247
                writer.writeAttribute("type", "editMapService");
248

    
249
                writeAreas(writer);
250

    
251
                writer.writeEndElement();
252
            writer.writeEndDocument();
253

    
254
            return stringWriter.getBuffer().toString();
255
    }
256

    
257
    private void writeAreas(XMLStreamWriter writer) throws XMLStreamException {
258
        Map<String, Map<String, List<String>>> areaMap = getAreasMap();
259
        //TODO multiple
260
        for (String layerKey : areaMap.keySet()){
261
            Map<String, List<String>> layer = areaMap.get(layerKey);
262
            for (String fieldKey: layer.keySet()){
263
                List<String> field = layer.get(fieldKey);
264
                //area
265
                writer.writeStartElement(AREA);
266
                //layer
267
                writer.writeStartElement(LAYER);
268
                writer.writeCharacters(layerKey);
269
                writer.writeEndElement();
270
                //field
271
                writer.writeStartElement(FIELD);
272
                writer.writeCharacters(fieldKey);
273
                writer.writeEndElement();
274
                //value
275
                for (String value : field){
276
                    writer.writeStartElement(VALUE);
277
                    writer.writeCharacters(value);
278
                    writer.writeEndElement();
279
                }
280
                writer.writeEndElement();
281
            }
282
        }
283

    
284
    }
285

    
286

    
287
    public int size() {
288
        return this.subAreas.size();
289
    }
290

    
291
}
(8-8/14)