package IndexManagement;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
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.fulltextindexlookup.stubs.CreateStatistics;
import org.gcube.indexmanagement.fulltextindexlookup.stubs.FullTextIndexLookupFactoryPortType;
import org.gcube.indexmanagement.fulltextindexlookup.stubs.FullTextIndexLookupPortType;
import org.gcube.indexmanagement.fulltextindexlookup.stubs.service.FullTextIndexLookupFactoryServiceAddressingLocator;
import org.gcube.indexmanagement.fulltextindexlookup.stubs.service.FullTextIndexLookupServiceAddressingLocator;
import org.gcube.indexmanagement.fulltextindexmanagement.stubs.FullTextIndexManagementFactoryPortType;
import org.gcube.indexmanagement.fulltextindexmanagement.stubs.FullTextIndexManagementPortType;
import org.gcube.indexmanagement.fulltextindexmanagement.stubs.service.FullTextIndexManagementFactoryServiceAddressingLocator;
import org.gcube.indexmanagement.fulltextindexmanagement.stubs.service.FullTextIndexManagementServiceAddressingLocator;
import org.gcube.indexmanagement.fulltextindexupdater.stubs.FullTextIndexUpdaterFactoryPortType;
import org.gcube.indexmanagement.fulltextindexupdater.stubs.FullTextIndexUpdaterPortType;
import org.gcube.indexmanagement.fulltextindexupdater.stubs.Process;
import org.gcube.indexmanagement.fulltextindexupdater.stubs.service.FullTextIndexUpdaterFactoryServiceAddressingLocator;
import org.gcube.common.searchservice.searchlibrary.resultset.elements.ResultElementBLOBGeneric;
import org.gcube.common.searchservice.searchlibrary.rsclient.elements.RSLocator;
import org.gcube.common.searchservice.searchlibrary.rsclient.elements.RSResourceLocalType;
import org.gcube.common.searchservice.searchlibrary.rsreader.RSBLOBIterator;
import org.gcube.common.searchservice.searchlibrary.rsreader.RSBLOBReader;
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) FullTextIndexClient [ -cred <credentialFile> ] <scope> -create "manager" | "lookup" | "all" <colName> <colSchema> <colLang> <indexTypeID>
 * 2) FullTextIndexClient [ -cred <credentialFile> ] <scope> -destroy "manager" | "lookup" | "all" <colName> <colSchema> <colLang>
 * 3) FullTextIndexClient [ -cred <credentialFile> ] <scope> -feed <colName> <colSchema> <colLang> <RS_epr>
 * 4) FullTextIndexClient [ -cred <credentialFile> ] <scope> -lookup <colName> <colSchema> <colLang> <query> 
 * 5) FullTextIndexClient [ -cred <credentialFile> ] <scope> -createStats <colName> <colSchema> <colLang>
 * 
 * @author Spyros Boutsis, NKUA
 */

public class FullTextIndexClient {
	
	private enum operationMode { CREATE, FEED, LOOKUP, DESTROY, CREATESTATS } ; 
	
	String lookupFactoryURI; 
    String updaterFactoryURI; 
    String managementFactoryURI;
    
    /**
     * Stores the contents of a ResultSet containing statistics to a file.
     * @param RS_EPR
     */
    private void storeStatisticsRSToFile(String RS_EPR, String statisticsFileName) {
    	try {
    		String s = null;
	    	RSBLOBIterator iterator = RSBLOBReader.getRSBLOBReader(new RSLocator(RS_EPR)).makeLocal(new RSResourceLocalType()).getRSIterator();
	    	while (iterator.hasNext()) {
		    	ResultElementBLOBGeneric blob = (ResultElementBLOBGeneric)iterator.next(ResultElementBLOBGeneric.class);
		    	if(blob != null) {
					BufferedReader reader = new BufferedReader(new InputStreamReader(blob.getContentOfBLOB()));
					FileWriter writer = new FileWriter(statisticsFileName);
					while((s = reader.readLine()) != null) {
						writer.write(s);
					}
					reader.close();
					writer.close();
					break;
		    	}
	    	}
	    } catch (Exception e) {
    		e.printStackTrace();
    	}
    }
    
    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 FullTextIndexManagementFactoryPortType createFulltextIndexManagementFactory(GCUBEScope scope, GCUBESecurityManager secManager) {
        try {
            // Get factory portType
        	FullTextIndexManagementFactoryServiceAddressingLocator IndexManagementFactoryLocator = new FullTextIndexManagementFactoryServiceAddressingLocator();
        	EndpointReferenceType IndexManagementFactoryEPR = new EndpointReferenceType();
        	IndexManagementFactoryEPR.setAddress(new Address(managementFactoryURI));
        	FullTextIndexManagementFactoryPortType IndexManagementFactoryPortType = IndexManagementFactoryLocator.getFullTextIndexManagementFactoryPortTypePort(IndexManagementFactoryEPR);
        	//ConfigureSecurity.setSecurity(((Stub)forwardIndexManagementFactoryPortType), false, cred, GSIConstants.GSI_MODE_FULL_DELEG);
        	IndexManagementFactoryPortType = GCUBERemotePortTypeContext.getProxy(IndexManagementFactoryPortType, scope, secManager);
            return IndexManagementFactoryPortType;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
        return null;
    }
	
	private String createFulltextIndexManagementResource(String collectionID, String indexTypeID, FullTextIndexManagementFactoryPortType IndexManagementFactoryPortType) {
		try {
			// Create forwardIndex resource and get endpoint reference of WS-Resource.
			org.gcube.indexmanagement.fulltextindexmanagement.stubs.CreateResource IndexManagementCreateResource = new org.gcube.indexmanagement.fulltextindexmanagement.stubs.CreateResource();
			IndexManagementCreateResource.setCollectionID(collectionID);
			IndexManagementCreateResource.setIndexTypeID(indexTypeID);
			IndexManagementCreateResource.setIndexID(null);
			IndexManagementCreateResource.setContentType("MetaData");
			

			org.gcube.indexmanagement.fulltextindexmanagement.stubs.CreateResourceResponse IndexManagementCreateResourceResponse = 
				IndexManagementFactoryPortType.createResource(IndexManagementCreateResource);
			return IndexManagementCreateResourceResponse.getIndexID();
		}
		catch (Exception ex) {
			ex.printStackTrace();
			System.exit(0);
		}
		return null;
	}

	private FullTextIndexLookupFactoryPortType createFullTextIndexLookupFactory(GCUBEScope scope, GCUBESecurityManager secManager) {
        try {
            // Get factory portType
        	FullTextIndexLookupFactoryServiceAddressingLocator IndexLookupFactoryLocator = new FullTextIndexLookupFactoryServiceAddressingLocator();
        	EndpointReferenceType IndexLookupFactoryEPR = new EndpointReferenceType();
            IndexLookupFactoryEPR.setAddress(new Address(lookupFactoryURI));
            FullTextIndexLookupFactoryPortType IndexLookupFactoryPortType = IndexLookupFactoryLocator.getFullTextIndexLookupFactoryPortTypePort(IndexLookupFactoryEPR);
            IndexLookupFactoryPortType = GCUBERemotePortTypeContext.getProxy(IndexLookupFactoryPortType, scope, secManager);
            return IndexLookupFactoryPortType;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
        return null;
    }
	
	private void createFullTextIndexLookupResource(String mainIndexID, FullTextIndexLookupFactoryPortType IndexLookupFactoryPortType) throws RemoteException {
    	// Create forwardIndex resource and get endpoint reference of WS-Resource.
    	org.gcube.indexmanagement.fulltextindexlookup.stubs.CreateResource fulltextIndexLookupCreateResource =
    		new org.gcube.indexmanagement.fulltextindexlookup.stubs.CreateResource();

    	fulltextIndexLookupCreateResource.setMainIndexID(mainIndexID);
    	IndexLookupFactoryPortType.createResource(fulltextIndexLookupCreateResource);
    }

	private FullTextIndexLookupPortType findFullTextIndexLookupResource(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", "FullTextIndexLookup" });
			props.add(new String[] { "CollectionID", collectionID });
//			props.add(new String[] { "KeyName", indexedField });
			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 and indexed field name.");
			System.exit(0);
		}
		EndpointReferenceType epr = eprs.get(0);

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

	private FullTextIndexManagementPortType findFullTextIndexManagementResource(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", "FullTextIndexManagement" });
			props.add(new String[] { "CollectionID", collectionID });
//			props.add(new String[] { "KeyName", indexedField });
			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 and indexed field name.");
			System.exit(0);
		}
		EndpointReferenceType epr = eprs.get(0);

		FullTextIndexManagementServiceAddressingLocator instanceLocator = new FullTextIndexManagementServiceAddressingLocator();
		FullTextIndexManagementPortType port = null;
		try {
			port = instanceLocator.getFullTextIndexManagementPortTypePort(epr);
			port = GCUBERemotePortTypeContext.getProxy(port, scope, secManager);
			return port;
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}
		return null;
	}
	
	private String doLookup(FullTextIndexLookupPortType lookup, String query) throws Exception {
		return lookup.query(query);		
	}

	private FullTextIndexUpdaterFactoryPortType createFullTextIndexUpdaterFactory(GCUBEScope scope, GCUBESecurityManager secManager) {
        try {
            // Get factory portType
        	FullTextIndexUpdaterFactoryServiceAddressingLocator IndexUpdaterFactoryLocator = new FullTextIndexUpdaterFactoryServiceAddressingLocator();
        	EndpointReferenceType IndexUpdaterFactoryEPR = new EndpointReferenceType();
            IndexUpdaterFactoryEPR.setAddress(new Address(updaterFactoryURI));
            FullTextIndexUpdaterFactoryPortType IndexUpdaterFactoryPortType = IndexUpdaterFactoryLocator.getFullTextIndexUpdaterFactoryPortTypePort(IndexUpdaterFactoryEPR);
            IndexUpdaterFactoryPortType = GCUBERemotePortTypeContext.getProxy(IndexUpdaterFactoryPortType, scope, secManager);
            return IndexUpdaterFactoryPortType;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
        return null;
    }

	private String findFullTextIndexID(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", "FullTextIndexManagement" });
			props.add(new String[] { "CollectionID", collectionID });
//			props.add(new String[] { "KeyName", indexedField });
			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 and indexed field name.");
			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 FullTextIndexUpdaterPortType createFullTextIndexUpdaterResource(String mainIndexID, FullTextIndexUpdaterFactoryPortType IndexUpdaterFactoryPortType, GCUBEScope scope, GCUBESecurityManager secManager) {
		try {
			// Create forwardIndex resource and get endpoint reference of WS-Resource.
            org.gcube.indexmanagement.fulltextindexupdater.stubs.CreateResource fulltextIndexUpdaterCreateResource =
                new org.gcube.indexmanagement.fulltextindexupdater.stubs.CreateResource();       
            fulltextIndexUpdaterCreateResource.setMainIndexID(mainIndexID);

            org.gcube.indexmanagement.fulltextindexupdater.stubs.CreateResourceResponse fulltextIndexUpdaterCreateResourceResponse = 
                IndexUpdaterFactoryPortType.createResource(fulltextIndexUpdaterCreateResource);
            EndpointReferenceType IndexUpdaterInstanceEPR = fulltextIndexUpdaterCreateResourceResponse.getEndpointReference();
            
            // Port type
            org.gcube.indexmanagement.fulltextindexupdater.stubs.service.FullTextIndexUpdaterServiceAddressingLocator IndexupdaterServiceAddressingLocator = 
                new org.gcube.indexmanagement.fulltextindexupdater.stubs.service.FullTextIndexUpdaterServiceAddressingLocator();
            
            FullTextIndexUpdaterPortType fulltextIndexUpdaterPortTypePort = IndexupdaterServiceAddressingLocator.getFullTextIndexUpdaterPortTypePort(IndexUpdaterInstanceEPR);
            fulltextIndexUpdaterPortTypePort = GCUBERemotePortTypeContext.getProxy(fulltextIndexUpdaterPortTypePort, scope, secManager);
            return fulltextIndexUpdaterPortTypePort;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
        return null;
    }
	
	private void updateIndexWithRowsetResultSet(FullTextIndexUpdaterPortType updater, String RS_EPR) {
		try {
			Process process = new Process();

			process.setDestroyAfterUpdate(true);
			process.setResultSetLocation(RS_EPR);
			// Tell the updater to start gathering data from the ResultSet
			updater.process(process);

		} 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 collectionName = null;
		String collectionSchema = null;
		String collectionLang = null;
		String collectionID = null;
		String indexTypeID = null;
		String RS_EPR_file = null;
		String query = null;
		int baseArg = -1;
		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];
			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];
			if (args.length > (baseArg+5)) {
				query = args[baseArg+5];
			}
			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 if (args[1].equalsIgnoreCase("-createStats")) {
			collectionName = args[baseArg+2];
			collectionSchema = args[baseArg+3];
			collectionLang = args[baseArg+4];
			mode = operationMode.CREATESTATS;
		}
		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.getFullTextIndexManagementFactoryURI();
			lookupFactoryURI = VOManager.getFullTextIndexLookupFactoryURI();
			updaterFactoryURI = VOManager.getFullTextIndexUpdaterFactoryURI();
		} catch (Exception e) {
			System.out.println("Failed to parse VO properties file: " + e);
		}
		
		
		
		if (mode == operationMode.CREATE) {
			String indexID = null;

			/* Create the index management resource */
			if (bHandleManager) {
				FullTextIndexManagementFactoryPortType managementPortType = createFulltextIndexManagementFactory(scope, secManager);
				indexID = createFulltextIndexManagementResource(collectionID, indexTypeID, managementPortType);
				System.out.println("Management resource created successfully, indexID is: " + indexID);
			}
			
			if (bHandleLookup) {
				if (indexID == null)
					indexID = findFullTextIndexID(collectionID, scope, secManager);
				
				/* Get the full text index lookup factory service porttype */
				FullTextIndexLookupFactoryPortType lookupPortType = createFullTextIndexLookupFactory(scope, secManager);
	
				/* Create the index lookup resource */
				boolean bRetry;
				do {
					bRetry = false;
					try {
						createFullTextIndexLookupResource(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) {
					FullTextIndexManagementPortType mng = findFullTextIndexManagementResource(collectionID, scope, secManager);
					mng.destroy(new Destroy());
				}
				
				if (bHandleLookup) {
					FullTextIndexLookupPortType look = findFullTextIndexLookupResource(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 = findFullTextIndexID(collectionID, scope, secManager);
				System.out.println("Connecting to index with indexID: " + indexID + " for updating");
				
				/* Create the index updater resource */
				FullTextIndexUpdaterFactoryPortType updaterPortType = createFullTextIndexUpdaterFactory(scope, secManager);
				FullTextIndexUpdaterPortType updater = createFullTextIndexUpdaterResource(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 */
				FullTextIndexLookupPortType lookup = findFullTextIndexLookupResource(collectionID, scope, secManager);
				
				/* Perform the lookup */
				String result = doLookup(lookup, query);
				System.out.println(result);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		else if (mode == operationMode.CREATESTATS) {
			/* Find the index lookup resource and use it to create the stats */
			FullTextIndexLookupPortType lookup = findFullTextIndexLookupResource(collectionID, scope, secManager);
			try {
				String statsRSEPR = lookup.createStatistics(new CreateStatistics());
				storeStatisticsRSToFile(statsRSEPR, "statistics.xml");
				System.out.println("Created index statistics.");
				System.out.println("Wrote statistics file 'statistics.xml'.");
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
	}

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

}

