/**
 * 
 */
package IndexManagement;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.util.LinkedList;
import java.util.List;

import org.apache.axis.message.addressing.Address;
import org.apache.axis.message.addressing.EndpointReferenceType;
import org.gcube.common.core.contexts.GCUBERemotePortTypeContext;
import org.gcube.common.core.contexts.GHNContext;
import org.gcube.common.core.informationsystem.client.AtomicCondition;
import org.gcube.common.core.informationsystem.client.ISClient;
import org.gcube.common.core.informationsystem.client.RPDocument;
import org.gcube.common.core.informationsystem.client.queries.WSResourceQuery;
import org.gcube.common.core.scope.GCUBEScope;
import org.gcube.common.core.security.GCUBESecurityManager;
import org.gcube.common.core.security.GCUBESecurityManagerImpl;
import org.gcube.indexmanagement.geoindexlookup.stubs.GeoIndexLookupFactoryPortType;
import org.gcube.indexmanagement.geoindexlookup.stubs.GeoIndexLookupPortType;
import org.gcube.indexmanagement.geoindexlookup.stubs.InclusionType;
import org.gcube.indexmanagement.geoindexlookup.stubs.Point;
import org.gcube.indexmanagement.geoindexlookup.stubs.RankingRequest;
import org.gcube.indexmanagement.geoindexlookup.stubs.RefinementRequest;
import org.gcube.indexmanagement.geoindexlookup.stubs.SearchPolygon;
import org.gcube.indexmanagement.geoindexlookup.stubs.service.GeoIndexLookupFactoryServiceAddressingLocator;
import org.gcube.indexmanagement.geoindexlookup.stubs.service.GeoIndexLookupServiceAddressingLocator;
import org.gcube.indexmanagement.geoindexmanagement.stubs.GeoIndexManagementFactoryPortType;
import org.gcube.indexmanagement.geoindexmanagement.stubs.GeoIndexManagementPortType;
import org.gcube.indexmanagement.geoindexmanagement.stubs.service.GeoIndexManagementFactoryServiceAddressingLocator;
import org.gcube.indexmanagement.geoindexmanagement.stubs.service.GeoIndexManagementServiceAddressingLocator;
import org.gcube.indexmanagement.geoindexupdater.stubs.GeoIndexUpdaterFactoryPortType;
import org.gcube.indexmanagement.geoindexupdater.stubs.GeoIndexUpdaterPortType;
import org.gcube.indexmanagement.geoindexupdater.stubs.Process;
import org.gcube.indexmanagement.geoindexupdater.stubs.service.GeoIndexUpdaterFactoryServiceAddressingLocator;
import org.gcube.indexmanagement.geoindexupdater.stubs.service.GeoIndexUpdaterServiceAddressingLocator;
import org.gridforum.jgss.ExtendedGSSCredential;
import org.gridforum.jgss.ExtendedGSSManager;
import org.ietf.jgss.GSSCredential;
import org.oasis.wsrf.lifetime.Destroy;

import IndexManagement.VOInfoManager.CollectionInfo;
import IndexManagement.VOInfoManager.MetadataCollectionInfo;


/**
 * Client used to create, feed and look up forward indexes.
 * 
 * Syntax: 
 * 1) GeoIndexClient [ -cred <credentialFile> ] <scope> -create "manager" | "lookup" | "all" <colName> <colSchema> <colLang> <indexTypeID> [ <geographicalSystem> <unitOfMeasurement> <numberOfDecimals> ]
 * 2) GeoIndexClient [ -cred <credentialFile> ] <scope> -destroy "manager" | "lookup" | "all" <colName> <colSchema> <colLang>
 * 3) GeoIndexClient [ -cred <credentialFile> ] <scope> -feed <colName> <colSchema> <colLang> <rowset_RS_EPR_file>
 * 4) GeoIndexClient [ -cred <credentialFile> ] <scope> -lookup <colName> <colSchema> <colLang> <x1,y1> <x2,y2> <x3,y3> [ .... <xn,yn> ]
 * 
 * @author Spyros Boutsis, NKUA
 */

public class GeoIndexClient {
	
	private enum operationMode { CREATE, FEED, LOOKUP, DESTROY };
	
	String lookupFactoryURI; 
    String updaterFactoryURI; 
    String managementFactoryURI;
    
    private List<EndpointReferenceType> getWSResourceEPRsFromPropValues(List<String[]> properties, GCUBEScope scope) throws Exception {
		String filter = "$result/child::*[local-name()='"+properties.get(0)[0].trim()+"']/string() eq '"+properties.get(0)[1].trim()+"'";
		for (int i=1; i<properties.size(); i++)
			filter += " and $result/child::*[local-name()='"+properties.get(i)[0].trim()+"']/string() eq '"+properties.get(i)[1].trim()+"'";
		
		ISClient client = GHNContext.getImplementation(ISClient.class);
		WSResourceQuery gquery = client.getQuery(WSResourceQuery.class);
		gquery.addGenericCondition(filter);

		List<EndpointReferenceType> ret = new LinkedList<EndpointReferenceType>();
		for(RPDocument d : client.execute(gquery, scope)){
			ret.add(d.getEndpoint());
		}
		return ret;
	}
    
    private List<String> getPropertyValueFromWSResourceEPR(EndpointReferenceType epr, String propName, GCUBEScope scope) throws Exception {    	
		ISClient client = GHNContext.getImplementation(ISClient.class);
		WSResourceQuery gquery = client.getQuery(WSResourceQuery.class);
		gquery.addAtomicConditions(
				new AtomicCondition("/../Source", epr.getAddress().toString()),
				new AtomicCondition("/../SourceKey", epr.getProperties().get_any()[0].getValue())
			);		
		for(RPDocument d : client.execute(gquery, scope)){
			return d.evaluate("//" + propName + "/text()");
		}
		return null;
	}
    
	private GeoIndexManagementFactoryPortType createGeoIndexManagementFactory(GCUBEScope scope, GCUBESecurityManager secManager) {
        try {
            // Get factory portType
        	GeoIndexManagementFactoryServiceAddressingLocator geoIndexManagementFactoryLocator = new GeoIndexManagementFactoryServiceAddressingLocator();
        	EndpointReferenceType geoIndexManagementFactoryEPR = new EndpointReferenceType();
        	geoIndexManagementFactoryEPR.setAddress(new Address(managementFactoryURI));
        	GeoIndexManagementFactoryPortType geoIndexManagementFactoryPortType = geoIndexManagementFactoryLocator.getGeoIndexManagementFactoryPortTypePort(geoIndexManagementFactoryEPR);
        	geoIndexManagementFactoryPortType = GCUBERemotePortTypeContext.getProxy(geoIndexManagementFactoryPortType, scope, secManager);
            return geoIndexManagementFactoryPortType;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
        return null;
    }
	
	private String createGeoIndexManagementResource(String collectionID, String indexTypeID, String geoSystem, String unitOfMeasurement, int numOfDecimals, GeoIndexManagementFactoryPortType geoIndexManagementFactoryPortType) {
		try {
			// Create geoIndex resource and get endpoint reference of WS-Resource.
			org.gcube.indexmanagement.geoindexmanagement.stubs.CreateResource geoIndexManagementCreateResource = new org.gcube.indexmanagement.geoindexmanagement.stubs.CreateResource();
			geoIndexManagementCreateResource.setCollectionID(new String[] { collectionID });
			geoIndexManagementCreateResource.setIndexTypeID(indexTypeID);
			geoIndexManagementCreateResource.setGeographicalSystem(geoSystem);
			geoIndexManagementCreateResource.setIndexID(null);
			geoIndexManagementCreateResource.setUnitOfMeasurement(unitOfMeasurement);
			geoIndexManagementCreateResource.setNumberOfDecimals(numOfDecimals);

			org.gcube.indexmanagement.geoindexmanagement.stubs.CreateResourceResponse geoIndexManagementCreateResourceResponse = geoIndexManagementFactoryPortType.createResource(geoIndexManagementCreateResource);
			return geoIndexManagementCreateResourceResponse.getIndexID();
		}
		catch (Exception ex) {
			ex.printStackTrace();
			System.exit(0);
		}
		return null;
	}

	private GeoIndexLookupFactoryPortType createGeoIndexLookupFactory(GCUBEScope scope, GCUBESecurityManager secManager) {
        try {
            // Get factory portType
        	GeoIndexLookupFactoryServiceAddressingLocator geoIndexLookupFactoryLocator = new GeoIndexLookupFactoryServiceAddressingLocator();
        	EndpointReferenceType geoIndexLookupFactoryEPR = new EndpointReferenceType();
            geoIndexLookupFactoryEPR.setAddress(new Address(lookupFactoryURI));
            GeoIndexLookupFactoryPortType geoIndexLookupFactoryPortType = geoIndexLookupFactoryLocator.getGeoIndexLookupFactoryPortTypePort(geoIndexLookupFactoryEPR);
            geoIndexLookupFactoryPortType = GCUBERemotePortTypeContext.getProxy(geoIndexLookupFactoryPortType, scope, secManager);
            return geoIndexLookupFactoryPortType;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
        return null;
    }
	
	private void createGeoIndexLookupResource(String mainIndexID, GeoIndexLookupFactoryPortType geoIndexLookupFactoryPortType) throws RemoteException {
    	// Create forwardIndex resource and get endpoint reference of WS-Resource.
    	org.gcube.indexmanagement.geoindexlookup.stubs.CreateResource geoIndexLookupCreateResource =
    		new org.gcube.indexmanagement.geoindexlookup.stubs.CreateResource();

    	geoIndexLookupCreateResource.setMainIndexID(mainIndexID);
    	geoIndexLookupFactoryPortType.createResource(geoIndexLookupCreateResource);
    }

	private GeoIndexLookupPortType findGeoIndexLookupResource(String collectionID, GCUBEScope scope, GCUBESecurityManager secManager) {
		List<EndpointReferenceType> eprs = null;
		try {
			List<String[]> props = new LinkedList<String[]>();
			props.add(new String[] { "ServiceClass", "Index" });
			props.add(new String[] { "ServiceName", "GeoIndexLookup" });
			props.add(new String[] { "CollectionID", collectionID });
			eprs = getWSResourceEPRsFromPropValues(props, scope);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(-1);
		}
		
		if (eprs.size() != 1) {
			System.out.println("Error: Found " + eprs.size() + " lookup resources for the given collection ID.");
			System.exit(0);
		}
		EndpointReferenceType epr = eprs.get(0);

		GeoIndexLookupServiceAddressingLocator instanceLocator = new GeoIndexLookupServiceAddressingLocator();
		GeoIndexLookupPortType port = null;
		try {
			port = instanceLocator.getGeoIndexLookupPortTypePort(epr);
			port = GCUBERemotePortTypeContext.getProxy(port, scope, secManager);
			return port;
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}
		return null;
	}

	private GeoIndexManagementPortType findGeoIndexManagementResource(String collectionID, GCUBEScope scope, GCUBESecurityManager secManager) {		
		List<EndpointReferenceType> eprs = null;
		
		try {
			List<String[]> props = new LinkedList<String[]>();
			props.add(new String[] { "ServiceClass", "Index" });
			props.add(new String[] { "ServiceName", "GeoIndexManagement" });
			props.add(new String[] { "CollectionID", collectionID });
			eprs = getWSResourceEPRsFromPropValues(props, scope);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(-1);
		}
		
		if (eprs.size() != 1) {
			System.out.println("Error: Found " + eprs.size() + " management resources for the given collection ID.");
			System.exit(0);
		}
		EndpointReferenceType epr = eprs.get(0);

		GeoIndexManagementServiceAddressingLocator instanceLocator = new GeoIndexManagementServiceAddressingLocator();
		GeoIndexManagementPortType port = null;
		try {
			port = instanceLocator.getGeoIndexManagementPortTypePort(epr);
			port = GCUBERemotePortTypeContext.getProxy(port, scope, secManager);
			return port;
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}
		return null;
	}
	
	private String doLookup(GeoIndexLookupPortType lookup, List<Point> polygonPoints) throws Exception {
		SearchPolygon search = new SearchPolygon();
		Point[] pointsArray = new Point[polygonPoints.size()];
		pointsArray = polygonPoints.toArray(pointsArray);
		search.setVertices(pointsArray);
		RefinementRequest refinement = new RefinementRequest(new String[]{}, "PolygonalRefiner");
		search.setRefinementList(new RefinementRequest[]{refinement});
		RankingRequest ranker = new RankingRequest();
		ranker.setRankerID("GenericRanker");
		search.setRanker(ranker);
		search.setInclusion(InclusionType.contains);

		String epr = lookup.search(search);
		return epr;
	}

	private GeoIndexUpdaterFactoryPortType createGeoIndexUpdaterFactory(GCUBEScope scope, GCUBESecurityManager secManager) {
        try {
            // Get factory portType
        	GeoIndexUpdaterFactoryServiceAddressingLocator geoIndexUpdaterFactoryLocator = new GeoIndexUpdaterFactoryServiceAddressingLocator();
        	EndpointReferenceType geoIndexUpdaterFactoryEPR = new EndpointReferenceType();
            geoIndexUpdaterFactoryEPR.setAddress(new Address(updaterFactoryURI));
            GeoIndexUpdaterFactoryPortType geoIndexUpdaterFactoryPortType = geoIndexUpdaterFactoryLocator.getGeoIndexUpdaterFactoryPortTypePort(geoIndexUpdaterFactoryEPR);
            geoIndexUpdaterFactoryPortType = GCUBERemotePortTypeContext.getProxy(geoIndexUpdaterFactoryPortType, scope, secManager);
            return geoIndexUpdaterFactoryPortType;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
        return null;
    }

	private String findGeoIndexID(String collectionID, GCUBEScope scope, GCUBESecurityManager secManager) {
		List<EndpointReferenceType> eprs = null;
		try {
			List<String[]> props = new LinkedList<String[]>();
			props.add(new String[] { "ServiceClass", "Index" });
			props.add(new String[] { "ServiceName", "GeoIndexManagement" });
			props.add(new String[] { "CollectionID", collectionID });
			eprs = getWSResourceEPRsFromPropValues(props, scope);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(-1);
		}
		
		if (eprs.size() != 1) {
			System.out.println("Error: Found " + eprs.size() + " management resources for the given collection ID.");
			System.exit(0);
		}
		EndpointReferenceType epr = eprs.get(0);

		try {
			return getPropertyValueFromWSResourceEPR(epr, "IndexID", scope).get(0);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}
		return null;
	}

	private GeoIndexUpdaterPortType createGeoIndexUpdaterResource(String mainIndexID, GeoIndexUpdaterFactoryPortType geoIndexUpdaterFactoryPortType, GCUBEScope scope, GCUBESecurityManager secManager) {
		try {
			// Create geoIndexUpdater resource and get endpoint reference of WS-Resource.
            org.gcube.indexmanagement.geoindexupdater.stubs.CreateResource geoIndexUpdaterCreateResource =
                new org.gcube.indexmanagement.geoindexupdater.stubs.CreateResource();       
            geoIndexUpdaterCreateResource.setMainIndexID(mainIndexID);

            org.gcube.indexmanagement.geoindexupdater.stubs.CreateResourceResponse geoIndexUpdaterCreateResourceResponse = 
                geoIndexUpdaterFactoryPortType.createResource(geoIndexUpdaterCreateResource);
            EndpointReferenceType geoIndexUpdaterInstanceEPR = geoIndexUpdaterCreateResourceResponse.getEndpointReference();
            
            // Port type
            GeoIndexUpdaterServiceAddressingLocator geoIndexupdaterServiceAddressingLocator = new GeoIndexUpdaterServiceAddressingLocator();
            GeoIndexUpdaterPortType geoIndexUpdaterPortTypePort = geoIndexupdaterServiceAddressingLocator.getGeoIndexUpdaterPortTypePort(geoIndexUpdaterInstanceEPR);
            geoIndexUpdaterPortTypePort = GCUBERemotePortTypeContext.getProxy(geoIndexUpdaterPortTypePort, scope, secManager);
            return geoIndexUpdaterPortTypePort;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
        return null;
    }
	
	private void updateIndexWithRowsetResultSet(GeoIndexUpdaterPortType updater, String RS_EPR) {
		try {
			updater.process(new Process(true, RS_EPR)); 
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}
	}
    
	/**
	 * Helper method to get a GSSCredential object from a given file
	 * @param filename file containing the (VOMS) credentials
	 * @return the corresponding GSSCredential object
	 * @throws Exception on error
	 */
	private static GSSCredential getCredFromFile(String filename) throws Exception {
		GSSCredential retcred = null;
 
		try {
			File inFile = new File(filename);
			byte [] data = new byte[(int)inFile.length()];
			FileInputStream inStream = new FileInputStream(inFile);
			inStream.read(data);
			inStream.close();
			ExtendedGSSManager manager = (ExtendedGSSManager)ExtendedGSSManager.getInstance();
			retcred = manager.createCredential(data,ExtendedGSSCredential.IMPEXP_OPAQUE,GSSCredential.DEFAULT_LIFETIME,null/*use default mechanism - GSI*/,GSSCredential.INITIATE_AND_ACCEPT);
		} catch (Exception e) {
			throw e;
		}
		return retcred;
	}
	
	/**
	 * Reads the contents of a text file.
	 * 
	 * @param filename The name of the file to read
	 * @return the contents of the file as a string
	 * @throws IOException
	 */
	private static String readTextFile(String filename) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename), "UTF-8"));
		StringBuffer buf = new StringBuffer();
		String tmp;
		while ((tmp = br.readLine()) != null) {
			if (!tmp.startsWith("<?xml"))
				buf.append(tmp + "\n");
		}
		br.close();
		return buf.toString();
	}
	
	public void run(String[] args) {
		ExtendedGSSCredential cred = null;
		String collectionID = null;
		String collectionName = null;
		String collectionSchema = null;
		String collectionLang = null;
		String indexTypeID = null;
		String RS_EPR_file = null;
		String geoSystem = null;
		String unit = null;
		int numOfDecimals = 0;
		int baseArg = -1;
		List<Point> points = new LinkedList<Point>();
		operationMode mode = operationMode.CREATE;
		GCUBESecurityManagerImpl secManager = null;
		boolean bHandleManager = false;
		boolean bHandleLookup = false;
		
		/* Check if we should act in a secure way and load the credential if yes */
		if (args[0].equals("-cred")) {
			try {
				cred = (ExtendedGSSCredential) getCredFromFile(args[1]);
			} catch (Exception e) {
				e.printStackTrace();
				System.exit(0);
			}
			baseArg = 1;
			
			try {
				secManager = new GCUBESecurityManagerImpl() {  public boolean isSecurityEnabled() {return true;}};
				secManager.useCredentials(cred);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		else {
			secManager = new GCUBESecurityManagerImpl() {  public boolean isSecurityEnabled() {return false;}};
		}
		
		/* Get the scope */
		GCUBEScope scope = GCUBEScope.getScope(args[baseArg+1]);
		baseArg++;
		
		/* Check syntax */
		if (args[baseArg+1].equalsIgnoreCase("-create")) {
			if (args[baseArg+2].equals("manager"))
				bHandleManager = true;
			else if (args[baseArg+2].equals("lookup"))
				bHandleLookup = true;
			else {
				bHandleManager = true;
				bHandleLookup = true;
			}
			collectionName = args[baseArg+3];
			collectionSchema = args[baseArg+4];
			collectionLang = args[baseArg+5];
			indexTypeID = args[baseArg+6];
			if (args.length > (baseArg+7)) {
				geoSystem = args[baseArg + 8];
				unit = args[baseArg+9];
				numOfDecimals = Integer.parseInt(args[baseArg+10]);
			}
			else {
				geoSystem = "WGS_1984";
				unit = "DD";
				numOfDecimals = 4;
			}
			mode = operationMode.CREATE;
		}
		else if (args[1].equalsIgnoreCase("-feed")) {
			collectionName = args[baseArg+2];
			collectionSchema = args[baseArg+3];
			collectionLang = args[baseArg+4];
			RS_EPR_file = args[baseArg+5];
			mode = operationMode.FEED;
		}
		else if (args[baseArg+1].equalsIgnoreCase("-lookup")) {
			collectionName = args[baseArg+2];
			collectionSchema = args[baseArg+3];
			collectionLang = args[baseArg+4];
			for (int i=baseArg+5; i<args.length; i++) {
				String[] xy = args[i].split(",");
				points.add(new Point(Integer.parseInt(xy[0]), Integer.parseInt(xy[1])));
			}
			mode = operationMode.LOOKUP;
		}
		else if (args[1].equalsIgnoreCase("-destroy")) {
			if (args[baseArg+2].equals("manager"))
				bHandleManager = true;
			else if (args[baseArg+2].equals("lookup"))
				bHandleLookup = true;
			else {
				bHandleManager = true;
				bHandleLookup = true;
			}
			collectionName = args[baseArg+3];
			collectionSchema = args[baseArg+4];
			collectionLang = args[baseArg+5];
			mode = operationMode.DESTROY;
		}
		else {
			System.out.println("Invalid parameter: " + args[1]);
			System.exit(0);
		}
		
		
		
		/* Get the metadata collection ID from the collection name */
		try {
			String VOFileName = args[baseArg].replace("/", "_") + ".properties";
			VOInfoManager VOManager = new VOInfoManager(VOFileName);
			CollectionInfo colInfo = VOManager.findCollectionByName(collectionName);
			if (colInfo == null) {
				System.out.println("Collection not found in VO properties, proceeding in 'fake collection' mode...");
				collectionID = collectionName;
			}
			else {
				MetadataCollectionInfo mcInfo = colInfo.findMetadataCollection(collectionSchema, collectionLang);
				if (mcInfo == null) {
					System.out.println("Metadata Collection not found in VO properties.");
					System.exit(-1);
				}
				collectionID = mcInfo.getID();
			}

			managementFactoryURI = VOManager.getGeoIndexManagementFactoryURI();
			lookupFactoryURI = VOManager.getGeoIndexLookupFactoryURI();
			updaterFactoryURI = VOManager.getGeoIndexUpdaterFactoryURI();
		} catch (Exception e) {
			System.out.println("Failed to parse VO properties file: " + e);
		}
		
		
		
		if (mode == operationMode.CREATE) {
			String indexID = null;
			
			if (bHandleManager) {
				/* Create the index management resource */
				GeoIndexManagementFactoryPortType managementPortType = createGeoIndexManagementFactory(scope, secManager);
				indexID = createGeoIndexManagementResource(collectionID, indexTypeID, geoSystem, unit, numOfDecimals, managementPortType);
				System.out.println("Management resource created successfully, indexID is: " + indexID);
			}
			
			if (bHandleLookup) {
				if (indexID == null)
					indexID = findGeoIndexID(collectionID, scope, secManager);
				
				/* Get the forward index lookup factory service porttype */
				GeoIndexLookupFactoryPortType lookupPortType = createGeoIndexLookupFactory(scope, secManager);
	
				/* Create the index lookup resource */
				boolean bRetry;
				do {
					bRetry = false;
					try {
						createGeoIndexLookupResource(indexID, lookupPortType);
					} catch (Exception e) {
						System.out.println("Failed to create the lookup resource, probably because the management resource has not been published to the IS yet. Retrying...");
						//e.printStackTrace();
						bRetry = true;
					}
				} while (bRetry);			
				System.out.println("Lookup resource created successfully");
			}
		}
		else if (mode == operationMode.DESTROY) {
			try {
				if (bHandleManager) {
					GeoIndexManagementPortType mng = findGeoIndexManagementResource(collectionID, scope, secManager);
					mng.destroy(new Destroy());
				}
				
				if (bHandleLookup) {
					GeoIndexLookupPortType look = findGeoIndexLookupResource(collectionID, scope, secManager);
					if (look != null)
						look.destroy(new Destroy());
				}
			} catch (Exception e) { e.printStackTrace(); }
		}
		else if (mode == operationMode.FEED){
			/* Read the rowset resultset EPR from the file */
			try {
				String RS_EPR = readTextFile(RS_EPR_file);
				String indexID = findGeoIndexID(collectionID, scope, secManager);
				System.out.println("Connecting to index with indexID: " + indexID + " for updating");
				
				/* Create the index updater resource */
				GeoIndexUpdaterFactoryPortType updaterPortType = createGeoIndexUpdaterFactory(scope, secManager);
				GeoIndexUpdaterPortType updater = createGeoIndexUpdaterResource(indexID, updaterPortType, scope, secManager);
				updateIndexWithRowsetResultSet(updater, RS_EPR);
				System.out.println("Updating completed successfully.");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		else if (mode == operationMode.LOOKUP) {
			try {
				/* Find the index lookup resource */
				GeoIndexLookupPortType lookup = findGeoIndexLookupResource(collectionID, scope, secManager);
				
				/* Perform the lookup */
				String result = doLookup(lookup, points);
				System.out.println(result);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		new GeoIndexClient().run(args);
	}

}

