/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2007 by:
Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53177 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.igeo.commands.model;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import net.sf.ehcache.Cache;
import org.deegree.datatypes.QualifiedName;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.HttpUtils;
import org.deegree.framework.util.StringTools;
import org.deegree.framework.xml.XMLFragment;
import org.deegree.framework.xml.XMLParsingException;
import org.deegree.framework.xml.XMLTools;
import org.deegree.igeo.ApplicationContainer;
import org.deegree.igeo.config.OnlineResourceType;
import org.deegree.igeo.config.QualifiedNameType;
import org.deegree.igeo.config.WCSDatasourceType;
import org.deegree.igeo.config.ServiceDatasourceType.CapabilitiesURL;
import org.deegree.igeo.dataadapter.DataAccessException;
import org.deegree.igeo.dataadapter.wcs.WCSCapabilitiesEvaluator;
import org.deegree.igeo.i18n.Messages;
import org.deegree.igeo.mapmodel.AuthenticationInformation;
import org.deegree.igeo.mapmodel.Datasource;
import org.deegree.igeo.mapmodel.LayerGroup;
import org.deegree.igeo.mapmodel.MapModel;
import org.deegree.igeo.mapmodel.WCSDatasource;
import org.deegree.igeo.settings.WCSGridCoverageAdapterSettings;
import org.deegree.kernel.AbstractCommand;
import org.deegree.model.Identifier;
import org.deegree.ogcwebservices.wcs.CoverageOfferingBrief;
import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescriptionDocument;
import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilities;
import org.xml.sax.SAXException;
/**
* <code>AddWCSLayerCommand</code> adds a WCS as a new layer to the map model
*
* @author <a href="mailto:buesching@lat-lon.de">Lyn Buesching</a>
* @author last edited by: $Author$
*
* @version $Revision$, $Date$
*
*/
public class AddWCSLayerCommand extends AbstractCommand {
private static final ILogger LOG = LoggerFactory.getLogger( AddWCSLayerCommand.class );
public static final QualifiedName commandName = new QualifiedName( "add layer from WCS command" );
private MapModel mapModel;
private String layerName = UUID.randomUUID().toString();
private String layerTitle = "";
private String layerAbstract = "";
private String nameDS = "";
private double minScaleDenominator = 0;
private double maxScaleDenominator = 9E99;
private URL capabilitiesURL;
private WCSCapabilities wcsCapabilities;
private List<org.deegree.igeo.config.LayerType.MetadataURL> metadataURLs = new ArrayList<org.deegree.igeo.config.LayerType.MetadataURL>();
private org.deegree.igeo.mapmodel.Layer newLayer;
private boolean performed = false;
private CoverageOfferingBrief coverageOffering;
private String crs;
private String format;
private String timestamp;
/**
* @param mapModel
* the mapModel to add the new layer
* @param capabilitiesURL
* the capabilities URL of the WCS to add as a new layer
* @param wcsCapabilities
* @param layerTitle
* the title of the layer
*/
private AddWCSLayerCommand( MapModel mapModel, URL capabilitiesURL, WCSCapabilities wcsCapabilities,
String layerTitle ) {
setMetaInformation( wcsCapabilities );
this.mapModel = mapModel;
this.capabilitiesURL = capabilitiesURL;
this.layerTitle = layerTitle;
}
/**
* @param mapModel
* the mapModel to add the new layer
* @param capabilitiesURL
* the capabilities URL of the WCS to add as a new layer
* @param wcsCapabilities
* the capabilities document of the WCS to add as new layer
* @param coverageOffering
* the selected coverage
* @param format
*/
public AddWCSLayerCommand( MapModel mapModel, URL capabilitiesURL, WCSCapabilities wcsCapabilities,
CoverageOffering coverageOffering, String format, String timestamp ) {
this( mapModel, capabilitiesURL, wcsCapabilities, coverageOffering.getLabel() );
setMetadataURLs( coverageOffering );
this.coverageOffering = coverageOffering;
if ( coverageOffering.getSupportedCRSs().getNativeSRSs() != null
&& coverageOffering.getSupportedCRSs().getNativeSRSs().length > 0 ) {
this.crs = coverageOffering.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0];
} else {
this.crs = coverageOffering.getSupportedCRSs().getRequestResponseSRSs()[0].getCodes()[0];
}
this.format = format;
this.timestamp = timestamp;
}
/**
* @param mapModel
* the mapModel to add the new layer
* @param capabilitiesURL
* the capabilities URL of the WCS to add as a new layer
* @param wcsCapabilities
* the capabilities document of the WCS to add as new layer
* @param coverageOffering
* the selected coverage
*/
public AddWCSLayerCommand( MapModel mapModel, URL capabilitiesURL, WCSCapabilities wcsCapabilities,
CoverageOfferingBrief coverageOffering ) {
this( mapModel, capabilitiesURL, wcsCapabilities, coverageOffering.getLabel() );
setMetadataURLs( coverageOffering );
this.coverageOffering = coverageOffering;
readCRSandFormat();
}
/**
*
* @param mapModel
* @param capabilitiesURL
* @param wcsCaps
* @param layerName
* @param layerTitle
* @param layerAbstract
* @param nameDS
* @param minScale
* @param maxScale
* @param coverageOffering
* @param format
* @param timestamp
*/
public AddWCSLayerCommand( MapModel mapModel, URL capabilitiesURL, WCSCapabilities wcsCaps, String layerName,
String layerTitle, String layerAbstract, String nameDS, double minScale,
double maxScale, CoverageOffering coverageOffering, String format, String timestamp ) {
this( mapModel, capabilitiesURL, wcsCaps, layerTitle );
this.layerName = layerName;
this.layerAbstract = layerAbstract;
this.minScaleDenominator = minScale;
this.maxScaleDenominator = maxScale;
this.nameDS = nameDS;
this.coverageOffering = coverageOffering;
if ( coverageOffering.getSupportedCRSs().getNativeSRSs() != null
&& coverageOffering.getSupportedCRSs().getNativeSRSs().length > 0 ) {
this.crs = coverageOffering.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0];
} else {
this.crs = coverageOffering.getSupportedCRSs().getRequestResponseSRSs()[0].getCodes()[0];
}
this.format = format;
this.timestamp = timestamp;
}
/*
* (non-Javadoc)
*
* @see org.deegree.kernel.Command#execute()
*/
public void execute()
throws Exception {
AuthenticationInformation authenticationInformation = null;
Cache cache = null;
List<Datasource> datasources = new ArrayList<Datasource>( 1 );
// create the wcs datasource
WCSDatasourceType dsType = new WCSDatasourceType();
dsType.setName( nameDS );
QualifiedNameType qnt = new QualifiedNameType();
qnt.setLocalName( coverageOffering.getName() );
dsType.setCoverage( qnt );
dsType.setMinScaleDenominator( minScaleDenominator );
dsType.setMaxScaleDenominator( maxScaleDenominator );
dsType.setEditable( false );
dsType.setQueryable( true );
dsType.setLazyLoading( true );
dsType.setSupportToolTips( false );
dsType.setNativeCRS( crs );
dsType.setFormat( format );
dsType.setTime( timestamp );
CapabilitiesURL cu = new CapabilitiesURL();
OnlineResourceType ort = new OnlineResourceType();
ort.setHref( this.capabilitiesURL.toExternalForm() );
cu.setOnlineResource( ort );
dsType.setCapabilitiesURL( cu );
datasources.add( new WCSDatasource( dsType, authenticationInformation, cache ) );
// avoid double layer name/id
Identifier id = new Identifier( layerName );
int i = 0;
String tmp = layerTitle;
while ( mapModel.exists( id ) ) {
tmp = layerTitle + "_" + i;
id = new Identifier( layerName + "_" + i++ );
}
// create a new layer
newLayer = new org.deegree.igeo.mapmodel.Layer( mapModel, id, tmp, this.layerAbstract, datasources,
this.metadataURLs );
newLayer.setMinScaleDenominator( minScaleDenominator );
newLayer.setMaxScaleDenominator( maxScaleDenominator );
newLayer.setVisible( true );
newLayer.setEditable( false );
// and add the layer to the mapModel
if ( mapModel.getLayerGroups().size() == 0 ) {
LayerGroup layerGroup = new LayerGroup( mapModel, new Identifier(), "LayerGroup", "" );
mapModel.insert( layerGroup, null, null, false );
}
mapModel.insert( newLayer, mapModel.getLayerGroups().get( 0 ), null, false );
performed = true;
fireCommandProcessedEvent();
}
/**
* @return
*/
private void readCRSandFormat() {
CoverageDescriptionDocument doc = new CoverageDescriptionDocument();
String descURL = null;
try {
ApplicationContainer<?> appCont = mapModel.getApplicationContainer();
WCSGridCoverageAdapterSettings wcsSet = appCont.getSettings().getWCSGridCoveragesAdapter();
descURL = readDescribeCoverageURL().toURI().toASCIIString();
String tmp = HttpUtils.normalizeURL( descURL );
descURL = HttpUtils.addAuthenticationForKVP( descURL, appCont.getUser(), appCont.getPassword(),
appCont.getCertificate( tmp ) );
URL url = new URL( descURL );
String req = "VERSION=" + wcsCapabilities.getVersion() + "&SERVICE=WCS&COVERAGE="
+ coverageOffering.getName() + "&request=DescribeCoverage";
InputStream is = HttpUtils.performHttpGet( url.toURI().toASCIIString(), req, wcsSet.getTimeout(),
appCont.getUser(), appCont.getPassword(), null ).getResponseBodyAsStream();
doc.load( is, descURL );
CoverageOffering co = doc.getCoverageOfferings()[0];
if ( co.getSupportedCRSs().getNativeSRSs() != null && co.getSupportedCRSs().getNativeSRSs().length > 0 ) {
crs = co.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0];
} else {
crs = co.getSupportedCRSs().getRequestResponseSRSs()[0].getCodes()[0];
}
format = co.getSupportedFormats().getFormats()[0].getCodes()[0];
} catch ( Exception e ) {
LOG.logError( e.getMessage(), e );
String s = StringTools.stackTraceToString( e );
throw new DataAccessException( Messages.getMessage( Locale.getDefault(), "$DG10113", descURL ) + s );
}
}
private URL readDescribeCoverageURL() {
XMLFragment xml;
String capabilitiesUrl = null;
ApplicationContainer<?> appCont = mapModel.getApplicationContainer();
WCSGridCoverageAdapterSettings wcsSet = appCont.getSettings().getWCSGridCoveragesAdapter();
try {
capabilitiesUrl = this.capabilitiesURL.toURI().toASCIIString();
String tmp = HttpUtils.normalizeURL( capabilitiesUrl );
capabilitiesUrl = HttpUtils.addAuthenticationForKVP( capabilitiesUrl, appCont.getUser(),
appCont.getPassword(), appCont.getCertificate( tmp ) );
InputStream is = HttpUtils.performHttpGet( capabilitiesUrl, null, wcsSet.getTimeout(), appCont.getUser(),
appCont.getPassword(), null ).getResponseBodyAsStream();
xml = new XMLFragment();
xml.load( is, capabilitiesUrl );
} catch ( SAXException e ) {
LOG.logError( e.getMessage(), e );
String s = StringTools.stackTraceToString( e );
throw new DataAccessException( Messages.getMessage( Locale.getDefault(), "$DG10106", capabilitiesUrl ) + s );
} catch ( Exception e ) {
LOG.logError( e.getMessage(), e );
String s = StringTools.stackTraceToString( e );
throw new DataAccessException( Messages.getMessage( Locale.getDefault(), "$$DG10107", capabilitiesUrl ) + s );
}
String version = null;
try {
version = XMLTools.getRequiredAttrValue( "version", null, xml.getRootElement() );
} catch ( XMLParsingException e ) {
LOG.logError( e.getMessage(), e );
LOG.logError( xml.getAsPrettyString() );
throw new DataAccessException( Messages.getMessage( Locale.getDefault(), "$DG10108", capabilitiesUrl,
xml.getAsPrettyString() ) );
}
String className = wcsSet.getCapabilitiesEvaluator( version );
Class<?> clzz = null;
try {
clzz = Class.forName( className );
} catch ( ClassNotFoundException e ) {
LOG.logError( e.getMessage(), e );
throw new DataAccessException( Messages.getMessage( Locale.getDefault(), "$DG10109", className ) );
}
WCSCapabilitiesEvaluator evaluator = null;
try {
evaluator = (WCSCapabilitiesEvaluator) clzz.newInstance();
} catch ( Exception e ) {
LOG.logError( e.getMessage(), e );
throw new DataAccessException( Messages.getMessage( Locale.getDefault(), "$DG10110", className ) );
}
evaluator.setCapabilities( xml );
try {
return evaluator.getDescribeCoverageHTTPGetURL();
} catch ( Exception e ) {
LOG.logError( e.getMessage(), e );
throw new DataAccessException( e.getMessage(), e );
}
}
/*
* (non-Javadoc)
*
* @see org.deegree.kernel.Command#getName()
*/
public QualifiedName getName() {
return commandName;
}
/*
* (non-Javadoc)
*
* @see org.deegree.kernel.Command#getResult()
*/
public Object getResult() {
return null;
}
/*
* (non-Javadoc)
*
* @see org.deegree.kernel.Command#isUndoSupported()
*/
public boolean isUndoSupported() {
return true;
}
/*
* (non-Javadoc)
*
* @see org.deegree.kernel.Command#undo()
*/
public void undo()
throws Exception {
if ( performed ) {
mapModel.remove( newLayer );
performed = false;
}
}
/**
* extract the meta information out of the WCS capabilities document
*
* @param wcsCapabilities
* the capabilities of the WCS
*/
private void setMetaInformation( WCSCapabilities wcsCapabilities ) {
this.wcsCapabilities = wcsCapabilities;
this.nameDS = wcsCapabilities.getService().getLabel();
}
/**
* @param layers
* the layer to extract the metadataURLs
*/
private void setMetadataURLs( CoverageOfferingBrief coverage ) {
layerAbstract = coverage.getDescription();
if ( coverage.getMetadataLink() != null ) {
URL url = coverage.getMetadataLink().getReference();
org.deegree.igeo.config.LayerType.MetadataURL mu = new org.deegree.igeo.config.LayerType.MetadataURL();
OnlineResourceType ort = new OnlineResourceType();
ort.setHref( url.toExternalForm() );
mu.setOnlineResource( ort );
this.metadataURLs.add( mu );
}
}
}