/* 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.publication;
import com.esri.gpt.catalog.arcims.ImsServiceException;
import com.esri.gpt.catalog.context.CatalogIndexException;
import com.esri.gpt.control.webharvest.IterationContext;
import com.esri.gpt.framework.resource.api.Native;
import com.esri.gpt.framework.resource.api.Publishable;
import com.esri.gpt.framework.resource.query.Criteria;
import com.esri.gpt.framework.resource.query.Query;
import com.esri.gpt.framework.util.Val;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Super-class for a processor that interacts with a resource for the express
* purpose of publishing metadata to the catalog.
*/
public abstract class ResourceProcessor {
/** class variables ========================================================= */
/** Logger */
private static final Logger LOGGER = Logger.getLogger(ResourceProcessor.class.getName());
/** instance variables ====================================================== */
private ProcessingContext context;
private String publicationMethod = "upload";
private Map<String,String> sourceURIs;
/** constructors ============================================================ */
/**
* Constructs with a supplied processing context.
* @param context the resource processing context
*/
public ResourceProcessor(ProcessingContext context) {
this.context = context;
}
/** properties ============================================================== */
/**
* Gets the processing context.
* @return the processing context
*/
public ProcessingContext getContext() {
return this.context ;
}
/**
* Gets the publication method.
* @return the publication method
*/
public String getPublicationMethod() {
return this.publicationMethod;
}
/**
* Sets the publication method.
* @param method the publication method
*/
public void setPublicationMethod(String method) {
this.publicationMethod = Val.chkStr(method);
}
/** methods ================================================================= */
/**
* Collects document source URIs associated with a parent resource (SQL LIKE).
* @param pattern the source URI pattern of the parent resource
* @param pattern2 optional secondary source URI pattern of the parent resource
* @throws SQLException if an exception occurs while communicating with the database
*/
protected void collectExistingSourceURIs(String pattern, String pattern2)
throws SQLException {
CatalogDao dao = new CatalogDao(this.getContext().getRequestContext());
this.sourceURIs = dao.querySourceURIs(pattern,pattern2);
}
/**
* Deletes catalog documents that are no longer referenced by the parent resource.
* <br/>Deletion only occurs if at least one URI was processed during this request.
* @throws SQLException if an exception occurs while communicating with the database
* @throws ImsServiceException if an exception occurs during delete
* @throws CatalogIndexException if an exception occurs during delete
* @throws IOException if accessing index fails
*/
protected void deleteUnreferencedSourceURIs()
throws SQLException, ImsServiceException, CatalogIndexException, IOException {
List<ProcessedRecord> records = this.getContext().getProcessedRecords();
if ((this.sourceURIs != null) && (this.sourceURIs.size() > 0) && (records.size() > 0)) {
for (ProcessedRecord record: records) {
this.sourceURIs.remove(record.getSourceUri());
}
if (this.sourceURIs.size() > 0) {
CatalogDao dao = new CatalogDao(this.getContext().getRequestContext());
dao.deleteSourceURIs(this.getContext(),this.sourceURIs);
}
}
}
/**
* Invokes processing against the resource.
* @throws Exception if an exception occurs
*/
public abstract void process() throws Exception;
/**
* Creates iteration query.
* Query is being used during synchronization.
* @param context iteration context
* @param criteria query criteria or <code>null</code> if no criteria
* @return query
*/
public abstract Query createQuery(IterationContext context, Criteria criteria);
/**
* Gets native resource.
* Native resource is a publishable resource created just for repository definition.
* Each native resource is {@link Publishable} and each repository has to be able to
* provide one.
* @param context iteration context
* @return native resource.
*/
public abstract Native getNativeResource(IterationContext context);
/**
* Publishes metadata associated with a resource.
* @param resourceUrl the URL for the resource being published
* @param resourceXml the resource XML
* @throws Exception if an exception occurs
*/
public void publishMetadata(String resourceUrl, String resourceXml)
throws Exception {
this.publishMetadata(resourceUrl,resourceXml,null);
}
/**
* Publishes metadata associated with a resource.
* @param resourceUrl the URL for the resource being published
* @param resourceXml the resource XML
* @param sourceUri a URI identifying the source
* @throws Exception if an exception occurs
*/
public void publishMetadata(String resourceUrl, String resourceXml, String sourceUri)
throws Exception {
ProcessingContext context = getContext();
ProcessedRecord processedRcord = new ProcessedRecord();
if ((sourceUri != null) && (sourceUri.length() > 0)) {
processedRcord.setSourceUri(sourceUri);
} else if ((resourceUrl != null) && (resourceUrl.length() > 0)) {
processedRcord.setSourceUri(resourceUrl);
}
context.getProcessedRecords().add(processedRcord);
// handle validation only requests
if (context.getValidateOnly()) {
try {
ValidationRequest request = new ValidationRequest(
context.getRequestContext(),resourceUrl,resourceXml);
request.verify();
context.incrementNumberValidated();
processedRcord.setStatusType(ProcessedRecord.StatusType.VALIDATED);
} catch (Exception e) {
context.incrementNumberFailed();
context.setLastException(e);
processedRcord.setStatusType(ProcessedRecord.StatusType.FAILED);
processedRcord.setException(e,this.getContext().getMessageBroker());
if (context.getWasSingleSource()) {
throw e;
} else {
// TODO: log this?
LOGGER.log(Level.FINER,"Error\n"+processedRcord.getSourceUri()+"\n"+resourceXml,e);
}
}
// handle publication requests
} else {
try {
PublicationRecord template = context.getTemplate();
UploadRequest request = new UploadRequest(
context.getRequestContext(),context.getPublisher(),resourceUrl,resourceXml);
PublicationRecord publicationRecord = request.getPublicationRecord();
if ((sourceUri != null) && (sourceUri.length() > 0)) {
publicationRecord.setSourceUri(sourceUri);
}
if (template != null) {
publicationRecord.setAutoApprove(template.getAutoApprove());
publicationRecord.setUpdateOnlyIfXmlHasChanged(template.getUpdateOnlyIfXmlHasChanged());
}
if ((this.getPublicationMethod() != null) && (this.getPublicationMethod().length() > 0)) {
publicationRecord.setPublicationMethod(this.getPublicationMethod());
}
request.publish();
context.incrementNumberValidated();
if (request.getPublicationRecord().getWasDocumentUnchanged()) {
context.incrementNumberUnchanged();
processedRcord.setStatusType(ProcessedRecord.StatusType.UNCHNAGED);
} else if (request.getPublicationRecord().getWasDocumentReplaced()) {
context.incrementNumberReplaced();
processedRcord.setStatusType(ProcessedRecord.StatusType.REPLACED);
} else {
context.incrementNumberCreated();
processedRcord.setStatusType(ProcessedRecord.StatusType.CREATED);
}
} catch (Exception e) {
context.incrementNumberFailed();
context.setLastException(e);
processedRcord.setStatusType(ProcessedRecord.StatusType.FAILED);
processedRcord.setException(e,this.getContext().getMessageBroker());
if (context.getWasSingleSource()) {
throw e;
} else {
// TODO: log this?
LOGGER.log(Level.FINER,"Error\n"+processedRcord.getSourceUri()+"\n"+resourceXml,e);
}
}
}
}
}