src.gov.nasa.worldwind.layers.BasicLayerFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of worldwindx Show documentation
Show all versions of worldwindx Show documentation
World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.
/*
* Copyright (C) 2012 United States Government as represented by the Administrator of the
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/
package gov.nasa.worldwind.layers;
import gov.nasa.worldwind.*;
import gov.nasa.worldwind.avlist.*;
import gov.nasa.worldwind.exception.*;
import gov.nasa.worldwind.ogc.*;
import gov.nasa.worldwind.ogc.wms.*;
import gov.nasa.worldwind.util.*;
import gov.nasa.worldwind.wms.WMSTiledImageLayer;
import org.w3c.dom.Element;
import java.util.*;
/**
* A factory that creates {@link gov.nasa.worldwind.layers.Layer} instances.
*
* @author dcollins
* @version $Id: BasicLayerFactory.java 1171 2013-02-11 21:45:02Z dcollins $
*/
public class BasicLayerFactory extends BasicFactory
{
/** Creates an instance of BasicLayerFactory; otherwise does nothing. */
public BasicLayerFactory()
{
}
/**
* Creates a layer or layer list from a general configuration source. The source can be one of the following:
* - a {@link java.net.URL}
- a {@link java.io.File}
- a {@link java.io.InputStream}
- {@link
* Element}
- a {@link String} holding a file name, a name of a resource on the classpath, or a string
* represenation of a URL
*
* For tiled image layers, this maps the serviceName
attribute of the Layer/Service
* element of the XML configuration file to the appropriate base tiled image layer type. Service types recognized
* are: - "WMS" for layers that draw their data from a WMS web service.
- "WWTileService" for layers
* that draw their data from a World Wind tile service.
- "Offline" for layers that draw their data only from
* the local cache.
*
* @param configSource the configuration source. See above for supported types.
*
* @return a layer or layer list.
*
* @throws IllegalArgumentException if the configuration file name is null or an empty string.
* @throws WWUnrecognizedException if the layer service type is unrecognized.
* @throws WWRuntimeException if object creation fails. The exception indicating the source of the failure is
* included as the {@link Exception#initCause(Throwable)}.
*/
public Object createFromConfigSource(Object configSource, AVList params)
{
Object layerOrLists = super.createFromConfigSource(configSource, params);
if (layerOrLists == null)
{
String msg = Logging.getMessage("generic.UnrecognizedDocument", configSource);
throw new WWUnrecognizedException(msg);
}
return layerOrLists;
}
@Override
protected Layer doCreateFromCapabilities(OGCCapabilities caps, AVList params)
{
String serviceName = caps.getServiceInformation().getServiceName();
if (serviceName == null || !(serviceName.equalsIgnoreCase(OGCConstants.WMS_SERVICE_NAME)
|| serviceName.contains("WMS")))
{
String message = Logging.getMessage("WMS.NotWMSService", serviceName != null ? serviceName : "null");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (params == null)
params = new AVListImpl();
if (params.getStringValue(AVKey.LAYER_NAMES) == null)
{
// Use the first named layer since no other guidance given
List namedLayers = ((WMSCapabilities) caps).getNamedLayers();
if (namedLayers == null || namedLayers.size() == 0 || namedLayers.get(0) == null)
{
String message = Logging.getMessage("WMS.NoLayersFound");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
params.setValue(AVKey.LAYER_NAMES, namedLayers.get(0).getName());
}
return new WMSTiledImageLayer((WMSCapabilities) caps, params);
}
/**
* Create the objects described in an XML element containing layer and/or layer-list descriptions. Nested layer
* lists and included layers are created recursively.
*
* @param domElement an XML element describing the layers and/or layer lists.
* @param params any properties to apply when creating the included layers.
*
* @return a Layer
, LayerList
or array of LayerList
s, as described by the
* specified description.
*
* @throws Exception if an exception occurs during creation. Exceptions occurring during creation of internal layers
* or layer lists are not re-thrown but are logged. The layer or layer list associated with the
* exception is not contained in the returned object.
*/
@Override
protected Object doCreateFromElement(Element domElement, AVList params) throws Exception
{
Element[] elements = WWXML.getElements(domElement, "//LayerList", null);
if (elements != null && elements.length > 0)
return createLayerLists(elements, params);
elements = WWXML.getElements(domElement, "./Layer", null);
if (elements != null && elements.length > 1)
return createLayerList(elements, params);
if (elements != null && elements.length == 1)
return this.createFromLayerDocument(elements[0], params);
String localName = WWXML.getUnqualifiedName(domElement);
if (localName != null && localName.equals("Layer"))
return this.createFromLayerDocument(domElement, params);
return null;
}
/**
* Create a collection of layer lists and their included layers described by an array of XML layer-list description
* elements.
*
* Any exceptions occurring during creation of the layer lists or their included layers are logged and not
* re-thrown. The layers associated with the exceptions are not included in the returned layer list.
*
* @param elements the XML elements describing the layer lists to create.
* @param params any parameters to apply when creating the included layers.
*
* @return an array containing the specified layer lists.
*/
protected LayerList[] createLayerLists(Element[] elements, AVList params)
{
ArrayList layerLists = new ArrayList();
for (Element element : elements)
{
try
{
String href = WWXML.getText(element, "@href");
if (href != null && href.length() > 0)
{
Object o = this.createFromConfigSource(href, params);
if (o == null)
continue;
if (o instanceof Layer)
{
LayerList ll = new LayerList();
ll.add((Layer) o);
o = ll;
}
if (o instanceof LayerList)
{
LayerList list = (LayerList) o;
if (list != null && list.size() > 0)
layerLists.add(list);
}
else if (o instanceof LayerList[])
{
LayerList[] lists = (LayerList[]) o;
if (lists != null && lists.length > 0)
layerLists.addAll(Arrays.asList(lists));
}
else
{
String msg = Logging.getMessage("LayerFactory.UnexpectedTypeForLayer", o.getClass().getName());
Logging.logger().log(java.util.logging.Level.WARNING, msg);
}
continue;
}
String title = WWXML.getText(element, "@title");
Element[] children = WWXML.getElements(element, "./Layer", null);
if (children != null && children.length > 0)
{
LayerList list = this.createLayerList(children, params);
if (list != null && list.size() > 0)
{
layerLists.add(list);
if (title != null && title.length() > 0)
list.setValue(AVKey.DISPLAY_NAME, title);
}
}
}
catch (Exception e)
{
Logging.logger().log(java.util.logging.Level.WARNING, e.getMessage(), e);
// keep going to create other layers
}
}
return layerLists.toArray(new LayerList[layerLists.size()]);
}
/**
* Create a list of layers described by an array of XML layer description elements.
*
* Any exceptions occurring during creation of the layers are logged and not re-thrown. The layers associated with
* the exceptions are not included in the returned layer list.
*
* @param layerElements the XML elements describing the layers to create.
* @param params any parameters to apply when creating the layers.
*
* @return a layer list containing the specified layers.
*/
protected LayerList createLayerList(Element[] layerElements, AVList params)
{
LayerList layerList = new LayerList();
for (Element element : layerElements)
{
try
{
layerList.add(this.createFromLayerDocument(element, params));
}
catch (Exception e)
{
Logging.logger().log(java.util.logging.Level.WARNING, e.getMessage(), e);
// keep going to create other layers
}
}
return layerList;
}
/**
* Create a layer described by an XML layer description.
*
* @param domElement the XML element describing the layer to create.
* @param params any parameters to apply when creating the layer.
*
* @return a new layer
*
* @throws WWUnrecognizedException if the layer type or service type given in the describing element is
* unrecognized.
* @see #createTiledImageLayer(org.w3c.dom.Element, gov.nasa.worldwind.avlist.AVList).
*/
protected Layer createFromLayerDocument(Element domElement, AVList params)
{
String className = WWXML.getText(domElement, "@className");
if (className != null && className.length() > 0)
{
Layer layer = (Layer) WorldWind.createComponent(className);
String actuate = WWXML.getText(domElement, "@actuate");
layer.setEnabled(WWUtil.isEmpty(actuate) || actuate.equals("onLoad"));
WWXML.invokePropertySetters(layer, domElement);
return layer;
}
AVList props = WWXML.copyProperties(domElement, null);
if (props != null)
{ // Copy params and add any properties for this layer to the copy
if (params != null)
props.setValues(params);
params = props;
}
Layer layer;
String href = WWXML.getText(domElement, "@href");
if (href != null && href.length() > 0)
{
Object o = this.createFromConfigSource(href, params);
if (o == null)
return null;
if (!(o instanceof Layer))
{
String msg = Logging.getMessage("LayerFactory.UnexpectedTypeForLayer", o.getClass().getName());
throw new WWRuntimeException(msg);
}
layer = (Layer) o;
}
else
{
String layerType = WWXML.getText(domElement, "@layerType");
if (layerType != null && layerType.equals("TiledImageLayer"))
{
layer = this.createTiledImageLayer(domElement, params);
}
else
{
String msg = Logging.getMessage("generic.UnrecognizedLayerType", layerType);
throw new WWUnrecognizedException(msg);
}
}
if (layer != null)
{
String actuate = WWXML.getText(domElement, "@actuate");
layer.setEnabled(actuate != null && actuate.equals("onLoad"));
WWXML.invokePropertySetters(layer, domElement);
}
return layer;
}
/**
* Create a {@link TiledImageLayer} layer described by an XML layer description.
*
* @param domElement the XML element describing the layer to create. The element must inculde a service name
* identifying the type of service to use to retrieve layer data. Recognized service types are
* "Offline", "WWTileService" and "OGC:WMS".
* @param params any parameters to apply when creating the layer.
*
* @return a new layer
*
* @throws WWUnrecognizedException if the service type given in the describing element is unrecognized.
*/
protected Layer createTiledImageLayer(Element domElement, AVList params)
{
Layer layer;
String serviceName = WWXML.getText(domElement, "Service/@serviceName");
if ("Offline".equals(serviceName))
{
layer = new BasicTiledImageLayer(domElement, params);
}
else if ("WWTileService".equals(serviceName))
{
layer = new BasicTiledImageLayer(domElement, params);
}
else if (OGCConstants.WMS_SERVICE_NAME.equals(serviceName))
{
layer = new WMSTiledImageLayer(domElement, params);
}
else if (AVKey.SERVICE_NAME_LOCAL_RASTER_SERVER.equals(serviceName))
{
layer = new LocalRasterServerLayer(domElement, params);
}
else
{
String msg = Logging.getMessage("generic.UnrecognizedServiceName", serviceName);
throw new WWUnrecognizedException(msg);
}
//
// String name = layer.getStringValue(AVKey.DISPLAY_NAME);
// System.out.println(name);
String actuate = WWXML.getText(domElement, "@actuate");
layer.setEnabled(actuate != null && actuate.equals("onLoad"));
return layer;
}
}