001: //=============================================================================
002: //=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
003: //=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
004: //=== and United Nations Environment Programme (UNEP)
005: //===
006: //=== This program is free software; you can redistribute it and/or modify
007: //=== it under the terms of the GNU General Public License as published by
008: //=== the Free Software Foundation; either version 2 of the License, or (at
009: //=== your option) any later version.
010: //===
011: //=== This program is distributed in the hope that it will be useful, but
012: //=== WITHOUT ANY WARRANTY; without even the implied warranty of
013: //=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: //=== General Public License for more details.
015: //===
016: //=== You should have received a copy of the GNU General Public License
017: //=== along with this program; if not, write to the Free Software
018: //=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
019: //===
020: //=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
021: //=== Rome - Italy. email: geonetwork@osgeo.org
022: //==============================================================================
023:
024: package org.wfp.vam.intermap.services.map;
025:
026: import java.net.URLDecoder;
027: import java.util.ArrayList;
028: import java.util.Collections;
029: import java.util.HashMap;
030: import java.util.List;
031: import java.util.StringTokenizer;
032: import jeeves.server.UserSession;
033: import jeeves.server.context.ServiceContext;
034: import org.jdom.Element;
035: import org.wfp.vam.intermap.Constants;
036: import org.wfp.vam.intermap.kernel.map.DefaultMapServers;
037: import org.wfp.vam.intermap.kernel.map.MapMerger;
038: import org.wfp.vam.intermap.kernel.map.mapServices.BoundingBox;
039: import org.wfp.vam.intermap.kernel.map.mapServices.MapService;
040: import org.wfp.vam.intermap.kernel.map.mapServices.arcims.ArcIMSService;
041: import org.wfp.vam.intermap.kernel.map.mapServices.wmc.schema.type.WMCExtension;
042: import org.wfp.vam.intermap.kernel.map.mapServices.wmc.schema.type.WMCLayer;
043: import org.wfp.vam.intermap.kernel.map.mapServices.wmc.schema.type.WMCViewContext;
044: import org.wfp.vam.intermap.kernel.map.mapServices.wmc.schema.type.WMCWindow;
045: import org.wfp.vam.intermap.kernel.map.mapServices.wms.CapabilitiesStore;
046: import org.wfp.vam.intermap.kernel.map.mapServices.wms.WmsService;
047:
048: public class MapUtil {
049: private static int _minh;
050: private static int _minw;
051: private static int _maxh;
052: private static int _maxw;
053:
054: private static String defaultImageSize;
055:
056: private static String url;
057:
058: public static void setImageSizes(int minh, int minw, int maxh,
059: int maxw) {
060: _minh = minh;
061: _minw = minw;
062: _maxh = maxh;
063: _maxw = maxw;
064: }
065:
066: // Returns the MapMerger object for the user session
067: public static MapMerger getMapMerger(ServiceContext context) {
068: MapMerger mm = (MapMerger) context.getUserSession()
069: .getProperty(Constants.SESSION_MAP);
070: if (mm == null)
071: mm = new MapMerger();
072:
073: return mm;
074: }
075:
076: public static void setAoi(ServiceContext context, float minx,
077: float miny, float maxx, float maxy) throws Exception {
078: BoundingBox bb = new BoundingBox(maxy, miny, maxx, minx);
079:
080: UserSession us = context.getUserSession();
081: us.setProperty("aoi", bb);
082: }
083:
084: protected static BoundingBox getAoi(ServiceContext context)
085: throws Exception {
086: UserSession us = context.getUserSession();
087: return (BoundingBox) us.getProperty("aoi");
088: }
089:
090: protected static void unsetAoi(ServiceContext context)
091: throws Exception {
092: UserSession us = context.getUserSession();
093: us.setProperty("aoi", new BoundingBox(0, 0, 0, 0)); // there is no way at the moment to set it null or delete it
094: }
095:
096: protected static void setActiveLayer(Element request, MapMerger mm)
097: throws Exception {
098: StringTokenizer t = new StringTokenizer(request
099: .getChildText("activeLayer"), "_");
100: try {
101: mm.setActiveLayer(Integer.parseInt(t.nextToken()), Integer
102: .parseInt(t.nextToken()));
103: } catch (Exception e) {
104: } // Who cares?
105: }
106:
107: protected static void setVisibleLayers(Element request, MapMerger mm) {
108: for (Element param : (List<Element>) request.getChildren()) {
109: String key = param.getName();
110: String value = param.getText();
111: StringTokenizer t = new StringTokenizer(key, "_");
112: if (t.hasMoreTokens()) {
113: if (t.nextToken().equals("layerVisible")) {
114: String serviceId = t.nextToken();
115: String layerId = t.nextToken();
116: MapService ms = mm.getService(Integer
117: .parseInt(serviceId));
118: if (ms != null) {
119: boolean visible = value.equals("true");
120: ms.setLayerVisible(layerId, visible);
121: }
122: }
123: }
124: }
125: }
126:
127: private static boolean existService(MapMerger mm, String serverUrl,
128: String serviceName) {
129: // Do not add the service if it is already there
130: for (MapService service : mm.getServices()) {
131: String url = service.getServerURL();
132: String name = service.getName();
133: if (url.equals(serverUrl) && name.equals(serviceName))
134: return true;
135: }
136:
137: return false;
138: }
139:
140: /**
141: * Add a WMCLayer ad a service.
142: * WMCLayer decoding is processed here.
143: */
144: public static int addService(MapMerger mm, WMCLayer layer)
145: throws Exception {
146: int id = addService(WmsService.TYPE, layer.getServer()
147: .getOnlineResource().getHref(), layer.getName(), "", // layer.getChildText("vendor_spec_par"); // DEBUG
148: mm);
149:
150: WMCExtension ext = layer.getExtension();
151: if (ext != null) {
152: Element et = ext.getChild("Transparency");
153: if (et != null)
154: mm.setTransparency(id, Float.parseFloat(et.getText()));
155: }
156:
157: return id;
158: }
159:
160: /**
161: * @return the id of the service, or -1 if the service has not been added
162: */
163: public static int addService(int serverType, String serverUrl,
164: String serviceName, String vsp, MapMerger mm)
165: throws Exception {
166: // Do not add the service if it is already there
167: if (existService(mm, serverUrl, serviceName))
168: return -1;
169:
170: int ret;
171:
172: switch (serverType) {
173: case ArcIMSService.TYPE:
174: ret = mm.addService(new ArcIMSService(serverUrl,
175: serviceName));
176: break;
177:
178: case WmsService.TYPE:
179: // Element capabilities = WmsGetCapClient.getCapabilities(serverUrl); // Old version: we may need it in snv commit
180: Element capabilities = CapabilitiesStore
181: .getCapabilities(serverUrl); // NEW VERSION: WORK IN PROGRESS
182: WmsService s = new WmsService(serverUrl, serviceName,
183: capabilities);
184: ret = mm.addService(s);
185: setVendorSpecificParams(s, vsp);
186: break;
187:
188: default:
189: throw new IllegalArgumentException("Unknown serverType "
190: + serverType + " for service " + serviceName
191: + " @ " + serverUrl);
192: }
193:
194: return ret;
195: }
196:
197: private static void setVendorSpecificParams(WmsService service,
198: String params) {
199: if (params == null)
200: return;
201:
202: String stParams = URLDecoder.decode(params);
203:
204: HashMap hmParams = new HashMap();
205: StringTokenizer t1;
206: for (t1 = new StringTokenizer(stParams, "&"); t1
207: .hasMoreTokens();) {
208: String s = t1.nextToken();
209: int p = s.indexOf("=");
210:
211: if (p != -1) {
212: String name = s.substring(0, p);
213: // System.out.println("name:" + name);
214: String value = s.substring(p + 1, s.length());
215: // System.out.println("value: " + value);
216:
217: hmParams.put(name, value);
218: }
219: }
220:
221: // System.out.println("hmParams: " + hmParams);
222: service.setVendorSpecificParams(hmParams); //TEST
223: }
224:
225: public static void setDefaultContext(MapMerger mm) throws Exception {
226: Element mapContext = DefaultMapServers.getDefaultContext();
227:
228: // Add each layer in the map context to the map
229: for (Element elServer : (List<Element>) mapContext
230: .getChildren("server")) {
231: String serverType = elServer
232: .getAttributeValue(Constants.MAP_SERVER_TYPE);
233: String serverUrl = elServer
234: .getAttributeValue(Constants.MAP_SERVER_URL);
235:
236: for (Element elLayer : (List<Element>) elServer
237: .getChildren(Constants.MAP_LAYER)) {
238: try {
239: String serviceName = elLayer
240: .getAttributeValue("name");
241: MapUtil.addService(Integer.parseInt(serverType),
242: serverUrl, serviceName, "", mm);
243: } catch (Exception e) {
244: e.printStackTrace();
245: } // DEBUG: tell the user
246: }
247: }
248:
249: MapUtil.setDefBoundingBox(mm);
250: }
251:
252: public static void setDefBoundingBox(MapMerger mm) throws Exception {
253: List<BoundingBox> lbb = new ArrayList<BoundingBox>();
254: for (MapService service : mm.getServices())
255: lbb.add(service.getDefBoundingBox());
256:
257: mm.setBoundingBox(BoundingBox.union(lbb));
258: }
259:
260: protected static void setBBoxFromUrl(String bbox, MapMerger mm) {
261: StringTokenizer st = new StringTokenizer(bbox, ",");
262:
263: try {
264: float w = Float.parseFloat(st.nextToken());
265: float s = Float.parseFloat(st.nextToken());
266: float e = Float.parseFloat(st.nextToken());
267: float n = Float.parseFloat(st.nextToken());
268:
269: mm.setBoundingBox(new BoundingBox(n, s, e, w));
270: }
271:
272: catch (Exception e) {
273: mm.setBoundingBox(new BoundingBox());
274: }
275: }
276:
277: /**
278: * @deprecated ETj: image dimensions are no longer handled server side
279: */
280: public static int getImageWidth(ServiceContext srvContext) {
281: String size = (String) srvContext.getUserSession().getProperty(
282: Constants.SESSION_SIZE);
283: int width;
284: if (size.equals("small"))
285: width = _minw;
286: else
287: width = _maxw;
288:
289: return width;
290: }
291:
292: /**
293: * @deprecated ETj: image dimensions are no longer handled server side
294: */
295: public static int getImageHeight(ServiceContext srvContext) {
296: String size = (String) srvContext.getUserSession().getProperty(
297: Constants.SESSION_SIZE);
298: int height;
299: if (size.equals("small"))
300: height = _minh;
301: else
302: height = _maxh;
303:
304: return height;
305: }
306:
307: // Returns the MapMerger object for the user session
308: static String getTool(ServiceContext srvContext) {
309: String tool = (String) srvContext.getUserSession().getProperty(
310: Constants.SESSION_TOOL);
311: if (tool == null)
312: tool = Constants.DEFAULT_TOOL;
313:
314: return tool;
315: }
316:
317: public static void setTempUrl(String url) {
318: MapUtil.url = url;
319: }
320:
321: public static String getTempUrl() {
322: return MapUtil.url;
323: }
324:
325: protected static void moveTo(BoundingBox bb, int x, int y,
326: int width, int height) throws Exception {
327: float mapX = bb.getWest() + (bb.getEast() - bb.getWest()) * x
328: / width;
329: float mapY = bb.getNorth() - (bb.getNorth() - bb.getSouth())
330: * y / height;
331: bb.moveTo(mapX, mapY);
332: }
333:
334: protected static BoundingBox move(BoundingBox bb, int deltaX,
335: int deltaY, int width, int height) throws Exception {
336: float mapX = (bb.getEast() - bb.getWest()) * (float) deltaX
337: / width;
338: float mapY = (bb.getNorth() - bb.getSouth()) * (float) deltaY
339: / height;
340: return bb.move(mapX, mapY);
341: }
342:
343: protected static BoundingBox zoomInBox(BoundingBox bb, int mapimgx,
344: int mapimgy, int mapimgx2, int mapimgy2, int imageWidth,
345: int imageHeigth) throws Exception {
346:
347: // Move and zoom
348: float mapX = bb.getWest() + (bb.getEast() - bb.getWest())
349: * mapimgx / imageWidth;
350: float mapY = bb.getNorth() - (bb.getNorth() - bb.getSouth())
351: * mapimgy / imageHeigth;
352: float mapX2 = bb.getWest() + (bb.getEast() - bb.getWest())
353: * mapimgx2 / imageWidth;
354: float mapY2 = bb.getNorth() - (bb.getNorth() - bb.getSouth())
355: * mapimgy2 / imageHeigth;
356:
357: return new BoundingBox(mapY2, mapY, mapX2, mapX);
358: }
359:
360: protected static BoundingBox zoomOutBox(BoundingBox bb,
361: int mapimgx, int mapimgy, int mapimgx2, int mapimgy2,
362: int imageWidth, int imageHeight) throws Exception {
363:
364: // Move and zoom
365: float north = bb.getNorth() + (bb.getNorth() - bb.getSouth())
366: * imageHeight / (mapimgy - mapimgy2);
367: float south = bb.getSouth() - (bb.getNorth() - bb.getSouth())
368: * imageHeight / (mapimgy - mapimgy2);
369: float east = bb.getEast() + (bb.getEast() - bb.getWest())
370: * imageWidth / (mapimgx2 - mapimgx);
371: float west = bb.getWest() - (bb.getEast() - bb.getWest())
372: * imageWidth / (mapimgx2 - mapimgx);
373:
374: // System.out.println("north : " + north + "; south = " + south + "; east = " + east + "; west = " + west);
375:
376: return new BoundingBox(north, south, east, west);
377: }
378:
379: public static BoundingBox setScale(BoundingBox bb, int imageWidth,
380: int imageHeight, long scale, float dpi) throws Exception {
381: float cx = (bb.getEast() + bb.getWest()) / 2;
382: float cy = (bb.getNorth() + bb.getSouth()) / 2;
383:
384: // Set the scale
385: double degScale = scale / 423307109.727 * 96f / dpi;
386: float dx = (float) (imageWidth * degScale);
387: float dy = (float) (imageHeight * degScale);
388:
389: return new BoundingBox(cy + dy / 2, cy - dy / 2, cx + dx / 2,
390: cx - dx / 2);
391: }
392:
393: public static void setDefaultImageSize(String s) {
394: defaultImageSize = s;
395: }
396:
397: public static String getDefaultImageSize() {
398: return defaultImageSize;
399: }
400:
401: public static String setContext(MapMerger mm, WMCViewContext vc)
402: throws Exception {
403: for (WMCLayer layer : vc.getLayerList()) {
404: try {
405: MapUtil.addService(mm, layer);
406: } catch (Exception e) {
407: e.printStackTrace();
408: }
409: }
410:
411: // set bounding box
412: mm.setBoundingBox(new BoundingBox(vc.getGeneral()
413: .getBoundingBox()));
414:
415: WMCWindow win = vc.getGeneral().getWindow();
416: String imagename = mm.merge(win.getWidth(), win.getHeight());
417: String url = MapUtil.getTempUrl() + "/" + imagename;
418:
419: return url;
420: }
421: }
|