001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.vfny.geoserver.action.data;
006:
007: import org.apache.struts.action.ActionForm;
008: import org.apache.struts.action.ActionForward;
009: import org.apache.struts.action.ActionMapping;
010: import org.apache.struts.util.MessageResources;
011: import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
012: import org.geotools.coverage.grid.io.AbstractGridFormat;
013: import org.geotools.factory.FactoryRegistryException;
014: import org.geotools.geometry.GeneralEnvelope;
015: import org.geotools.referencing.CRS;
016: import org.geotools.referencing.NamedIdentifier;
017: import org.geotools.resources.CRSUtilities;
018: import org.opengis.coverage.grid.Format;
019: import org.opengis.geometry.MismatchedDimensionException;
020: import org.opengis.referencing.FactoryException;
021: import org.opengis.referencing.NoSuchAuthorityCodeException;
022: import org.opengis.referencing.crs.CoordinateReferenceSystem;
023: import org.opengis.referencing.cs.AxisDirection;
024: import org.opengis.referencing.cs.CoordinateSystem;
025: import org.opengis.referencing.operation.MathTransform;
026: import org.opengis.referencing.operation.TransformException;
027: import org.vfny.geoserver.action.ConfigAction;
028: import org.vfny.geoserver.action.HTMLEncoder;
029: import org.vfny.geoserver.config.CoverageConfig;
030: import org.vfny.geoserver.config.DataConfig;
031: import org.vfny.geoserver.form.data.CoveragesEditorForm;
032: import org.vfny.geoserver.global.CoverageStoreInfo;
033: import org.vfny.geoserver.global.Data;
034: import org.vfny.geoserver.global.GeoserverDataDirectory;
035: import org.vfny.geoserver.global.MetaDataLink;
036: import org.vfny.geoserver.global.UserContainer;
037: import java.io.IOException;
038: import java.util.Collections;
039: import java.util.HashMap;
040: import java.util.Iterator;
041: import java.util.LinkedList;
042: import java.util.List;
043: import java.util.Locale;
044: import java.util.Map;
045: import java.util.Set;
046: import java.util.logging.Level;
047: import javax.servlet.ServletException;
048: import javax.servlet.http.HttpServletRequest;
049: import javax.servlet.http.HttpServletResponse;
050:
051: /**
052: * These Action handles all the buttons for the Coverage Editor.
053: *
054: * <p>
055: * Buttons that make this action go:
056: *
057: * <ul>
058: * <li> Submit: update the CoverageConfig held by the user, punt it back into
059: * DataConfig and return to the CoverageSelect screen. </li>
060: * </ul>
061: *
062: * As usual we will have to uninternationlize the action name provided to us.
063: * </p>
064: *
065: * @author Richard Gould
066: * @author Jody Garnett
067: * @author $Author: Alessio Fabiani (alessio.fabiani@gmail.com) $ (last
068: * modification)
069: * @author $Author: Simone Giannecchini (simboss1@gmail.com) $ (last
070: * modification)
071: */
072: public final class CoveragesEditorAction extends ConfigAction {
073: public ActionForward execute(ActionMapping mapping,
074: ActionForm form, UserContainer user,
075: HttpServletRequest request, HttpServletResponse response)
076: throws IOException, ServletException {
077: if (LOGGER.isLoggable(Level.FINER)) {
078: LOGGER.finer(new StringBuffer("form bean:").append(
079: form.getClass().getName()).toString());
080: }
081:
082: final CoveragesEditorForm coverageForm = (CoveragesEditorForm) form;
083:
084: String action = coverageForm.getAction();
085:
086: if (LOGGER.isLoggable(Level.FINER)) {
087: LOGGER.finer(new StringBuffer("CoveragesEditorAction is ")
088: .append(action).toString());
089: }
090:
091: String newCoverage = coverageForm.getNewCoverage();
092:
093: if (LOGGER.isLoggable(Level.FINER)) {
094: LOGGER.finer(new StringBuffer("CoveragesEditorNew is ")
095: .append(newCoverage).toString());
096: }
097:
098: Locale locale = (Locale) request.getLocale();
099: MessageResources messages = getResources(request);
100: final String SUBMIT = HTMLEncoder.decode(messages.getMessage(
101: locale, "label.submit"));
102: final String ENVELOPE = HTMLEncoder.decode(messages.getMessage(
103: locale, "config.data.calculateBoundingBox.label"));
104: final String LOOKUP_SRS = HTMLEncoder.decode(messages
105: .getMessage(locale, "config.data.lookupSRS.label"));
106:
107: if (LOGGER.isLoggable(Level.FINER)) {
108: LOGGER.finer(new StringBuffer("ENVELOPE: ")
109: .append(ENVELOPE).toString());
110: }
111:
112: if (SUBMIT.equals(action)) {
113: return executeSubmit(mapping, coverageForm, user, request);
114: }
115:
116: if ((newCoverage != null) && "true".equals(newCoverage)) {
117: if (LOGGER.isLoggable(Level.FINER)) {
118: LOGGER.finer(new StringBuffer("NEW COVERAGE: ").append(
119: newCoverage).toString());
120: }
121:
122: request.setAttribute(
123: DataCoveragesNewAction.NEW_COVERAGE_KEY, "true");
124: }
125:
126: if (ENVELOPE.equals(action)) {
127: return executeEnvelope(mapping, coverageForm, user, request);
128: }
129:
130: if (LOOKUP_SRS.equals(action)) {
131: return executeLookupSRS(mapping, coverageForm, user,
132: request);
133: }
134:
135: // Update, Up, Down, Add, Remove need to resync
136: try {
137: sync(coverageForm, user.getCoverageConfig(), request);
138: } catch (FactoryException e) {
139: throw new ServletException(e);
140: }
141:
142: form.reset(mapping, request);
143:
144: return mapping.findForward("config.data.coverage.editor");
145: }
146:
147: /**
148: * Populate the bounding box fields from the source and pass control back to
149: * the UI
150: *
151: * @param mapping
152: * DOCUMENT ME!
153: * @param coverageForm
154: * DOCUMENT ME!
155: * @param user
156: * DOCUMENT ME!
157: * @param request
158: * DOCUMENT ME!
159: *
160: * @return DOCUMENT ME!
161: *
162: * @throws IOException
163: * DOCUMENT ME!
164: * @throws ServletException
165: * DOCUMENT ME!
166: */
167: private ActionForward executeEnvelope(ActionMapping mapping,
168: CoveragesEditorForm coverageForm, UserContainer user,
169: HttpServletRequest request) throws IOException,
170: ServletException {
171: final String formatID = coverageForm.getFormatId();
172: final Data catalog = getData();
173: CoverageStoreInfo cvStoreInfo = catalog.getFormatInfo(formatID);
174:
175: if (cvStoreInfo == null) {
176: cvStoreInfo = new CoverageStoreInfo(getDataConfig()
177: .getDataFormat(formatID).toDTO(), catalog);
178: }
179:
180: final Format format = cvStoreInfo.getFormat();
181: AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) cvStoreInfo
182: .getReader();
183:
184: if (reader == null) {
185: reader = (AbstractGridCoverage2DReader) ((AbstractGridFormat) format)
186: .getReader(GeoserverDataDirectory
187: .findDataFile(cvStoreInfo.getUrl()));
188: }
189:
190: try {
191: final CoordinateReferenceSystem sourceCRS = reader.getCrs();
192: final GeneralEnvelope gEnvelope = reader
193: .getOriginalEnvelope();
194: final GeneralEnvelope targetEnvelope = gEnvelope;
195: GeneralEnvelope envelope = targetEnvelope;
196:
197: if (sourceCRS.getIdentifiers().isEmpty()) {
198: String nativeCRS = coverageForm.getSrsName();
199:
200: if (nativeCRS != null) {
201: MathTransform transform;
202:
203: if (!nativeCRS.toUpperCase().startsWith("EPSG:")) {
204: try {
205: nativeCRS = "EPSG:"
206: + Integer.decode(nativeCRS);
207: transform = CRS.findMathTransform(
208: sourceCRS, CRS.decode(nativeCRS),
209: true);
210: envelope = CRSUtilities.transform(
211: transform, envelope);
212: coverageForm.setSrsName(nativeCRS);
213: } catch (NumberFormatException e) {
214: coverageForm.setSrsName("UNKNOWN");
215: }
216: } else {
217: transform = CRS.findMathTransform(sourceCRS,
218: CRS.decode(nativeCRS), true);
219: envelope = CRSUtilities.transform(transform,
220: envelope);
221: }
222: } else {
223: coverageForm.setSrsName("UNKNOWN");
224: }
225: } else {
226: String identifier = sourceCRS.getIdentifiers()
227: .toArray()[0].toString();
228:
229: /*
230: * CRS.lookupIdentifier(sourceCRS, Collections
231: * .singleton("EPSG"), false);
232: */
233: if ((identifier != null)
234: && !identifier.startsWith("EPSG:")) {
235: identifier = "EPSG:" + identifier;
236: }
237:
238: coverageForm.setSrsName(identifier);
239: }
240:
241: coverageForm.setWKTString(sourceCRS.toWKT());
242: coverageForm.setMinX(Double.toString(envelope
243: .getLowerCorner().getOrdinate(0)));
244: coverageForm.setMaxX(Double.toString(envelope
245: .getUpperCorner().getOrdinate(0)));
246: coverageForm.setMinY(Double.toString(envelope
247: .getLowerCorner().getOrdinate(1)));
248: coverageForm.setMaxY(Double.toString(envelope
249: .getUpperCorner().getOrdinate(1)));
250: } catch (FactoryRegistryException e) {
251: throw new ServletException(e);
252: } catch (MismatchedDimensionException e) {
253: throw new ServletException(e);
254: } catch (IndexOutOfBoundsException e) {
255: throw new ServletException(e);
256: } catch (NoSuchAuthorityCodeException e) {
257: throw new ServletException(e);
258: } catch (FactoryException e) {
259: throw new ServletException(e);
260: } catch (TransformException e) {
261: throw new ServletException(e);
262: }
263:
264: return mapping.findForward("config.data.coverage.editor");
265: }
266:
267: /**
268: * Sync generated attributes with schemaBase.
269: *
270: * @param form
271: * @param config
272: * @throws FactoryException
273: */
274: private void sync(CoveragesEditorForm form, CoverageConfig config,
275: HttpServletRequest request) throws FactoryException {
276: config.setDefaultInterpolationMethod(form
277: .getDefaultInterpolationMethod());
278: config.setDescription(form.getDescription());
279: config.setInterpolationMethods(interpolationMethods(form));
280: config.setKeywords(keyWords(form));
281: config.setLabel(form.getLabel());
282: config.setMetadataLink(metadataLink(form));
283: config.setNativeFormat(form.getNativeFormat());
284: config.setRequestCRSs(requestCRSs(form));
285: config.setResponseCRSs(responseCRSs(form));
286: config.setCrs(CRS.parseWKT(form.getWKTString()));
287: if (!form.getSrsName().toUpperCase().startsWith("EPSG"))
288: config.setSrsName("EPSG:" + form.getSrsName());
289: else
290: config.setSrsName(form.getSrsName());
291: config.setSrsWKT(form.getWKTString());
292:
293: if (!"UNKNOWN".equals(config.getSrsName())
294: && (config.getSrsName() != null)
295: && config.getSrsName().toUpperCase()
296: .startsWith("EPSG:")) {
297: config.setCrs(CRS.decode(config.getSrsName()));
298: }
299:
300: config.setEnvelope(getEnvelope(form, config.getCrs()));
301: config.setSupportedFormats(supportedFormats(form));
302: config.setDefaultStyle(form.getStyleId());
303:
304: config.getStyles().clear();
305: if (form.getOtherSelectedStyles() != null) {
306:
307: for (int i = 0; i < form.getOtherSelectedStyles().length; i++) {
308: config.addStyle(form.getOtherSelectedStyles()[i]);
309: }
310: }
311:
312: config.setName(form.getName());
313: config.setWmsPath(form.getWmsPath());
314:
315: final StringBuffer temp = new StringBuffer(config.getFormatId());
316: temp.append("_").append(form.getName());
317: config.setDirName(temp.toString());
318:
319: /**
320: * Sync params
321: */
322: final Map params = new HashMap();
323: Iterator it = form.getParamKeys().iterator();
324: String paramKey;
325: String paramValue;
326: int index = 0;
327:
328: while (it.hasNext()) {
329: paramKey = (String) it.next();
330: paramValue = (String) form.getParamValues().get(index);
331: params.put(paramKey, paramValue);
332: index++;
333: }
334:
335: config.setParameters(params);
336: }
337:
338: /**
339: * Execute Submit Action.
340: *
341: * @param mapping
342: * @param form
343: * @param user
344: * @param request
345: *
346: * @return
347: * @throws FactoryException
348: */
349: private ActionForward executeSubmit(ActionMapping mapping,
350: CoveragesEditorForm form, UserContainer user,
351: HttpServletRequest request) throws IOException {
352: final CoverageConfig config = user.getCoverageConfig();
353:
354: try {
355: sync(form, config, request);
356: } catch (FactoryException e) {
357: final IOException ex = new IOException(e
358: .getLocalizedMessage());
359: ex.initCause(e);
360: throw ex;
361: }
362:
363: final DataConfig dataConfig = (DataConfig) getDataConfig();
364: final StringBuffer coverage = new StringBuffer(config
365: .getFormatId());
366: dataConfig.addCoverage(coverage.append(":").append(
367: config.getName()).toString(), config);
368:
369: // Don't think reset is needed (as me have moved on to new page)
370: // form.reset(mapping, request);
371: getApplicationState().notifyConfigChanged();
372:
373: // Coverage no longer selected
374: user.setCoverageConfig(null);
375:
376: return mapping.findForward("config.data.coverage");
377: }
378:
379: /**
380: *
381: *
382: * @param coverageForm
383: * @param system
384: *
385: * @return Bounding box in lat long TODO is this correct
386: */
387: private GeneralEnvelope getEnvelope(
388: CoveragesEditorForm coverageForm,
389: CoordinateReferenceSystem crs) {
390: final double[] coordinates = new double[4];
391: final CoordinateSystem cs = crs.getCoordinateSystem();
392: boolean lonFirst = true;
393:
394: if (AxisDirection.NORTH.equals(cs.getAxis(0).getDirection()
395: .absolute())) {
396: lonFirst = false;
397: }
398:
399: boolean swapXY = !lonFirst;
400:
401: // latitude index
402: final int latIndex = lonFirst ? 1 : 0;
403:
404: final AxisDirection latitude = cs.getAxis(latIndex)
405: .getDirection();
406: final AxisDirection longitude = cs.getAxis((latIndex + 1) % 2)
407: .getDirection();
408: final boolean[] reverse = new boolean[] {
409: lonFirst ? (!longitude.equals(AxisDirection.EAST))
410: : (!latitude.equals(AxisDirection.NORTH)),
411: lonFirst ? (!latitude.equals(AxisDirection.NORTH))
412: : (!longitude.equals(AxisDirection.EAST)) };
413:
414: coordinates[0] = ((!reverse[(latIndex + 1) % 2]) ? ((!swapXY) ? Double
415: .parseDouble(coverageForm.getMinX())
416: : Double.parseDouble(coverageForm.getMinY()))
417: : ((!swapXY) ? Double.parseDouble(coverageForm
418: .getMaxX()) : Double.parseDouble(coverageForm
419: .getMaxY())));
420: coordinates[1] = ((!reverse[latIndex]) ? ((!swapXY) ? Double
421: .parseDouble(coverageForm.getMinY()) : Double
422: .parseDouble(coverageForm.getMinX()))
423: : ((!swapXY) ? Double.parseDouble(coverageForm
424: .getMaxY()) : Double.parseDouble(coverageForm
425: .getMaxX())));
426: coordinates[2] = ((!reverse[(latIndex + 1) % 2]) ? ((!swapXY) ? Double
427: .parseDouble(coverageForm.getMaxX())
428: : Double.parseDouble(coverageForm.getMaxY()))
429: : ((!swapXY) ? Double.parseDouble(coverageForm
430: .getMinX()) : Double.parseDouble(coverageForm
431: .getMinY())));
432: coordinates[3] = ((!reverse[latIndex]) ? ((!swapXY) ? Double
433: .parseDouble(coverageForm.getMaxY()) : Double
434: .parseDouble(coverageForm.getMaxX()))
435: : ((!swapXY) ? Double.parseDouble(coverageForm
436: .getMinY()) : Double.parseDouble(coverageForm
437: .getMinX())));
438:
439: GeneralEnvelope envelope = new GeneralEnvelope(new double[] {
440: coordinates[0], coordinates[1] }, new double[] {
441: coordinates[2], coordinates[3] });
442:
443: envelope.setCoordinateReferenceSystem(crs);
444:
445: return envelope;
446: }
447:
448: private ActionForward executeLookupSRS(ActionMapping mapping,
449: CoveragesEditorForm coverageForm, UserContainer user,
450: HttpServletRequest request) throws IOException,
451: ServletException {
452: final String formatID = coverageForm.getFormatId();
453: final Data catalog = getData();
454: CoverageStoreInfo cvStoreInfo = catalog.getFormatInfo(formatID);
455:
456: if (cvStoreInfo == null) {
457: cvStoreInfo = new CoverageStoreInfo(getDataConfig()
458: .getDataFormat(formatID).toDTO(), catalog);
459: }
460:
461: final Format format = cvStoreInfo.getFormat();
462: AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) cvStoreInfo
463: .getReader();
464:
465: if (reader == null) {
466: reader = (AbstractGridCoverage2DReader) ((AbstractGridFormat) format)
467: .getReader(GeoserverDataDirectory
468: .findDataFile(cvStoreInfo.getUrl()));
469: }
470:
471: try {
472: final CoordinateReferenceSystem sourceCRS = reader.getCrs();
473: final GeneralEnvelope gEnvelope = reader
474: .getOriginalEnvelope();
475: final GeneralEnvelope targetEnvelope = gEnvelope;
476: GeneralEnvelope envelope = targetEnvelope;
477: String s = CRS.lookupIdentifier(sourceCRS, true);
478:
479: if (s == null) {
480: coverageForm.setSrsName("UNKNOWN");
481: } else if (s.toUpperCase().startsWith("EPSG:")) {
482: coverageForm.setSrsName(s);
483: } else {
484: coverageForm.setSrsName("EPSG:" + s);
485: }
486: } catch (Exception e) {
487: coverageForm.setSrsName("UNKNOWN");
488: }
489:
490: return mapping.findForward("config.data.coverage.editor");
491: }
492:
493: private MetaDataLink metadataLink(CoveragesEditorForm coverageForm) {
494: MetaDataLink ml = new MetaDataLink();
495:
496: if ((coverageForm.getMetadataLink() != null)
497: && (coverageForm.getMetadataLink().length() > 0)) {
498: ml.setAbout(coverageForm.getMetadataLink());
499: ml.setMetadataType("other");
500: } else {
501: ml = null;
502: }
503:
504: return ml;
505: }
506:
507: /**
508: * DOCUMENT ME!
509: *
510: * @param coverageForm
511: *
512: * @return Set of keywords
513: */
514: private List keyWords(CoveragesEditorForm coverageForm) {
515: LinkedList keywords = new LinkedList();
516: String[] array = (coverageForm.getKeywords() != null) ? coverageForm
517: .getKeywords().split(" ")
518: : new String[0];
519: final int length = array.length;
520:
521: for (int i = 0; i < length; i++) {
522: keywords.add(array[i]);
523: }
524:
525: return keywords;
526: }
527:
528: private List interpolationMethods(CoveragesEditorForm coverageForm) {
529: LinkedList interpolationMethods = new LinkedList();
530: String[] array = (coverageForm.getInterpolationMethods() != null) ? coverageForm
531: .getInterpolationMethods().split(",")
532: : new String[0];
533: final int length = array.length;
534:
535: for (int i = 0; i < length; i++) {
536: interpolationMethods.add(array[i]);
537: }
538:
539: return interpolationMethods;
540: }
541:
542: private List requestCRSs(CoveragesEditorForm coverageForm) {
543: LinkedList requestCRSs = new LinkedList();
544: String[] array = (coverageForm.getRequestCRSs() != null) ? coverageForm
545: .getRequestCRSs().split(",")
546: : new String[0];
547: final int length = array.length;
548:
549: for (int i = 0; i < length; i++) {
550: requestCRSs.add(array[i]);
551: }
552:
553: return requestCRSs;
554: }
555:
556: private List responseCRSs(CoveragesEditorForm coverageForm) {
557: LinkedList responseCRSs = new LinkedList();
558: String[] array = (coverageForm.getResponseCRSs() != null) ? coverageForm
559: .getResponseCRSs().split(",")
560: : new String[0];
561: final int length = array.length;
562:
563: for (int i = 0; i < length; i++) {
564: responseCRSs.add(array[i]);
565: }
566:
567: return responseCRSs;
568: }
569:
570: private List supportedFormats(CoveragesEditorForm coverageForm) {
571: LinkedList supportedFormats = new LinkedList();
572: String[] array = (coverageForm.getSupportedFormats() != null) ? coverageForm
573: .getSupportedFormats().split(",")
574: : new String[0];
575: final int length = array.length;
576:
577: for (int i = 0; i < length; i++) {
578: supportedFormats.add(array[i]);
579: }
580:
581: return supportedFormats;
582: }
583: }
|