/* 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.agp.sync;
import com.esri.gpt.agp.client.AgpConnection;
import com.esri.gpt.agp.client.AgpItem;
import com.esri.gpt.agp.client.AgpItemListener;
import com.esri.gpt.agp.client.AgpProperties;
import com.esri.gpt.agp.client.AgpProperty;
import com.esri.gpt.agp.client.AgpSearchCriteria;
import com.esri.gpt.agp.client.AgpSearchRequest;
import java.util.ArrayList;
/**
* Item related helper functions for the AgpPush synchronizer.
*/
public class AgpItemHelper {
/** constructors ============================================================ */
/** Default constructor. */
public AgpItemHelper() {}
/** methods ================================================================= */
/**
* Determines if an item with an exact itemId exists at the destination.
* <br/>Avoid publishing these (these tend to be the start up items
* common to all arcGIS Portal instances.
* @param sourceItem the source item
* @param destination the destination
* @return true if an item with the exact itemId exists at the destination
*/
public boolean doesUnsyncedItemExist(AgpItem sourceItem, AgpDestination destination)
throws Exception {
final AgpItem destItem = new AgpItem();
destItem.setProperties(null);
String sSrcId = sourceItem.getProperties().getValue("id");
String sQuery = "id:"+sSrcId;
AgpSearchRequest request = new AgpSearchRequest();
AgpSearchCriteria criteria = new AgpSearchCriteria();
criteria.setQ(sQuery);
criteria.setNum(1);
request.search(destination.getConnection(),criteria,
new AgpItemListener() {
@Override
public void onItemLoaded(AgpConnection connection, AgpItem item)
throws Exception {
destItem.setProperties(item.getProperties());
}
}
);
if (destItem.getProperties() != null) {
return true;
}
return false;
}
/**
* Determines if a source item originated from synchronization.
* <br/>Avoid propagating synced items from portal to portal.
* @param item the source item
* @return true if the item originated from synchronization
*/
public boolean isSyncedItem(AgpItem item) {
String sTypeKeywords = item.getProperties().getValue("typeKeywords");
if (sTypeKeywords != null) {
String[] aTokens = sTypeKeywords.split(",");
for (String sToken: aTokens) {
sToken = sToken.trim();
if (sToken.length() > 0) {
if (sToken.equalsIgnoreCase("gptsync")) {
return true;
}
}
}
}
return false;
}
/**
* Make the destination item.
* @param source the source
* @param sourceItem the source item
* @return the destination item
*/
protected AgpItem makeDestinationItem(AgpSource source, AgpItem sourceItem) {
AgpItem destItem = new AgpItem();
String[] aIgnoreProps = {
"id",
"item",
"uploaded",
"modified",
"thumbnail",
"thumbnailurl",
"metadata",
"owner",
"access",
"typeKeywords",
};
// TODO: item plus typeKeywords ??
String[] aProps = {
"itemType",
"type",
"url",
"text",
"title",
"description",
"snippet",
"accessInformation",
"licenseInfo",
"culture",
"tags",
"extent",
"spatialReference"
};
AgpProperties sourceProps = sourceItem.getProperties();
AgpProperties destProps = destItem.getProperties();
for (String sProp: aProps) {
AgpProperty sourceProp = sourceProps.get(sProp);
if (sourceProp != null) {
String sValue = sourceProp.getValue();
if (sValue == null) sValue = "";
else sValue = sValue.trim();
if (sValue.length() > 0) {
//System.err.println(sProp+"=push="+sValue);
destProps.add(new AgpProperty(sourceProp.getName(),sValue));
}
}
}
String sTypeKeywords = this.makeDestinationTypeKeywords(source,sourceItem);
destProps.add(new AgpProperty("typeKeywords",sTypeKeywords));
// TODO: item property?
/*
String sSrcItemType = sourceProps.getValue("itemType");
if ((sSrcItemType != null) && (sSrcItemType.equals("url"))) {
String sValue = sourceProps.getValue("item");
if (sValue == null) sValue = "";
else sValue = sValue.trim();
if (sValue.length() > 0) {
//System.err.println(sProp+"=push="+sValue);
destProps.add(new AgpProperty("item",sValue));
}
}
*/
return destItem;
}
/**
* Make the ArcGIS Portal typeKeywords for the destination item.
* @param source the source
* @param sourceItem the source item
* @return the ArcGIS Portal typeKeywords (delimited).
*/
private String makeDestinationTypeKeywords(AgpSource source, AgpItem sourceItem) {
// add the type keywords
// TODO: what about the original typekeywords
StringBuilder sbTypeKeywords = new StringBuilder();
String sModified = sourceItem.getProperties().getValue("modified");
String sSyncKey = this.makeSyncKey(sourceItem);
ArrayList<String> aTypeKeywords = new ArrayList<String>();
String sTypeKeywords = sourceItem.getProperties().getValue("typeKeywords");
if (sTypeKeywords != null) {
String[] aTokens = sTypeKeywords.split(",");
for (String sToken: aTokens) {
sToken = sToken.trim();
if (sToken.length() > 0) {
if (!sToken.startsWith("gptsync")) {
aTypeKeywords.add(sToken);
}
}
}
}
// TODO: need to specify the host?
String sAlphaNumeric = "[^a-zA-Z0-9]+";
String sSrcHost = source.getConnection().getHost().toLowerCase();
sSrcHost = sSrcHost.replace(".","DOT");
sSrcHost = sSrcHost.replaceAll(sAlphaNumeric,"R");
String sFullTag = sSyncKey;
sFullTag += "srcmodified"+sModified;
sFullTag += "srchost"+sSrcHost;
aTypeKeywords.add("gptsync");
aTypeKeywords.add(sSyncKey);
aTypeKeywords.add(sFullTag);
for (String sTypeKeyword: aTypeKeywords) {
if (sbTypeKeywords.length() > 0) sbTypeKeywords.append(",");
sbTypeKeywords.append(sTypeKeyword);
}
return sbTypeKeywords.toString();
}
/**
* Make the synchronization key.
* @param sourceItem the source item
* @return the key
*/
protected String makeSyncKey(AgpItem sourceItem) {
String sSourceID = sourceItem.getProperties().get("id").getValue();
String sSyncKey = "gptsyncsrcid"+sSourceID;
return sSyncKey;
}
/**
* Make the synchronization key.
* @param sourceId the ID of the source item
* @return the key
*/
protected String makeSyncKey(String sourceId) {
return "gptsyncsrcid"+sourceId;
}
/**
* Query for a destination item.
* @param destination the destination
* @param sourceItem the source item
* @return the found item
* @throws Exception if an exception occurs
*/
private AgpItem queryDestinationItem(AgpDestination destination,
AgpItem sourceItem) throws Exception {
final AgpItem destinationItem = new AgpItem();
destinationItem.setProperties(null);
String sSyncKey = this.makeSyncKey(sourceItem);
String sQuery = "typekeywords:"+sSyncKey;
AgpSearchRequest request = new AgpSearchRequest();
AgpSearchCriteria criteria = new AgpSearchCriteria();
criteria.setQ(sQuery);
criteria.setNum(1);
request.search(destination.getConnection(),criteria,
new AgpItemListener() {
@Override
public void onItemLoaded(AgpConnection connection, AgpItem item)
throws Exception {
destinationItem.setProperties(item.getProperties());
//System.err.println("idgggggggggggg="+item.getProperties().get("id").getValue());
}
}
);
if (destinationItem.getProperties() != null) {
//System.err.println("idzzzzzzzzzzz="+destinationItem.getProperties().get("id").getValue());
return destinationItem;
}
return null;
}
/**
* Query for a single item.
* @param connection the connection
* @param query the query string
* @return the found item
* @throws Exception if an exception occurs
*/
protected AgpItem querySingleItem(AgpConnection connection, String query)
throws Exception {
final AgpItem qItem = new AgpItem();
qItem.setProperties(null);
AgpSearchRequest request = new AgpSearchRequest();
AgpSearchCriteria criteria = new AgpSearchCriteria();
criteria.setQ(query);
criteria.setNum(1);
request.search(connection,criteria,
new AgpItemListener() {
@Override
public void onItemLoaded(AgpConnection connection, AgpItem item) throws Exception {
qItem.setProperties(item.getProperties());
}
}
);
if (qItem.getProperties() != null) {
return qItem;
}
return null;
}
/**
* Determine if the destination item requires an update.
* @param sourceItem the synchronization source item
* @param destination the synchronization destination
* @param destItem the synchronization destination item
* @return true if the item should be updated
* @throws Exception if an exception occurs
*/
protected boolean requiresUpdate(AgpItem sourceItem,
AgpDestination destination, AgpItem destItem) throws Exception {
boolean bRequiresUpdate = true;
AgpItem existingDestItem = this.queryDestinationItem(destination,sourceItem);
if (existingDestItem != null) {
String sDestID = existingDestItem.getProperties().getValue("id");
destItem.getProperties().add(new AgpProperty("id",sDestID));
String sTMod = existingDestItem.getProperties().get("modified").getValue();
String sSMod = sourceItem.getProperties().get("modified").getValue();
long nTMod = Long.valueOf(sTMod);
long nSMod = Long.valueOf(sSMod);
long nDiff = nSMod - nTMod;
long nThresh = (1 * 1000);
if (nDiff < nThresh) {
bRequiresUpdate = false;
}
}
return bRequiresUpdate;
}
}