/*******************************************************************************
* Copyright 2012 Geoscience Australia
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package au.gov.ga.earthsci.catalog.dataset;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import org.w3c.dom.Element;
import au.gov.ga.earthsci.catalog.ICatalogTreeNode;
import au.gov.ga.earthsci.common.util.UTF8URLEncoder;
import au.gov.ga.earthsci.common.util.XmlUtil;
/**
* Helper class that reads legacy dataset.xml structures from a provided source.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
final public class DatasetReader
{
private DatasetReader()
{
}
private static final String NAME_ATTRIBUTE = "@name"; //$NON-NLS-1$
private static final String INFO_ATTRIBUTE = "@info"; //$NON-NLS-1$
private static final String ICON_ATTRIBUTE = "@icon"; //$NON-NLS-1$
private static final String URL_ATTRIBUTE = "@url"; //$NON-NLS-1$
private static final String BASE_ATTRIBUTE = "@base"; //$NON-NLS-1$
private static final String DEFAULT_ATTRIBUTE = "@default"; //$NON-NLS-1$
private static final String ENABLED_ATTRIBUTE = "@enabled"; //$NON-NLS-1$
private static final String DATASET_NODE_NAME = "Dataset"; //$NON-NLS-1$
private static final String LINK_NODE_NAME = "Link"; //$NON-NLS-1$
private static final String LAYER_NODE_NAME = "Layer"; //$NON-NLS-1$
private static final String VALID_NODES_XPATH = DATASET_NODE_NAME + "|" + LINK_NODE_NAME + "|" + LAYER_NODE_NAME; //$NON-NLS-1$//$NON-NLS-2$
private static final String DATASET_LIST_XPATH = "//DatasetList"; //$NON-NLS-1$
/**
* Read a dataset file from the given source and return the root node of the
* dataset tree defined by the provided source.
* <p/>
* Note that {@code link} nodes will not be expanded - they will be returned
* as {@link DatasetLinkCatalogTreeNode}s which can be lazy-expanded.
*
* @param source
* The source to read the dataset structure from. See
* {@link XmlUtil#getElementFromSource(Object)} for supported
* sources.
* @param context
* The context URL to use when resolving relative paths. May be
* <code>null</code>.
*
* @return The root node of the dataset tree structure defined in the given
* source.
*
* @throws MalformedURLException
*/
public static ICatalogTreeNode read(final Object source, final URL context) throws MalformedURLException,
URISyntaxException
{
final Element rootElement = XmlUtil.getElementFromSource(source);
if (rootElement == null)
{
return new DatasetCatalogTreeNode(null, getRootNodeName(source, context), null, null, true, true);
}
// Special case
URL theContext = context;
if (context == null && source instanceof URL)
{
theContext = (URL) source;
}
final ICatalogTreeNode root =
new DatasetCatalogTreeNode(theContext.toURI(), getRootNodeName(source, context), null, null, true, true);
final Element[] elements = XmlUtil.getElements(rootElement, DATASET_LIST_XPATH, null);
if (elements != null)
{
for (Element element : elements)
{
addChildren(element, root, theContext);
}
}
return root;
}
private static String getRootNodeName(Object source, URL context)
{
if (source instanceof File)
{
return ((File) source).getAbsolutePath();
}
if (source instanceof URI)
{
return UTF8URLEncoder.decode(((URI) source).toASCIIString());
}
if (source instanceof URL)
{
return UTF8URLEncoder.decode(((URL) source).toExternalForm());
}
if (context != null)
{
return UTF8URLEncoder.decode(context.toExternalForm());
}
return Messages.DatasetReader_DefaultRootNodeName;
}
private static void addChildren(final Element element, final ICatalogTreeNode parent, final URL context)
throws MalformedURLException, URISyntaxException
{
final Element[] elements = XmlUtil.getElements(element, VALID_NODES_XPATH, null);
if (elements == null)
{
return;
}
for (Element e : elements)
{
if (isDatasetNode(e))
{
final ICatalogTreeNode dataset = addDataset(e, parent, context);
addChildren(e, dataset, context);
}
else if (isLinkNode(e))
{
addLink(e, parent, context);
}
else if (isLayerNode(e))
{
addLayer(e, parent, context);
}
}
}
private static boolean isLayerNode(final Element element)
{
return element.getNodeName().equalsIgnoreCase(LAYER_NODE_NAME);
}
private static boolean isLinkNode(final Element element)
{
return element.getNodeName().equalsIgnoreCase(LINK_NODE_NAME);
}
private static boolean isDatasetNode(final Element element)
{
return element.getNodeName().equalsIgnoreCase(DATASET_NODE_NAME);
}
private static ICatalogTreeNode addDataset(final Element element, final ICatalogTreeNode parent, final URL context)
throws MalformedURLException, URISyntaxException
{
final String name = XmlUtil.getText(element, NAME_ATTRIBUTE);
final URL info = XmlUtil.getURL(element, INFO_ATTRIBUTE, context);
final URL icon = XmlUtil.getURL(element, ICON_ATTRIBUTE, context);
final boolean base = XmlUtil.getBoolean(element, BASE_ATTRIBUTE, false);
URI nodeURI = buildChildURI(parent.getURI(), UTF8URLEncoder.encode(name));
final ICatalogTreeNode dataset = new DatasetCatalogTreeNode(nodeURI, name, info, icon, base);
parent.addChild(dataset);
return dataset;
}
private static void addLink(final Element element, final ICatalogTreeNode parent, final URL context)
throws MalformedURLException, URISyntaxException
{
final String name = XmlUtil.getText(element, NAME_ATTRIBUTE);
final URL info = XmlUtil.getURL(element, INFO_ATTRIBUTE, context);
final URL icon = XmlUtil.getURL(element, ICON_ATTRIBUTE, context);
final URL url = XmlUtil.getURL(element, URL_ATTRIBUTE, context);
final boolean base = XmlUtil.getBoolean(element, BASE_ATTRIBUTE, false);
URI nodeURI = buildChildURI(parent.getURI(), url.toExternalForm());
final ICatalogTreeNode link = new DatasetLinkCatalogTreeNode(nodeURI, name, url, info, icon, base);
parent.addChild(link);
}
private static void addLayer(final Element element, final ICatalogTreeNode parent, final URL context)
throws MalformedURLException, URISyntaxException
{
final String name = XmlUtil.getText(element, NAME_ATTRIBUTE);
final URL info = XmlUtil.getURL(element, INFO_ATTRIBUTE, context);
final URL icon = XmlUtil.getURL(element, ICON_ATTRIBUTE, context);
final URL url = XmlUtil.getURL(element, URL_ATTRIBUTE, context);
final boolean base = XmlUtil.getBoolean(element, BASE_ATTRIBUTE, false);
final boolean def = XmlUtil.getBoolean(element, DEFAULT_ATTRIBUTE, false);
final boolean enabled = XmlUtil.getBoolean(element, ENABLED_ATTRIBUTE, true);
URI nodeURI = buildChildURI(parent.getURI(), url.toExternalForm());
final DatasetLayerCatalogTreeNode layer =
new DatasetLayerCatalogTreeNode(nodeURI, name, url, info, icon, base, def, enabled);
parent.addChild(layer);
}
private static URI buildChildURI(URI parentURI, String childPath) throws URISyntaxException
{
return new URI(parentURI.toASCIIString() + "/" + childPath); //$NON-NLS-1$
}
}