/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You 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 com.esri.gpt.catalog.arcgis.metadata;
import com.esri.arcgisws.DEBrowseOptions;
import com.esri.arcgisws.DataElement;
import com.esri.arcgisws.GeoDataServerBindingStub ;
import com.esri.arcgisws.XmlPropertySet;
import com.esri.gpt.framework.collection.StringAttributeMap;
import com.esri.gpt.framework.context.ApplicationConfiguration;
import com.esri.gpt.framework.context.ApplicationContext;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.resource.api.Publishable;
import com.esri.gpt.framework.resource.api.Resource;
import com.esri.gpt.framework.resource.api.SourceUri;
import com.esri.gpt.framework.resource.common.UrlUri;
import com.esri.gpt.framework.util.Val;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Handles the collection of metadata for an ArcGIS geodatabase service (GeoDataServer).
*/
public class GeoDataServerHandler extends ServiceHandler {
/** class variables ========================================================= */
/** Logger */
private static final Logger LOGGER = Logger.getLogger(GeoDataServerHandler.class.getName());
/** constructors ============================================================ */
/** Default constructor. */
public GeoDataServerHandler() {
super();
}
/** methods ================================================================= */
/**
* Collect metadata associated with a service.
* @param handlerFactory handler factory
* @param serviceInfo the active service information
* @throws Exception if an exception occurs
*/
@Override
public void collectMetadata(ServiceHandlerFactory handlerFactory, ServiceInfo serviceInfo)
throws Exception {
serviceInfo.getKeywords().add(serviceInfo.getType());
serviceInfo.addKeywords("geographicService,service",",");
}
/**
* Publishes metadata associated with a service.
* <br/>A record is published for the GeoDataServer itself.
* <br/>Any data element containing an XML will also be published,
* the SORCEURI for the element will be: [geodataserver-rest-endpoint]/element.name
* @param processor the ArcGIS Server service processor
* @param serviceInfo the active service information
* @throws Exception if an exception occurs
*/
@Override
public void publishMetadata(AGSProcessor processor, ServiceInfo serviceInfo)
throws Exception {
// publish the service
String resourceUrl = serviceInfo.getResourceUrl();
String resourceXml = serviceInfo.asDublinCore(processor);
processor.publishMetadata(resourceUrl,resourceXml);
// configuration parameters for data element recursion
RequestContext rContext = processor.getContext().getRequestContext();
StringAttributeMap params = rContext.getCatalogConfiguration().getParameters();
boolean recurse = true;
if (Val.chkStr(params.getValue("AGSProcessor.GeoDataServer.recurse")).equalsIgnoreCase("false")) {
recurse = false;
}
boolean expandDescendants = false;
if (Val.chkStr(params.getValue("AGSProcessor.GeoDataServer.expandDescendants")).equalsIgnoreCase("true")) {
expandDescendants= true;
}
int maxDataElements = Val.chkInt(params.getValue("AGSProcessor.GeoDataServer.maxDataElements"),200);
if (maxDataElements == 0) {
recurse = false;
}
if (recurse) {
// publish each data element within the geodatabase that has metadata
GeoDataServerBindingStub stub =
getCredentials()==null || getCredentials().getUsername().length()==0 || getCredentials().getPassword().length()==0?
new GeoDataServerBindingStub(serviceInfo.getSoapUrl()):
new GeoDataServerBindingStub(serviceInfo.getSoapUrl(), getCredentials().getUsername(), getCredentials().getPassword());
DEBrowseOptions options = new DEBrowseOptions();
if (expandDescendants) {
options.setExpandType(com.esri.arcgisws.EsriDEExpandType.esriDEExpandDescendants);
} else {
options.setExpandType(com.esri.arcgisws.EsriDEExpandType.esriDEExpandChildren);
}
options.setRetrieveFullProperties(false);
options.setRetrieveMetadata(false);
// retrieve data elements
DataElement[] elements = null;
try {
if (maxDataElements < 0) {
options.setRetrieveMetadata(true);
elements = stub.getDataElements(options);
} else {
// test first without retrieving actual metadata to avoid out of memory issues,
// if under the threshould element count then go back and get the metadata
DataElement[] test = stub.getDataElements(options);
if ((test != null) && (test.length > 0) && (test.length <= maxDataElements)) {
options.setRetrieveMetadata(true);
elements = stub.getDataElements(options);
}
}
} catch (Exception e) {
LOGGER.log(Level.WARNING,"Error while processing: "+serviceInfo.getSoapUrl(),e);
return;
}
// publish metadata per data element
if (elements != null) {
for (DataElement element: elements) {
if (Thread.currentThread().isInterrupted()) return;
XmlPropertySet xmlProps = element.getMetadata();
if (xmlProps != null) {
String xml = Val.chkStr(xmlProps.getXmlDoc());
if ((xml != null) && (xml.length() > 0)) {
String sourceUri = serviceInfo.getRestUrl()+"/"+element.getName();
LOGGER.finer("Publishing metadata for: "+sourceUri);
processor.publishMetadata(null,xml,sourceUri);
}
}
}
}
}
}
@Override
public void appendRecord(Collection<Resource> records, ServiceHandlerFactory factory, ServiceInfo serviceInfo, boolean isNative) throws Exception {
super.appendRecord(records, factory, serviceInfo, isNative);
// configuration parameters for data element recursion
ApplicationContext appCtx = ApplicationContext.getInstance();
ApplicationConfiguration cfg = appCtx.getConfiguration();
StringAttributeMap params = cfg.getCatalogConfiguration().getParameters();
boolean recurse = true;
if (Val.chkStr(params.getValue("AGSProcessor.GeoDataServer.recurse")).equalsIgnoreCase("false")) {
recurse = false;
}
boolean expandDescendants = false;
if (Val.chkStr(params.getValue("AGSProcessor.GeoDataServer.expandDescendants")).equalsIgnoreCase("true")) {
expandDescendants= true;
}
int maxDataElements = Val.chkInt(params.getValue("AGSProcessor.GeoDataServer.maxDataElements"),200);
if (maxDataElements == 0) {
recurse = false;
}
if (recurse) {
// publish each data element within the geodatabase that has metadata
GeoDataServerBindingStub stub =
getCredentials()==null || getCredentials().getUsername().length()==0 || getCredentials().getPassword().length()==0?
new GeoDataServerBindingStub(serviceInfo.getSoapUrl()):
new GeoDataServerBindingStub(serviceInfo.getSoapUrl(), getCredentials().getUsername(), getCredentials().getPassword());
DEBrowseOptions options = new DEBrowseOptions();
if (expandDescendants) {
options.setExpandType(com.esri.arcgisws.EsriDEExpandType.esriDEExpandDescendants);
} else {
options.setExpandType(com.esri.arcgisws.EsriDEExpandType.esriDEExpandChildren);
}
options.setRetrieveFullProperties(false);
options.setRetrieveMetadata(false);
// retrieve data elements
DataElement[] elements = null;
try {
if (maxDataElements < 0) {
options.setRetrieveMetadata(true);
elements = stub.getDataElements(options);
} else {
// test first without retrieving actual metadata to avoid out of memory issues,
// if under the threshould element count then go back and get the metadata
DataElement[] test = stub.getDataElements(options);
if ((test != null) && (test.length > 0) && (test.length <= maxDataElements)) {
options.setRetrieveMetadata(true);
elements = stub.getDataElements(options);
}
}
} catch (Exception e) {
LOGGER.log(Level.WARNING,"Error while processing: "+serviceInfo.getSoapUrl(),e);
return;
}
// publish metadata per data element
if (elements != null) {
for (DataElement element: elements) {
addElement(records, serviceInfo, element);
}
}
}
}
/**
* Adds a single element.
* @param records records to add element
* @param serviceInfo service info
* @param element element to add
*/
private void addElement(Collection<Resource> records, ServiceInfo serviceInfo, DataElement element) {
records.add(new DataElementRecord(serviceInfo, element));
DataElement [] children = element.getChildren();
if (children!=null) {
for (DataElement child: children) {
addElement(records, serviceInfo, child);
}
}
}
/**
* Data element specific Record implementation.
*/
private class DataElementRecord extends ServiceInfoProvider implements Publishable {
private DataElement element;
public DataElementRecord(ServiceInfo info, DataElement element) {
super(info);
this.element = element;
}
@Override
public SourceUri getSourceUri() {
return new UrlUri(getServiceInfo().getRestUrl()+"/"+element.getName());
}
@Override
public String getContent() throws IOException {
XmlPropertySet xmlProps = element.getMetadata();
return xmlProps!=null? Val.chkStr(xmlProps.getXmlDoc()): "";
}
@Override
public Iterable<Resource> getNodes() {
return new ArrayList<Resource>();
}
@Override
public Date getUpdateDate() {
return null;
}
}
}