// // Copyright (c)1998-2011 Pearson Education, Inc. or its affiliate(s). // All rights reserved. // package openadk.examples.sifquery; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Iterator; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import openadk.library.*; import openadk.library.infra.SIF_Error; import openadk.library.tools.xpath.SIFXPathContext; public class SIFQuery extends Agent implements QueryResults { private static Map<String, ComparisonOperators> supportedComparisons = new HashMap<String, ComparisonOperators>(); public SIFQuery() { super( "SIFQuery" ); } private synchronized static void initializeComparisonList() { if (supportedComparisons.size() == 0) { supportedComparisons.put("=", ComparisonOperators.EQ); supportedComparisons.put(">", ComparisonOperators.GT); supportedComparisons.put("<", ComparisonOperators.LT); supportedComparisons.put(">=", ComparisonOperators.GE); supportedComparisons.put("<=", ComparisonOperators.LE); supportedComparisons.put("!=", ComparisonOperators.NE); } } /** * @param args */ public static void main(String[] args) { final SIFQuery _agent = new SIFQuery();; try { if( args.length < 2 ) { System.out.println("Usage: SIFQuery /zone zone /url url [/events] [options]"); System.out.println(" /zone zone The name of the zone"); System.out.println(" /url url The zone URL"); ADKExamples.printHelp(); return; } // Pre-parse the command-line before initializing the ADK ADK.debug = ADK.DBG_MODERATE; ADKExamples.parseCL( null, args ); // Initialize the ADK with the specified version, loading only the Student SDO package ADK.initialize(); // Call StartAgent. _agent.startAgent(args); // Turn down debugging ADK.debug = ADK.DBG_NONE; // Call runConsole() This method does not return until the agent shuts down _agent.runConsole(); // Wait for Ctrl-C to be pressed Object semaphore = new Object(); synchronized( semaphore ) { semaphore.wait(); } System.out.println("Agent is running (Press Ctrl-C to stop)"); } catch( Throwable e ) { System.out.println(e); } finally { if( _agent != null && _agent.isInitialized() ){ // Always shutdown the agent on exit try { _agent.shutdown( ADKExamples.Unreg ? ADKFlags.PROV_UNREGISTER : ADKFlags.PROV_NONE ); } catch( ADKException adkEx ){ System.out.println( adkEx ); adkEx.printStackTrace(); } } } } private void startAgent(String[] args) throws Exception { this.initialize(); Map params = ADKExamples.parseCL( this, args ); String zoneId = (String)params.get("zone"); String url = (String)params.get("url"); if( zoneId == null || url == null ) { System.out.println("The /zone and /url parameters are required"); System.exit(0); } // 1) Get an instance of the zone to connect to Zone zone = getZoneFactory().getInstance( zoneId, url ); zone.getProperties().setCompressionThreshold(0); zone.setQueryResults( this ); // 3) Connect to zones zone.connect( ADKExamples.Reg ? ADKFlags.PROV_REGISTER : ADKFlags.PROV_NONE ); zone.getZoneStatus(); } private void runConsole() throws IOException, ADKException { System.out.println( "SIFQuery Command Line" ); System.out.println( "Version @PRODUCT_VERSION@" ); printSQLHelp(); BufferedReader input = new BufferedReader( new InputStreamReader( System.in ) ); Pattern sqlPattern = Pattern.compile( "(?:select)(.*)(?:from)(.*)(?:where)(.*)$", Pattern.CASE_INSENSITIVE ); boolean finished = false; while( !finished ){ printPrompt(); String query = input.readLine().trim(); if( query.length() == 0 ){ continue; } String lcaseQuery = query.toLowerCase(); if( lcaseQuery.charAt( 0 ) == 'q' ){ finished = true; continue; } if( lcaseQuery.indexOf( "where" ) == -1 ){ // The regular expression requires a where clause query = query + " where "; } Matcher results = null; try { results = sqlPattern.matcher( query ); } catch( Exception ex ){ System.out.println( "ERROR evaluating expression: " + ex ); continue; } if( !results.matches() ){ System.out.println( "Unknown error evaluating expression." ); continue; } if( results.groupCount() == 3 ){ Query q = createQuery( results.group( 2 ) ); if( q != null && addConditions( q, results.group( 3 ) ) && addSelectFields( q, results.group( 1 ) ) ) { System.out.println( "Sending Query to zone.... " ); String queryXML = q.toXML(); System.out.println( queryXML ); // Store the original source query in the userData property q.setUserData( queryXML ); this.getZoneFactory().getAllZones()[0].query( q ); } } else { System.out.println( "ERROR: Unrecognized query syntax..." ); printSQLHelp(); } } } private void printPrompt(){ System.out.print( "SIF: " ); } private void printSQLHelp(){ System.out.println( "Syntax: Select {fields} From {SIF Object} [Where {field}={value}] " ); System.out.println( " {fields} one or more field names, seperated by a comma" ); System.out.println( " (may by empty or * )" ); System.out.println( " {SIF Object} the name of a SIF Object that is provided in the zone" ); System.out.println( " {field} a field name" ); System.out.println( " {value} a value" ); System.out.println( "Examples:" ); System.out.println( "SIF: Select * from StudentPersonal" ); System.out.println( "SIF: Select * from StudentPersonal where RefId=43203167CFF14D08BB9C8E3FD0F9EC3C" ); System.out.println( "SIF: Select * from StudentPersonal where Name/FirstName=Amber" ); System.out.println( "SIF: Select Name/FirstName, Name/LastName from StudentPersonal where Demographics/Gender=F" ); System.out.println( "SIF: Select * from StudentSchoolEnrollment where RefId=43203167CFF14D08BB9C8E3FD0F9EC3C" ); System.out.println(); } private Query createQuery( String fromClause ){ ElementDef queryDef = ADK.DTD().lookupElementDef( fromClause.trim() ); if( queryDef == null ){ System.out.println( "ERROR: Unrecognized FROM statement: " + fromClause ); printSQLHelp(); return null; } else{ return new Query( queryDef ); } } private boolean addSelectFields(Query q, String selectClause ) { if( selectClause.length() == 0 || selectClause.indexOf( "*" ) > -1 ){ return true; } String[] fields = selectClause.split( "," ); for( String field : fields ){ field = field.trim(); if( field.length() > 0 ){ ElementDef restriction =ADK.DTD().lookupElementDefBySQP( q.getObjectType(), field ); if( restriction == null ){ System.out.println( "ERROR: Unrecognized SELECT field: " + field ); printSQLHelp(); return false; } else { q.addFieldRestriction( restriction ); } } } return true; } private boolean addConditions(Query q, String whereClause ) { initializeComparisonList(); boolean added = true; whereClause = whereClause.trim(); if( whereClause.length() == 0 ){ return added; } String[] whereConditions = whereClause.split(" [aA][nN][dD] "); ComparisonOperators cmpOperator = ComparisonOperators.EQ; String[] fields = null; if (whereConditions.length > 0) { for (String condition : whereConditions) { fields = null; for (Map.Entry<String, ComparisonOperators> kvp : supportedComparisons.entrySet()) { String cmpString = kvp.getKey(); cmpOperator = kvp.getValue(); if (cmpOperator == ComparisonOperators.EQ) { int index = condition.lastIndexOf(cmpString); fields = new String[2]; if (index > 0) { fields[0] = condition.substring(0, index); fields[1] = condition.substring((index + 1)); } else { fields[0] = condition; } } if (fields == null) { fields = condition.split(cmpString); } if (fields[0] == condition) { //Means no match found using that current comparison operator //so skip this condition fields = null; continue; } if (fields.length != 2) { System.out.println("ERROR: Unsupported where clause: " + whereClause); printSQLHelp(); added = false; break; } String fieldExpr = fields[0].trim(); ElementDef sdo = ADK.DTD().lookupElementDefBySQP(q.getObjectType(), fields[0].trim()); if (sdo == null) { System.out.println("ERROR: Unrecognized field in where clause: " + fields[0].trim()); printSQLHelp(); added = false; break; } else { if (fieldExpr.indexOf('[') > 0) { // If there is a square bracket in the field syntax, use the raw XPath, // rather then the ElementDef because using ElementDef restrictions // does not work for XPath expressions that contain predicates // Note that using raw XPath expressions works fine, but the ADK is no longer // going to be able to use version-independent rendering of the query q.addCondition(fieldExpr, cmpOperator, fields[1].trim()); } else { q.addCondition( sdo, cmpOperator, fields[1].trim() ); } //our condition has been found, no need to check the other comparison //operators for a match so move to the next condition break; } } }//end for each } return added; } public void onQueryPending(MessageInfo info, Zone zone) throws ADKException { SIFMessageInfo smi = (SIFMessageInfo)info; System.out.println( "Sending SIF Request with MsgId " + smi.getMsgId() + " to zone " + zone.getZoneId() ); } public void onQueryResults(DataObjectInputStream data, SIF_Error error, Zone zone, MessageInfo info) throws ADKException { SIFMessageInfo smi = (SIFMessageInfo)info; System.out.println(); System.out.println( "********************************************* " ); System.out.println( "Received SIF_Response packet from zone" + zone.getZoneId() ); System.out.println( "Details... " ); System.out.println( "Request MsgId: " + smi.getSIFRequestMsgId() ); System.out.println( "Packet Number: " + smi.getPacketNumber() ); System.out.println(); if( error != null ){ System.out.println( "The publisher returned an error: " ); System.out.println( "Category: " + error.getSIF_Category() + " Code: " + error.getSIF_Code() ); System.out.println( "Description " + error.getSIF_Desc() ); if( error.getSIF_ExtendedDesc() != null ) { System.out.println( "Details: " + error.getSIF_ExtendedDesc() ); } return; } try { int objectCount = 0; while( data.available() ){ SIFDataObject next = data.readDataObject(); objectCount++; System.out.println(); System.out.println( "Text Values for " + next.getElementDef().name() + " " + objectCount + " {" + next.getKey() + "}" ); SIFXPathContext context = SIFXPathContext.newSIFContext( next ); // Print out all attributes Iterator textNodes = context.iterate("//@*"); while( textNodes.hasNext() ) { Element value = (Element)textNodes.next(); ElementDef valueDef = value.getElementDef(); System.out.print( valueDef.getParent().tag( SIFVersion.LATEST ) + "/@" + valueDef.tag( SIFVersion.LATEST ) + "=" + value.getTextValue() + ", " ); } System.out.println(); // Print out all elements that have a text value textNodes = context.iterate("//*"); while( textNodes.hasNext() ) { Element value = (Element)textNodes.next(); String textValue = value.getTextValue(); if( textValue != null ){ ElementDef valueDef = value.getElementDef(); System.out.print( valueDef.tag( SIFVersion.LATEST ) + "=" + textValue + ", " ); } } } System.out.println(); System.out.println( "Total Objects in Packet: " + objectCount ); } catch( Exception ex ){ System.out.println( ex.getMessage() ); ex.printStackTrace(); } if( !smi.getMorePackets() ){ // This is the final packet. Print stats System.out.println( "Final Packet has been received." ); RequestInfo ri = smi.getSIFRequestInfo(); if( ri != null ){ System.out.println( "Source Query: " ); System.out.println( ri.getUserData() ); long difference = smi.getTimestamp().getTime().getTime() - ri.getRequestTime().getTime(); System.out.println( "Query execution time: " + difference + " ms" ); } } else { System.out.println( "This is not the final packet for this SIF_Response" ); } System.out.println( "********************************************* " ); System.out.println( ); printPrompt(); } }