Project

General

Profile

Download (10.6 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2007 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

    
11
package eu.etaxonomy.cdm.ext;
12

    
13
import java.awt.Color;
14
import java.util.ArrayList;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Set;
20

    
21
import javax.persistence.Transient;
22

    
23
import org.apache.log4j.Logger;
24

    
25
import eu.etaxonomy.cdm.common.CdmUtils;
26
import eu.etaxonomy.cdm.model.common.Language;
27
import eu.etaxonomy.cdm.model.common.Representation;
28
import eu.etaxonomy.cdm.model.description.Distribution;
29
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
30
import eu.etaxonomy.cdm.model.description.PresenceTerm;
31
import eu.etaxonomy.cdm.model.location.NamedArea;
32
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
33

    
34
/**
35
 * @author a.mueller
36
 * @created 17.11.2008
37
 * @version 1.0
38
 */
39
public class EditGeoServiceUtilities {
40
	private static final Logger logger = Logger.getLogger(EditGeoServiceUtilities.class);
41

    
42
	private static PresenceAbsenceTermBase<?> defaultStatus = PresenceTerm.PRESENT();
43

    
44
	//preliminary implementation for TDWG areas
45
	/**
46
	 * Returns the parameter String for the EDIT geo webservice to create a map.
47
	 * @param distributions A set of distributions that should be shown on the map
48
	 * @param presenceAbsenceTermColors A map that defines the colors of PresenceAbsenceTerms. 
49
	 * The PresenceAbsenceTerms are defined by their uuid. If a PresenceAbsenceTerm is not included in
50
	 * this map, it's default color is taken instead. If the map == null all terms are colored by their default color. 
51
	 * @param width The maps width
52
	 * @param height The maps height
53
	 * @param bbox The maps bounding box (e.g. "-180,-90,180,90" for the whole world)
54
	 * @param layer The layer that is responsible for background borders and colors. Use the name for the layer.
55
	 * If null 'earth' is taken as default. 
56
	 * @return the parameter string or an empty string if the <code>distributions</code> set was null or empty.
57
	 */
58
	@Transient
59
	public static String getEditGeoServiceUrlParameterString(
60
			Set<Distribution> distributions, 
61
			Map<PresenceAbsenceTermBase<?>,Color> presenceAbsenceTermColors, 
62
			int width, 
63
			int height, 
64
			String bbox, 
65
			String backLayer,
66
			List<Language> languages){
67
		
68
		String result = "";
69
		String layer = ""; 
70
		String areaData = "";
71
		String areaStyle = "";
72
		String areaTitle = "";
73
		String widthStr = "";
74
		String heightStr = "";
75
		String adLayerSeparator = ":";
76
		String styleInAreaDataSeparator = "|";
77
		String msSeparator = ","; //Separator for the ms parameter values , e.g. 'x' => ms=600x400
78
		double borderWidth = 0.1;
79
		
80
		
81
		if(distributions == null || distributions.size() == 0){
82
			return "";
83
		}
84
		if (presenceAbsenceTermColors == null) {
85
			//presenceAbsenceTermColors = new HashMap<PresenceAbsenceTermBase<?>, Color>();
86
			presenceAbsenceTermColors = makeDefaultColorMap();
87
		}
88

    
89
		//List<String> layerStrings = new ArrayList<String>(); 
90
		Map<String, Map<Integer, Set<Distribution>>> layerMap = new HashMap<String, Map<Integer, Set<Distribution>>>(); 
91
		List<PresenceAbsenceTermBase<?>> statusList = new ArrayList<PresenceAbsenceTermBase<?>>();
92
		
93
		//bbox, width, hight
94
		if (bbox == null){
95
			// FIXME uncommented this as it can not be desirable to have default values in this method
96
			// we need a parameterString that consists of essential parameters only 
97
			// defaults should be implemented in the geoservice itself.
98
			//bbox ="bbox=-180,-90,180,90";  //earth is default
99
		}else{
100
			bbox = "bbox=" + bbox;
101
		}
102
		if (width > 0){
103
			widthStr = "" + width;
104
		}
105
		if (height > 0){
106
			heightStr = msSeparator + height;
107
		}
108
		String ms = "ms=" + widthStr + heightStr;
109
		if (ms.equals("ms=")){
110
			ms = null;
111
		}
112
		
113
		//iterate through distributions and group styles and layers
114
		//and collect necessary information
115
		for (Distribution distribution:distributions){
116
			//collect status
117
			PresenceAbsenceTermBase<?> status = distribution.getStatus();
118
			if(status == null){
119
				status = defaultStatus;
120
			}
121
			if (! statusList.contains(status)){
122
				statusList.add(status);
123
			}
124
			//group by layers and styles
125
			NamedArea area = distribution.getArea();
126
			if (area != null){
127
				NamedAreaLevel level = area.getLevel();
128
				String geoLayerString = getGeoServiceLayer(level);
129
				//Set<Distribution> layerDistributionSet;
130
				//int index = layerStrings.indexOf(geoLayerString);
131
				Map<Integer, Set<Distribution>> styleMap = layerMap.get(geoLayerString);
132
				if (styleMap == null){
133
					styleMap = new HashMap<Integer, Set<Distribution>>();
134
					layerMap.put(geoLayerString, styleMap);
135
				}
136
				addDistributionToMap(distribution, styleMap, statusList);
137
			}
138
		}
139
		
140
		//layer
141
		if (backLayer == null || "".equals(layer.trim())){
142
			backLayer = "earth"; 
143
		}
144
		layer = "l="+backLayer;
145
//		for (String layerString : layerMap.keySet()){
146
//			layer += "," + layerString;
147
//		}
148
		//layer = "l=" + layer.substring(1); //remove first |
149
		
150
		
151
		//style
152
		areaStyle = "";
153
		int i = 0;
154
		for (PresenceAbsenceTermBase<?> status: statusList){
155
			
156
			char style = getStyleAbbrev(i);
157
			
158
			//getting the area title
159
			if (languages == null){
160
				languages = new ArrayList<Language>();
161
				languages.add(Language.DEFAULT());
162
			}
163
			Representation representation = 
164
				status.getPreferredRepresentation(languages);
165
			String statusLabel = representation.getLabel();
166
			areaTitle += "|" + style + ":" + statusLabel;
167
			
168
			//getting the area color
169
			Color statusColor = presenceAbsenceTermColors.get(status);
170
			String rgb;
171
			if (statusColor != null){
172
				rgb = Integer.toHexString(statusColor.getRGB()).substring(2);
173
			}else{
174
				if(status != null){
175
					rgb = status.getDefaultColor(); //TODO
176
				} else {
177
					rgb = defaultStatus.getDefaultColor();
178
				}
179
			}
180
			areaStyle += "|" + style + ":" + rgb;
181

    
182
			if (borderWidth >0){
183
				areaStyle += ",," + borderWidth;
184
			}
185

    
186
			i++;			
187
		}
188
		
189
		if(areaStyle.length() > 0){
190
			areaStyle = "as=" + areaStyle.substring(1); //remove first |
191
		}
192
		if(areaTitle.length() > 0){
193
			areaTitle = "title=" + areaTitle.substring(1); //remove first |
194
		}
195
		
196
		boolean separateLevels = false; //FIXME as parameter
197
		//areaData
198
		areaData = "";
199
		boolean isFirstLayer = true;
200
		Map<String, String> resultMap = new HashMap<String, String>();
201
		
202
		for (String layerString : layerMap.keySet()){
203
			//Set<Distribution> layerDistributions = layerData.get(layerIndex);
204
			//int distributionListIndex = 1;
205
			areaData += (isFirstLayer? "" : "||") + layerString + adLayerSeparator;
206
			Map<Integer, Set<Distribution>> styleMap = layerMap.get(layerString);
207
			boolean isFirstStyle = true;
208
			for (int style: styleMap.keySet()){
209
				char styleChar = getStyleAbbrev(style);
210
				areaData += (isFirstStyle? "" : styleInAreaDataSeparator) + styleChar + ":";
211
				Set<Distribution> distributionSet = styleMap.get(style);
212
				boolean isFirstDistribution = true;
213
				for (Distribution distribution: distributionSet){
214
					String areaAbbrev = getAreaAbbrev(distribution);
215
					areaData += (isFirstDistribution ? "" : ",") + areaAbbrev;
216
					isFirstDistribution = false;
217
				}
218
				isFirstStyle = false;
219
			}
220
			isFirstLayer = separateLevels;
221
			if(separateLevels){
222
				//result per level
223
				result = CdmUtils.concat("&", new String[] {layer, "ad=" + areaData.substring(0), areaStyle, areaTitle, bbox, ms});
224
				resultMap.put(layerString, result);
225
			}
226
		}
227
		
228
		areaData = "ad=" + areaData.substring(0); //remove first |
229
		
230
		//result
231
		result = CdmUtils.concat("&", new String[] {layer, areaData, areaStyle, areaTitle, bbox, ms});
232
		if (logger.isDebugEnabled()){logger.debug("getEditGeoServiceUrlParameterString end");}
233
		
234
		return result;
235
	}
236
	
237
	private static Map<PresenceAbsenceTermBase<?>,Color> makeDefaultColorMap(){
238
		Map<PresenceAbsenceTermBase<?>,Color> result = new HashMap<PresenceAbsenceTermBase<?>, Color>();
239
		try {
240
			result.put(PresenceTerm.PRESENT(), Color.decode("0x4daf4a"));
241
			result.put(PresenceTerm.NATIVE(), Color.decode("0x4daf4a"));
242
			result.put(PresenceTerm.NATIVE_DOUBTFULLY_NATIVE(), Color.decode("0x377eb8"));
243
			result.put(PresenceTerm.CULTIVATED(), Color.decode("0x984ea3"));
244
			result.put(PresenceTerm.INTRODUCED(), Color.decode("0xff7f00"));
245
			result.put(PresenceTerm.INTRODUCED_ADVENTITIOUS(), Color.decode("0xffff33"));
246
			result.put(PresenceTerm.INTRODUCED_CULTIVATED(), Color.decode("0xa65628"));
247
			result.put(PresenceTerm.INTRODUCED_NATURALIZED(), Color.decode("0xf781bf"));
248
		} catch (NumberFormatException nfe) {
249
			logger.error(nfe);
250
		}
251
		return result;
252
	}
253
	
254
	
255
	private static String getAreaAbbrev(Distribution distribution){
256
		NamedArea area = distribution.getArea();
257
		Representation representation = area.getRepresentation(Language.DEFAULT());
258
		String areaAbbrev = representation.getAbbreviatedLabel();
259
		if (area.getLevel() != null && area.getLevel().equals(NamedAreaLevel.TDWG_LEVEL4())){
260
			areaAbbrev = areaAbbrev.replace("-", "");
261
		}
262
		return areaAbbrev;
263
	}
264
	
265
	
266
	/**
267
	 * transform an integer (style counter) into a valid character representing a style.
268
	 * 0-25 => a-z<br>
269
	 * 26-51 => A-Z<br>
270
	 * i not in {0,...,51} is undefined
271
	 * @param i
272
	 * @return
273
	 */
274
	private static char getStyleAbbrev(int i){
275
		i++;
276
		int ascii = 96 + i;
277
		if (i >26){
278
			ascii = 64 + i;
279
		}
280
		return (char)ascii;
281
	}
282
	
283
	private static String getGeoServiceLayer(NamedAreaLevel level){
284
		//TODO integrate into CDM 
285
		if (level.equals(NamedAreaLevel.TDWG_LEVEL1())){
286
			return "tdwg1";
287
		}else if (level.equals(NamedAreaLevel.TDWG_LEVEL2())){
288
			return "tdwg2";
289
		}if (level.equals(NamedAreaLevel.TDWG_LEVEL3())){
290
			return "tdwg3";
291
		}if (level.equals(NamedAreaLevel.TDWG_LEVEL4())){
292
			return "tdwg4";
293
		}
294
		return "unknown";
295
	}
296
	
297
	private static void addDistributionToMap(Distribution distribution, Map<Integer, Set<Distribution>> styleMap,
298
			List<PresenceAbsenceTermBase<?>> statusList) {
299
		PresenceAbsenceTermBase<?> status = distribution.getStatus();
300
		if (status == null) {
301
			status = defaultStatus;
302
		}
303
		int style = statusList.indexOf(status);
304
		Set<Distribution> distributionSet = styleMap.get(style);
305
		if (distributionSet == null) {
306
			distributionSet = new HashSet<Distribution>();
307
			styleMap.put(style, distributionSet);
308
		}
309
		distributionSet.add(distribution);
310
	}
311
	
312

    
313
	
314
	/**
315
	 * @param args
316
	 */
317
	public static void main(String[] args) {
318
		// TODO Auto-generated method stub
319

    
320
	}
321
}
(2-2/3)