Input: Calls a method on each TableHelper depending on the { @link UpgradeStrategy } . In order to prevent recursive calls to getDatabase () this method must pass the db parameter through to any other methods that need it . [CODESPLIT] @ Override public void onUpgrade ( SQLiteDatabase db , int oldVersion , int newVersion ) { switch ( getUpgradeStrategy ( ) ) { case DROP_CREATE : this . dropAndCreate ( db ) ; break ; case BACKUP_RESTORE : this . backupAndRestore ( this . getContext ( ) , db ) ; break ; case UPGRADE : this . upgrade ( db , oldVersion , newVersion ) ; break ; } }


Input: Calls { @link TableHelper#onUpgrade ( SQLiteDatabase int int ) } for each TableHelper . Override this method to implement your own upgrade strategy . [CODESPLIT] public void upgrade ( SQLiteDatabase db , int oldVersion , int newVersion ) { for ( TableHelper th : getTableHelpers ( ) ) { th . onUpgrade ( db , oldVersion , newVersion ) ; } }


Input: Backs up all tables to CSV drops and recreates them then restores them from CSV . By default creates CSV filenames with no suffix . You could override this method to supply a timestamp suffix ( make sure it s the same for both backup and restore ) but beware that this could cause backup files to proliferate . Ideally this method should clean up backup files after the database has been restored . [CODESPLIT] public void backupAndRestore ( Context ctx , SQLiteDatabase db ) { if ( backupAllTablesToCsv ( ctx , db , null ) ) { dropAndCreate ( db ) ; restoreAllTablesFromCsv ( ctx , db , null ) ; } else { throw new RuntimeException ( "Backup of " + getDatabaseName ( ) + " failed, aborting upgrade" ) ; } }


Input: Backup all tables to CSV files one per table [CODESPLIT] public boolean backupAllTablesToCsv ( Context ctx , SQLiteDatabase db , String suffix ) { boolean allSucceeded = true ; for ( TableHelper table : getTableHelpers ( ) ) { allSucceeded &= table . backup ( db , ctx , suffix ) ; } return allSucceeded ; }


Input: Restore all tables from CSV files one per table [CODESPLIT] public void restoreAllTablesFromCsv ( Context ctx , SQLiteDatabase db , String suffix ) { for ( TableHelper table : getTableHelpers ( ) ) { table . restore ( db , ctx , suffix ) ; } }


Input: Read the current model state from a file in support of incremental compilation . This is necessary because the annotation processor has access to only classes which have been annotated ( and any resulting generated classes on subsequent rounds ) but DatabaseHelper classes aren t available when doing incremental compilation on a new @Entity . [CODESPLIT] void readIndex ( Filer filer ) { StandardLocation location = StandardLocation . SOURCE_OUTPUT ; FileObject indexFile ; try { indexFile = filer . getResource ( location , "com.turbomanage.storm" , ENV_FILE ) ; logger . info ( "Reading index " + indexFile . toUri ( ) ) ; // indexFile.openReader() not implemented on all platforms Reader fileReader = new InputStreamReader ( indexFile . openInputStream ( ) ) ; BufferedReader reader = new BufferedReader ( fileReader ) ; String line = reader . readLine ( ) ; // BEGIN_CONVERTERS line = reader . readLine ( ) ; while ( line != null && ! line . startsWith ( END_CONVERTERS ) ) { ConverterModel converter = ConverterModel . readFromIndex ( line , logger ) ; this . addConverter ( converter ) ; line = reader . readLine ( ) ; } line = reader . readLine ( ) ; while ( line != null && line . startsWith ( BEGIN_DATABASE ) ) { DatabaseModel dbModel = DatabaseModel . readFromIndex ( reader , logger ) ; this . addDatabase ( dbModel ) ; line = reader . readLine ( ) ; } reader . close ( ) ; } catch ( IOException e ) { // gulp--only way to catch not yet existing file on first run } }


Input: Write the current model state to a file in support of incremental compilation . [CODESPLIT] void writeIndex ( Filer filer ) { StandardLocation location = StandardLocation . SOURCE_OUTPUT ; FileObject indexFile ; try { indexFile = filer . createResource ( location , "com.turbomanage.storm" , ENV_FILE ) ; OutputStream fos = indexFile . openOutputStream ( ) ; PrintWriter out = new PrintWriter ( fos ) ; // Dump converters out . println ( BEGIN_CONVERTERS ) ; for ( ConverterModel converter : converters ) { converter . writeToIndex ( out ) ; } out . println ( END_CONVERTERS ) ; // Dump databases for ( DatabaseModel dbModel : dbModels . values ( ) ) { dbModel . writeToIndex ( out ) ; } out . close ( ) ; } catch ( IOException e ) { throw new RuntimeException ( e ) ; } }


Input: Register a custom { @link TypeConverter } for a given data ( field ) type . This method is called at compile time by the annotation processor . In order for the TypeConverter to be visible it must be in a jar on the client project s annotation factory classpath . [CODESPLIT] public boolean addConverter ( ConverterModel converter ) { if ( converters . contains ( converter ) ) return true ; for ( String type : converter . getConvertibleTypes ( ) ) { // TODO what if already put the 1st type? if ( typeMap . containsKey ( type ) && ! typeMap . get ( type ) . equals ( converter ) ) return false ; typeMap . put ( type , converter ) ; } converters . add ( converter ) ; logger . info ( "Added " + converter . getQualifiedClassName ( ) ) ; return true ; }


Input: Returns a JPA Query with all previously specified parameters added . [CODESPLIT] public Query createQuery ( final EntityManager manager ) { if ( manager == null ) { throw new NullPointerException ( "Entity Manager required" ) ; } final Query query = manager . createQuery ( render ( ) ) ; for ( Parameter < ? > parameter : parameters ) { parameter . apply ( query ) ; } return query ; }


Input: Returns a JPA TypedQuery with all previously specified parameters added . [CODESPLIT] public < T > TypedQuery < T > createQuery ( final EntityManager manager , Class < T > type ) { if ( manager == null ) { throw new NullPointerException ( "Entity Manager required" ) ; } TypedQuery < T > result = manager . createQuery ( render ( ) , type ) ; for ( Parameter < ? > parameter : parameters ) { parameter . apply ( result ) ; } return result ; }


Input: Adds the given parameter to the builder . All parameters will added to the JPA Query returned by a call to { @link #createQuery ( EntityManager ) } or { @link #createQuery ( EntityManager Class ) } . [CODESPLIT] public QueryBuilder setParameter ( final String name , final Calendar value , TemporalType temporalType ) { return setParameter ( new ParameterCalendar ( name , value , temporalType ) ) ; }


Input: Adds the given parameter to the builder . All parameters will added to the JPA Query returned by a call to { @link #createQuery ( EntityManager ) } or { @link #createQuery ( EntityManager Class ) } . [CODESPLIT] public QueryBuilder setParameter ( final String name , final Date value , final TemporalType temporalType ) { return setParameter ( new ParameterDate ( name , value , temporalType ) ) ; }


Input: Adds the given parameter to the builder . All parameters will added to the JPA Query returned by a call to { @link #createQuery ( EntityManager ) } or { @link #createQuery ( EntityManager Class ) } . [CODESPLIT] public QueryBuilder setParameter ( final String name , final Object value ) { return setParameter ( new ParameterObject ( name , value ) ) ; }


Input: Adds given parameter to the builder . All parameters will added to the JPA Query returned by a call to { @link #createQuery ( EntityManager ) } or { @link #createQuery ( EntityManager Class ) } . [CODESPLIT] public QueryBuilder setParameter ( final Parameter < ? > parameter ) { if ( parent == null ) { parameters . add ( parameter ) ; } else { parent . setParameter ( parameter ) ; } return this ; }


Input: Adds all given parameters to the builder . All parameters will added to the JPA Query returned by a call to { @link #createQuery ( EntityManager ) } or { @link #createQuery ( EntityManager Class ) } . [CODESPLIT] public QueryBuilder setParameters ( final List < Parameter < ? > > parameters ) { if ( parent == null ) { this . parameters . addAll ( parameters ) ; } else { parent . setParameters ( parameters ) ; } return this ; }


Input: Renders this object as JPQL query string . [CODESPLIT] public String render ( ) { StringBuilder query = new StringBuilder ( ) ; if ( ! select . isEmpty ( ) ) { query . append ( "SELECT " ) ; query . append ( StringUtils . join ( select . items ) ) ; } if ( ! deleteFrom . isEmpty ( ) ) { query . append ( "DELETE FROM " ) ; query . append ( deleteFrom . item ) ; } if ( ! update . isEmpty ( ) ) { query . append ( "UPDATE " ) ; query . append ( update . item ) ; if ( ! set . isEmpty ( ) ) { query . append ( " SET " ) ; query . append ( StringUtils . join ( set . items ) ) ; } } if ( ! from . isEmpty ( ) ) { query . append ( " FROM " ) ; query . append ( StringUtils . join ( from . items ) ) ; } if ( ! where . isEmpty ( ) ) { query . append ( " WHERE " ) ; query . append ( where . render ( ) ) ; } if ( ! group . isEmpty ( ) ) { query . append ( " GROUP BY " ) ; query . append ( StringUtils . join ( group . items ) ) ; } if ( order . isEmpty ( ) == false ) { query . append ( " ORDER BY " ) ; query . append ( StringUtils . join ( order . items ) ) ; } return query . toString ( ) ; }


Input: Deletes a single row by ID . Returns the number of rows deleted or 0 if unsuccessful . [CODESPLIT] public int delete ( Long id ) { if ( id != null ) { return getWritableDb ( ) . delete ( th . getTableName ( ) , th . getIdCol ( ) + "=?" , new String [ ] { id . toString ( ) } ) ; } return 0 ; }


Input: Returns a single object by ID or null if no match found . If more than one match is found throws { @link TooManyResultsException } . [CODESPLIT] public T get ( Long id ) { return load ( ) . eq ( th . getIdCol ( ) , id ) . get ( ) ; }


Input: Inserts a row for the provided entity . If the entity s id is the default long ( 0 ) the database generates an id and populates the entity s ID field . Returns the generated ID or - 1 if error . [CODESPLIT] public long insert ( T obj ) { ContentValues cv = th . getEditableValues ( obj ) ; if ( th . getId ( obj ) == 0 ) { // the default, remove from ContentValues to allow autoincrement cv . remove ( th . getIdCol ( ) . toString ( ) ) ; } long id = getWritableDb ( ) . insertOrThrow ( th . getTableName ( ) , null , cv ) ; th . setId ( obj , id ) ; return id ; }


Input: Efficiently insert a collection of entities using { @link InsertHelper } . [CODESPLIT] public long insertMany ( Iterable < T > many ) { long numInserted = 0 ; InsertHelper insertHelper = new DatabaseUtils . InsertHelper ( getWritableDb ( ) , th . getTableName ( ) ) ; getWritableDb ( ) . beginTransaction ( ) ; try { for ( T obj : many ) { ContentValues cv = th . getEditableValues ( obj ) ; if ( th . getId ( obj ) == 0 ) { // the default, remove from ContentValues to allow autoincrement cv . remove ( th . getIdCol ( ) . toString ( ) ) ; } long id = insertHelper . insert ( cv ) ; if ( id == - 1 ) return - 1 ; numInserted ++ ; } getWritableDb ( ) . setTransactionSuccessful ( ) ; } finally { getWritableDb ( ) . endTransaction ( ) ; } return numInserted ; }


Input: Insert or update . [CODESPLIT] public long save ( T obj ) { if ( th . getId ( obj ) == 0 ) { return insert ( obj ) ; } long updated = update ( obj ) ; if ( updated == 1 ) { return 0 ; } return - 1 ; }


Input: Update all columns for the row having the ID matching the provided entity s ID . [CODESPLIT] public long update ( T obj ) { ContentValues cv = th . getEditableValues ( obj ) ; Long id = th . getId ( obj ) ; int numRowsUpdated = getWritableDb ( ) . update ( th . getTableName ( ) , cv , th . getIdCol ( ) + "=?" , new String [ ] { id . toString ( ) } ) ; return numRowsUpdated ; }


Input: Convenience method queries the entity table using the provided WHERE clause and parameters and returns a { @link Cursor } . [CODESPLIT] public Cursor query ( String where , String [ ] params ) { return query ( where , params , null ) ; }


Input: Convenience method queries the entity table using the provided WHERE clause and parameters and returns a { @link Cursor } . [CODESPLIT] public Cursor query ( String where , String [ ] params , String orderBy ) { return getReadableDb ( ) . query ( th . getTableName ( ) , null , where , params , null , null , orderBy ) ; }


Input: Converts all rows in a { @link Cursor } to a List of objects . [CODESPLIT] public List < T > asList ( Cursor c ) { // TODO consider returning Iterable<T> instead try { ArrayList < T > resultList = new ArrayList < T > ( ) ; for ( boolean hasItem = c . moveToFirst ( ) ; hasItem ; hasItem = c . moveToNext ( ) ) { T obj = th . newInstance ( c ) ; resultList . add ( obj ) ; } return resultList ; } finally { c . close ( ) ; } }


Input: Converts a { @link Cursor } to an object . If there is more than one row in the Cursor throws { @link TooManyResultsException } . [CODESPLIT] public T asObject ( Cursor c ) { try { if ( c . getCount ( ) == 1 ) { c . moveToFirst ( ) ; return th . newInstance ( c ) ; } else if ( c . getCount ( ) > 1 ) { throw new TooManyResultsException ( "Cursor returned " + c . getCount ( ) + " rows" ) ; } return null ; } finally { c . close ( ) ; } }


Input: Associate given { @link QueryBuilder } with this object and all of its items . [CODESPLIT] void setBuilder ( final QueryBuilder builder ) { super . setBuilder ( builder ) ; for ( WhereItem item : items ) { item . setBuilder ( builder ) ; } }


Input: Add a { @link WhereItem } to this object . [CODESPLIT] public WhereItem add ( final WhereItem item ) { items . add ( item ) ; item . setBuilder ( builder ( ) ) ; return this ; }


Input: Adds an { @literal SQL } { @code AND } clause . [CODESPLIT] public WhereAnd and ( ) { final WhereAnd and = new WhereAnd ( builder ( ) ) ; items . add ( and ) ; return and ; }


Input: Adds an { @literal SQL } { @code OR } clause . [CODESPLIT] public WhereOr or ( ) { final WhereOr or = new WhereOr ( builder ( ) ) ; items . add ( or ) ; return or ; }


Input: Adds an { @literal SQL } { @code IN } predicate . [CODESPLIT] public < V extends Object > WhereItems in ( final String expression , final Collection < V > collection ) { items . add ( new WhereIn ( builder ( ) , expression , false , collection ) ) ; return this ; }


Input: Adds an { @literal SQL } { @code IN } predicate . [CODESPLIT] public < V extends Object > WhereItems in ( final String expression , final V ... array ) { items . add ( new WhereIn ( builder ( ) , expression , false , array ) ) ; return this ; }


Input: Adds a { @code NOT IN } predicate . [CODESPLIT] public < V extends Object > WhereItems notIn ( final String expression , final Collection < V > collection ) { items . add ( new WhereIn ( builder ( ) , expression , true , collection ) ) ; return this ; }


Input: Adds a NOT IN predicate . [CODESPLIT] public < V extends Object > WhereItems notIn ( final String expression , final V ... array ) { items . add ( new WhereIn ( builder ( ) , expression , true , array ) ) ; return this ; }


Input: Adds a sub - query predicate . [CODESPLIT] public QueryBuilder subquery ( final String lhsPredicate ) { final WhereSubquery subquery = new WhereSubquery ( builder ( ) , lhsPredicate ) ; items . add ( subquery ) ; return subquery . getQueryBuilder ( ) ; }


Input: { [CODESPLIT] @ Override public boolean context ( ) { int myid = getAgent ( ) . getId ( ) ; Token2 goal = ( Token2 ) getGoal ( ) ; return ( myid == goal . getAgent ( ) ) ; }


Input: / * package [CODESPLIT] void log ( ) { Board board = ( ( Player ) getAgent ( ) ) . getBoard ( ) ; Player . out . println ( "Moving disc " + solve . disc + " from pin " + solve . src + " to " + solve . dest ) ; board . move ( solve . src , solve . dest ) ; Player . out . println ( board . toString ( ) ) ; }


Input: Makes the next intentions stack active using a round robin scheme . [CODESPLIT] Stack255 nextActiveStack ( ) { activeStack = ( activeStack + 1 ) % stacks . size ( ) ; return ( Stack255 ) stacks . get ( activeStack ) ; }


Input: Returns an empty intentions stack . Creates a new intentions stack and adds it to the list of stacks if needed . [CODESPLIT] Stack255 getEmptyIntentionStack ( ) { // If the active stack is empty then return it (don't check other stacks) if ( ! stacks . isEmpty ( ) && getActiveStack ( ) . isEmpty ( ) ) { return getActiveStack ( ) ; } // else create an empty stack, add it to the list ot stacks, and return it Stack255 stack = new Stack255 ( ( byte ) 8 , ( byte ) 2 ) ; stacks . push ( stack ) ; return stack ; }


Input: Add the set of bindings for a given plan to this store . Any previously stored bindings for this plan will be replaced . [CODESPLIT] public void add ( Plan plan , Set < Belief > planBindings ) { if ( plan == null ) { return ; } // remove any old bindings, making sure to decrement the cached size if ( this . bindings . containsKey ( plan ) ) { Set < Belief > oldBindings = this . bindings . remove ( plan ) ; if ( oldBindings == null || oldBindings . isEmpty ( ) ) { cachedsize -- ; } else { cachedsize -= oldBindings . size ( ) ; } } // add this binding and update the cached size this . bindings . put ( plan , planBindings ) ; if ( planBindings == null || planBindings . isEmpty ( ) ) { cachedsize ++ ; } else { cachedsize += planBindings . size ( ) ; } }


Input: Selects a plan instance from the set of plan bindings using the given policy . [CODESPLIT] public Plan selectPlan ( PlanSelectionPolicy policy ) { Plan plan = null ; int index = 0 ; switch ( policy ) { case FIRST : case LAST : Plan [ ] plans = bindings . keySet ( ) . toArray ( new Plan [ 0 ] ) ; plan = ( policy == PlanSelectionPolicy . FIRST ) ? plans [ 0 ] : plans [ plans . length - 1 ] ; index = ( policy == PlanSelectionPolicy . FIRST ) ? 0 : plans . length - 1 ; setPlanVariables ( plan . getAgent ( ) , plan , bindings . get ( plan ) , index ) ; break ; case RANDOM : plan = selectPlanAtRandom ( ) ; break ; default : // TODO: ignore remaining polic break ; } return plan ; }


Input: Selects a plan instance at random from the set of plan bindings . [CODESPLIT] private Plan selectPlanAtRandom ( ) { Plan plan = null ; Set < Belief > vars = null ; int index = rand . nextInt ( size ( ) ) ; int idx = 0 ; boolean bindingsExist = false ; for ( Plan p : bindings . keySet ( ) ) { vars = bindings . get ( p ) ; bindingsExist = ( vars != null && ! vars . isEmpty ( ) ) ; idx += bindingsExist ? vars . size ( ) : 1 ; if ( idx > index ) { plan = p ; if ( bindingsExist ) { index = index - ( idx - vars . size ( ) ) ; setPlanVariables ( plan . getAgent ( ) , plan , vars , index ) ; } break ; } } return plan ; }


Input: Sets the plan instance variables using the given results set . [CODESPLIT] private final void setPlanVariables ( Agent agent , Plan planInstance , Set < Belief > results , int choice ) { if ( agent == null || planInstance == null ) { return ; } Belief belief = getResultAtIndex ( results , choice ) ; if ( belief == null ) { return ; } Object [ ] tuple = belief . getTuple ( ) ; if ( tuple == null ) { return ; } int index = 0 ; HashMap < String , Object > vars = new HashMap < String , Object > ( ) ; for ( Object o : belief . getTuple ( ) ) { try { String fieldname = ABeliefStore . getFieldName ( agent . getId ( ) , belief . getBeliefset ( ) , index ) ; vars . put ( fieldname , o ) ; } catch ( BeliefBaseException e ) { Log . error ( "Agent " + agent . getId ( ) + " could not retrive belief set field: " + e . getMessage ( ) ) ; } index ++ ; } planInstance . setPlanVariables ( vars ) ; }


Input: Gets the result at the given index from the results set . [CODESPLIT] private Belief getResultAtIndex ( Set < Belief > results , int index ) { Belief belief = null ; if ( ! ( results == null || index < 0 || index >= results . size ( ) ) ) { int idx = 0 ; for ( Belief b : results ) { if ( idx == index ) { belief = b ; break ; } idx ++ ; } } return belief ; }


Input: Gets the parents of this object in the Goal - Plan tree . [CODESPLIT] public byte [ ] getParents ( ) { if ( parents == null ) { return null ; } byte [ ] arr = new byte [ parents . length ] ; System . arraycopy ( parents , 0 , arr , 0 , arr . length ) ; return arr ; }


Input: Gets all the children of this object in the Goal - Plan tree . [CODESPLIT] public byte [ ] getChildren ( ) { if ( children == null ) { return null ; } byte [ ] arr = new byte [ children . length ] ; System . arraycopy ( children , 0 , arr , 0 , arr . length ) ; return arr ; }


Input: Grows the given array by the given size . [CODESPLIT] public static byte [ ] grow ( byte [ ] bytes , int increment ) { if ( bytes == null ) { return new byte [ 1 ] ; } byte [ ] temp = new byte [ bytes . length + increment ] ; System . arraycopy ( bytes , 0 , temp , 0 , bytes . length ) ; return temp ; }


Input: Creates a new logger . [CODESPLIT] public static Logger createLogger ( String name , Level level , String file ) { LoggerContext lc = ( LoggerContext ) LoggerFactory . getILoggerFactory ( ) ; PatternLayoutEncoder ple = new PatternLayoutEncoder ( ) ; ple . setPattern ( "%date %level [%thread] %logger{10} [%file:%line]%n%msg%n%n" ) ; ple . setContext ( lc ) ; ple . start ( ) ; FileAppender < ILoggingEvent > fileAppender = new FileAppender < ILoggingEvent > ( ) ; fileAppender . setFile ( file ) ; fileAppender . setEncoder ( ple ) ; fileAppender . setAppend ( false ) ; fileAppender . setContext ( lc ) ; fileAppender . start ( ) ; logger = ( Logger ) LoggerFactory . getLogger ( name ) ; logger . detachAndStopAllAppenders ( ) ; // detach console (doesn't seem to work) logger . addAppender ( fileAppender ) ; // attach file appender logger . setLevel ( level ) ; logger . setAdditive ( true ) ; // set to true if root should log too return logger ; }


Input: Performs a single step of this plan i . e . progresses this intention . [CODESPLIT] public void step ( ) { if ( body == null || body . length == 0 || index < 0 || index >= body . length ) { return ; } body [ index ++ ] . step ( ) ; }


Input: Sets the list of goals for this agent . [CODESPLIT] public void setGoals ( byte [ ] arr ) { if ( arr == null ) { goals = null ; return ; } goals = new byte [ arr . length ] ; System . arraycopy ( arr , 0 , goals , 0 , goals . length ) ; }


Input: <p > addGoal . < / p > [CODESPLIT] public void addGoal ( byte goal ) { goals = GoalPlanType . grow ( goals , 1 ) ; goals [ goals . length - 1 ] = goal ; }


Input: Waits for user to press a key before continuing . Useful for connecting to a profiler [CODESPLIT] static void pauseForUserInput ( ) { System . out . println ( "Press the Enter/Return key to continue.." ) ; Scanner in = new Scanner ( System . in ) ; in . nextLine ( ) ; in . close ( ) ; }


Input: Initialises the intention selection pools . [CODESPLIT] public static void initIntentionSelectionPools ( int nagents , int ncores ) { Main . poolsize = ( nagents > ncores ) ? ( nagents / ncores ) : 1 ; Main . npools = ( nagents > ncores ) ? ncores : nagents ; }


Input: Starts the intention selection threads that each handle a pool of agents . [CODESPLIT] static void initIntentionSelectionThreads ( Config config ) { int ncores = config . getNumThreads ( ) ; Main . intentionSelectors = new IntentionSelector [ ncores ] ; for ( int i = 0 ; i < Main . npools ; i ++ ) { Main . intentionSelectors [ i ] = new IntentionSelector ( i , config . getRandomSeed ( ) ) ; } }


Input: Starts the intention selection threads . [CODESPLIT] static void startIntentionSelectionThreads ( ) { for ( int i = 0 ; i < Main . npools ; i ++ ) { Thread thread = new Thread ( Main . intentionSelectors [ i ] ) ; thread . setName ( "jill-" + i ) ; thread . start ( ) ; // start and wait at the entry barrier } }


Input: Stops the intention selection threads . [CODESPLIT] static void shutdownIntentionSelectionThreads ( ) { for ( int i = 0 ; i < Main . npools ; i ++ ) { Main . intentionSelectors [ i ] . shutdown ( ) ; } }


Input: Loads any configured extensions ( see { @link JillExtension } ) . [CODESPLIT] static boolean loadExtensions ( Config config ) { if ( config . getExtensions ( ) == null ) { return true ; } for ( Config . ExtensionData extensionData : config . getExtensions ( ) ) { JillExtension extension = ProgramLoader . loadExtension ( extensionData . getClassname ( ) ) ; if ( extension != null ) { Program . registerExtension ( extension ) ; extension . init ( extensionData . getArgs ( ) . toArray ( new String [ 0 ] ) ) ; } else { return false ; } } return true ; }


Input: Registers a new Jill extension . [CODESPLIT] public static void registerExtension ( JillExtension extension ) { if ( extension != null ) { GlobalState . eventHandlers . add ( extension ) ; Main . logger . info ( "Registered Jill extension: " + extension ) ; } else { Main . logger . warn ( "Cannot register null extension; will ignore." ) ; } }


Input: { [CODESPLIT] @ Override public void start ( PrintStream writer , String [ ] params ) { parse ( params ) ; out = writer ; // Create a new belief set about neighbours BeliefSetField [ ] fields = { new BeliefSetField ( "name" , String . class , true ) , } ; try { // Attach this belief set to this agent this . createBeliefSet ( beliefset , fields ) ; int numAgents = GlobalState . agents . size ( ) ; // Cannot have more neighbours than agents if ( neighbourhood >= numAgents ) { Log . error ( "Agent " + getName ( ) + " cannot add " + neighbourhood + " neighbours, when there are only " + numAgents + " agents all up" ) ; System . exit ( - 1 ) ; } // Add beliefs about neighbours for ( int i = 1 ; i <= neighbourhood ; i ++ ) { int neighbour = ( getId ( ) + i ) % numAgents ; this . addBelief ( beliefset , Integer . toString ( neighbour ) ) ; Log . debug ( "Agent " + getName ( ) + " added neighbour " + neighbour ) ; } Log . debug ( "Agent " + getName ( ) + " is initialising with neighbourhood size of " + neighbourhood + " on each side (so " + ( neighbourhood * 2 ) + " neighbours)" ) ; // Let Agent 0 start the token passing if ( getId ( ) == 0 ) { Log . debug ( "round 1" ) ; Token3 token = new Token3 ( 1 , 1 ) ; token . setHops ( 1 ) ; send ( 1 , token ) ; } } catch ( BeliefBaseException e ) { Log . error ( e . getMessage ( ) ) ; } }


Input: Parses the command line arguments . [CODESPLIT] public static void parse ( String [ ] args ) { for ( int i = 0 ; i < args . length ; i ++ ) { switch ( args [ i ] ) { case "-neighbourhood" : if ( i + 1 < args . length ) { i ++ ; try { neighbourhood = Integer . parseInt ( args [ i ] ) ; } catch ( NumberFormatException e ) { Log . warn ( "Value '" + args [ i ] + "' is not a number" ) ; } } break ; case "-rounds" : if ( i + 1 < args . length ) { i ++ ; try { rounds = Integer . parseInt ( args [ i ] ) ; } catch ( NumberFormatException e ) { Log . warn ( "Value '" + args [ i ] + "' is not a number" ) ; } } break ; default : // Ignore all other arguments break ; } } }


Input: Resets the global state . [CODESPLIT] public static void reset ( ) { agentTypes = new AObjectCatalog ( "agentTypes" , 5 , 5 ) ; goalTypes = new AObjectCatalog ( "goalTypes" , 10 , 5 ) ; planTypes = new AObjectCatalog ( "planTypes" , 20 , 5 ) ; agents = null ; beliefbase = null ; eventHandlers = new HashSet < JillExtension > ( ) ; }


Input: Creates a given number of agents of a given Class and adds the newly created agents to the given store . [CODESPLIT] public static boolean loadAgent ( String className , int num , AObjectCatalog agents ) { // Load the Agent class Class < ? > aclass = loadClass ( className , Agent . class ) ; if ( aclass == null ) { return false ; } // Save this agent type to the catalog of known agent types AgentType atype = new AgentType ( className ) ; atype . setAgentClass ( aclass ) ; GlobalState . agentTypes . push ( atype ) ; // Find the goals that this agent has String [ ] goals = getGoalsFromAgentInfoAnnotation ( aclass ) ; if ( goals . length == 0 ) { return false ; } // First pass: get the goals and their plans (flat goal-plan list) loadGoalPlanNodes ( atype , goals ) ; // Second pass: complete the goal-plan hierarchy completeGoalPlanHierarchy ( ) ; // Now create the specified number of instances of this agent type createAgentsInCatalog ( agents , atype , aclass , num ) ; // return success return true ; }


Input: Loads the given plan classes and sets up parent - child links with the given goal type . [CODESPLIT] private static boolean processPlansForGoal ( GoalType gtype , String [ ] plans ) { for ( int j = 0 ; j < plans . length ; j ++ ) { // Load the Plan class Class < ? > pclass = loadClass ( plans [ j ] , Plan . class ) ; if ( pclass == null ) { return false ; } // Found the plan class, so add this plan to the catalog of known plan types logger . info ( "Found Plan " + pclass . getName ( ) + " that handles Goal " + gtype . getName ( ) ) ; PlanType ptype = new PlanType ( pclass . getName ( ) ) ; ptype . setPlanClass ( pclass ) ; GlobalState . planTypes . push ( ptype ) ; // Set up the parent/child links between them (makings of a goal-plan tree) ptype . addParent ( ( byte ) gtype . getId ( ) ) ; gtype . addChild ( ( byte ) ptype . getId ( ) ) ; } return true ; }


Input: Completes the Goal - Plan hierarchy linkages between all { @link GlobalState#goalTypes } and { @link GlobalState#planTypes } . [CODESPLIT] private static boolean completeGoalPlanHierarchy ( ) { for ( int i = 0 ; i < GlobalState . planTypes . size ( ) ; i ++ ) { PlanType ptype = ( PlanType ) GlobalState . planTypes . get ( i ) ; String [ ] postsGoals = getGoalsFromPlanInfoAnnotation ( ptype . getPlanClass ( ) ) ; // A @PlanInfo is optional, and only present if this plan posts goals if ( postsGoals == null ) { continue ; } // But if @PlanInfo was given then it cannot be incomplete if ( postsGoals . length == 0 ) { return false ; } // All good, so find the goals that this plan posts and set up the Goal-Plan tree links for ( String goalname : postsGoals ) { GoalType gtype = ( GoalType ) GlobalState . goalTypes . find ( goalname ) ; if ( gtype == null ) { logger . error ( "Plan " + ptype . getName ( ) + " posts goal " + goalname + "which is not a known goal type." ) ; return false ; } // Found a goal posted by the plan, so setup the parent-child links ptype . addChild ( ( byte ) gtype . getId ( ) ) ; gtype . addParent ( ( byte ) ptype . getId ( ) ) ; } } return true ; }


Input: Creates the specified number of agent instances of the given type and adds them to the catalog . [CODESPLIT] private static void createAgentsInCatalog ( AObjectCatalog agents , AgentType atype , Class < ? > aclass , int num ) { int added = 0 ; try { for ( int i = 0 ; i < num ; i ++ ) { // Create a new instance (name prefix 'a' for agents) Agent agent = ( Agent ) ( aclass . getConstructor ( String . class ) . newInstance ( "a" + Integer . toString ( i ) ) ) ; // Assign the static goal plan tree hierarchy to this instance agent . setGoals ( atype . getGoals ( ) ) ; // Add this instance to the catalog of agent instances agents . push ( agent ) ; added ++ ; } logger . info ( "Finished loading {} agents" , added ) ; } catch ( NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e ) { logger . error ( "Could not create instance of class " + aclass . getName ( ) ) ; } }


Input: Gets the list of goals specified in the @AgentInfo annotation of the given agent class . [CODESPLIT] private static String [ ] getGoalsFromAgentInfoAnnotation ( Class < ? > aclass ) { // Find the goals that this agent has Annotation annotation = aclass . getAnnotation ( AgentInfo . class ) ; if ( annotation == null ) { logger . error ( "Agent " + aclass . getName ( ) + " is missing the " + "@AgentInfo(hasGoals={\"package.GoalClass1, package.GoalClass2, ...\"}) " + knowsNothing + "about this agent's goals and plans." ) ; return new String [ 0 ] ; } AgentInfo ainfo = ( AgentInfo ) annotation ; String [ ] goals = ainfo . hasGoals ( ) ; if ( goals . length == 0 ) { logger . error ( "Agent " + aclass . getName ( ) + " does not have any goals defined. Was expecting something like " + "@AgentInfo(hasGoals={\"package.GoalClass1, package.GoalClass2, ...\"}) " + knowsNothing + "about this agent's goals and plans." ) ; } return goals ; }


Input: Gets the list of plans specified in the @GoalInfo annotation of the given goal class . [CODESPLIT] private static String [ ] getPlansFromGoalsInfoAnnotation ( Class < ? > gclass ) { // Find the plans that this goal has Annotation annotation = gclass . getAnnotation ( GoalInfo . class ) ; if ( annotation == null ) { logger . error ( "Goal " + gclass . getName ( ) + " is missing the " + "@GoalInfo(hasPlans={\"package.PlanClass1, package.PlanClass2, ...\"}) " + knowsNothing + "about which plans can handle this goal." ) ; return new String [ 0 ] ; } GoalInfo ginfo = ( GoalInfo ) annotation ; String [ ] plans = ginfo . hasPlans ( ) ; if ( plans . length == 0 ) { logger . error ( "Goal " + gclass . getName ( ) + " does not have any plans defined. Was expecting something like " + "@GoalInfo(hasPlans={\"package.PlanClass1, package.PlanClass2, ...\"}) " + knowsNothing + "about which plans can handle this goal." ) ; } return plans ; }


Input: Gets the list of goals specified in the @PlanInfo annotation of the given plan class . [CODESPLIT] private static String [ ] getGoalsFromPlanInfoAnnotation ( Class < ? > pclass ) { Annotation annotation = pclass . getAnnotation ( PlanInfo . class ) ; PlanInfo pinfo = ( PlanInfo ) annotation ; // A @PlanInfo is optional, and only present if this plan posts goals if ( pinfo == null ) { return null ; } String [ ] postsGoals = pinfo . postsGoals ( ) ; if ( postsGoals . length == 0 ) { logger . error ( "Plan " + pclass . getName ( ) + " has incomplete " + "@PlanInfo(postsGoals={\"package.GoalClass1\", \"package.GoalClass2\", ...})) " + "annotation" ) ; } else { logger . info ( "Plan " + pclass . getName ( ) + " posts " + postsGoals . length + " goals" ) ; } return postsGoals ; }


Input: Loads the class of given name and type . [CODESPLIT] private static Class < ? > loadClass ( String className , Class < ? > classType ) { Class < ? > aclass = null ; try { aclass = Class . forName ( className ) ; } catch ( ClassNotFoundException e ) { logger . error ( "Class not found: " + className , e ) ; return null ; } if ( ! classType . isAssignableFrom ( aclass ) ) { logger . error ( "Class '" + className + "' is not of type " + classType . getName ( ) ) ; return null ; } logger . info ( "Found class " + className + " of type " + classType . getName ( ) ) ; return aclass ; }


Input: Loads a Jill extension . [CODESPLIT] public static JillExtension loadExtension ( String className ) { JillExtension extension = null ; Class < ? > eclass ; try { // Check that we have the extension class, else abort eclass = Class . forName ( className ) ; if ( ! JillExtension . class . isAssignableFrom ( eclass ) ) { logger . error ( "Class '" + className + "' does not implement " + JillExtension . class . getName ( ) ) ; return null ; } logger . info ( "Loading extension " + className ) ; extension = ( JillExtension ) ( eclass . newInstance ( ) ) ; } catch ( ClassNotFoundException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException e ) { logger . error ( "Could not load extension " + className , e ) ; } return extension ; }


Input: Checks if two objects have the same name . The check is case sensitive . [CODESPLIT] public static boolean isNameEqual ( AObject obj1 , AObject obj2 ) { // Not equal if the names are null, or empty, or not the same size if ( obj1 . name == null || obj2 . name == null || obj1 . name . length != obj2 . name . length || obj1 . name . length == 0 ) { return false ; } // Not equal if any name character is different for ( int i = 0 ; i < obj1 . name . length ; i ++ ) { if ( obj1 . name [ i ] != obj2 . name [ i ] ) { return false ; } } // Else equal return true ; }


Input: Returns a usage string for the Jill command line arguments . [CODESPLIT] public static String usage ( ) { return GlobalConstant . APP_HEADER + "\n\n" + "usage: " + Main . class . getName ( ) + "  [options] --agent-class <agentclass> --num-agents <numagents>" + "\n" + "   --config <string>                 load configuration from string" + "\n" + "   --configfile <file>               load configuration from file" + "\n" + "   --exit-on-idle <boolean>          forces system exit when all agents are " + "idle (default is '" + GlobalConstant . EXIT_ON_IDLE + "')\n" + "   --help                            print this usage message and exit \n" + "   --plan-selection-policy <policy>  policy for selecting from plan instances " + "(FIRST, RANDOM, or LAST (default is '" + GlobalConstant . PLAN_SELECTION_POLICY + "')\n" + "   --plan-instances-limit <number>   maximum number of applicable plan instances " + "to consider (default is '" + GlobalConstant . PLAN_INSTANCES_LIMIT + "')\n" ; }


Input: Parses the given command line arguments . [CODESPLIT] public static void parse ( String [ ] args ) { for ( int i = 0 ; args != null && i < args . length ; i ++ ) { // First parse args that don't require an option if ( "--help" . equals ( args [ i ] ) ) { abort ( null ) ; } // Now parse args that must be accompanied by an option if ( i + 1 < args . length ) { parseArgumentWithOption ( args [ i ] , args [ ++ i ] ) ; // force increment the counter } } // Abort if required args were not given if ( config == null ) { abort ( "Configuration file or string was not given" ) ; } else if ( config . getAgents ( ) == null || config . getAgents ( ) . isEmpty ( ) ) { abort ( "Configuration is missing agents specification" ) ; } }


Input: Parses the given command line argument and associated option . Will abort if an unrecoverable error occurs . [CODESPLIT] private static void parseArgumentWithOption ( String arg , String opt ) { switch ( arg ) { case "--config" : config = loadConfigFromString ( opt ) ; break ; case "--configfile" : config = loadConfigFromFile ( opt ) ; break ; case "--exit-on-idle" : GlobalConstant . EXIT_ON_IDLE = Boolean . parseBoolean ( opt ) ; break ; case "--plan-selection-policy" : try { GlobalConstant . PLAN_SELECTION_POLICY = GlobalConstant . PlanSelectionPolicy . valueOf ( opt ) ; } catch ( IllegalArgumentException e ) { abort ( "Unknown plan selection policy '" + opt + "'" ) ; } break ; case "--plan-instances-limit" : try { GlobalConstant . PLAN_INSTANCES_LIMIT = Integer . parseInt ( opt ) ; } catch ( NumberFormatException e ) { abort ( "Option value '" + opt + "' is not a number" ) ; } break ; default : // Ignore any other arguments (which may be used by components external to Jill) break ; } }


Input: Loads the Jill startup configuration object . <p > Configuration is specified at run time via one of the following two options : <ul > <li > { @code -- config <string > } < / li > <li > { @code -- configfile <file > } < / li > < / ul > The contents of { @code <string > } or { @code <file > } are parsed in exactly the same way . The expected syntax is JSON format . If both options are specified then last specified option will overrule . < / p > [CODESPLIT] static Config loadConfigFromString ( String str ) { Gson gson = new Gson ( ) ; Config config = null ; try { config = gson . fromJson ( str , Config . class ) ; } catch ( JsonSyntaxException e ) { abort ( "Invalid JSON syntax in " + str + ": " + e . getMessage ( ) ) ; } return config ; }


Input: Sample program to test belief base evaluation speeds . [CODESPLIT] public static void main ( String [ ] args ) throws BeliefBaseException { // Configure logging Log . createLogger ( "" , Level . INFO , "BeliefBase.log" ) ; // BeliefBase bb = new H2BeliefBase("jdbc:h2:mem:agents;CACHE_SIZE=1048576"); String bs1 = "neighbour" ; String bs2 = "hascar" ; long t0 ; long t1 ; int numAgents = 10000 ; int numNeighbours = 1000 ; BeliefBase bb = new ABeliefStore ( numAgents , 4 ) ; Log . info ( "Initialising " + numAgents + " agents with " + numNeighbours + " beliefs each" ) ; BeliefSetField [ ] fields1 = { new BeliefSetField ( "name" , String . class , true ) , new BeliefSetField ( "gender" , String . class , false ) , } ; BeliefSetField [ ] fields2 = { new BeliefSetField ( "name" , String . class , true ) , new BeliefSetField ( "car" , Boolean . class , false ) , } ; long t2 = System . currentTimeMillis ( ) ; for ( int i = 0 ; i < numAgents ; i ++ ) { t0 = System . currentTimeMillis ( ) ; bb . createBeliefSet ( i , bs1 , fields1 ) ; t1 = System . currentTimeMillis ( ) ; Log . debug ( "Created belief set '" + bs1 + "' " + Log . formattedDuration ( t0 , t1 ) ) ; t0 = System . currentTimeMillis ( ) ; for ( int j = 0 ; j < numNeighbours ; j ++ ) { bb . addBelief ( i , bs1 , "agent" + j , ( ( j % 2 ) == 0 ) ? "male" : "female" ) ; } t1 = System . currentTimeMillis ( ) ; Log . debug ( "Agent " + i + " added " + numNeighbours + " beliefs to belief set '" + bs1 + "' (" + ( t1 - t0 ) + " ms)" ) ; } long t3 = System . currentTimeMillis ( ) ; Log . info ( "Finished initialising " + numAgents + " agents with " + numNeighbours + " beliefs each for belief set '" + bs1 + "' " + Log . formattedDuration ( t2 , t3 ) ) ; t2 = System . currentTimeMillis ( ) ; for ( int i = 0 ; i < numAgents ; i ++ ) { t0 = System . currentTimeMillis ( ) ; bb . createBeliefSet ( i , bs2 , fields2 ) ; t1 = System . currentTimeMillis ( ) ; Log . debug ( "Created belief set '" + bs2 + "' " + Log . formattedDuration ( t0 , t1 ) ) ; t0 = System . currentTimeMillis ( ) ; for ( int j = 0 ; j < numNeighbours ; j ++ ) { bb . addBelief ( i , bs2 , "agent" + j , ( ( j % 2 ) == 0 ) ? true : false ) ; } t1 = System . currentTimeMillis ( ) ; Log . debug ( "Agent " + i + " added " + numNeighbours + " beliefs to belief set '" + bs2 + "' (" + ( t1 - t0 ) + " ms)" ) ; } t3 = System . currentTimeMillis ( ) ; Log . info ( "Finished initialising " + numAgents + " agents with " + numNeighbours + " beliefs each for belief set '" + bs2 + "' " + Log . formattedDuration ( t2 , t3 ) ) ; final String opstr = ".name=agent" ; int agentId = 0 ; int neighbourId = 0 ; doEval ( bb , agentId , bs1 + opstr + neighbourId ) ; agentId = 0 ; neighbourId = numNeighbours - 1 ; doEval ( bb , agentId , bs1 + opstr + neighbourId ) ; agentId = numAgents - 1 ; neighbourId = numNeighbours - 1 ; doEval ( bb , agentId , bs1 + opstr + neighbourId ) ; agentId = 0 ; neighbourId = 0 ; doEval ( bb , agentId , bs1 + opstr + neighbourId ) ; agentId = 0 ; neighbourId = numNeighbours - 1 ; doEval ( bb , agentId , bs1 + opstr + neighbourId ) ; agentId = numAgents - 1 ; neighbourId = numNeighbours - 1 ; doEval ( bb , agentId , bs1 + opstr + neighbourId ) ; }


Input: Evaluates the given query on the given belief base for the agent . [CODESPLIT] public static void doEval ( BeliefBase bb , int agentId , String query ) throws BeliefBaseException { final long t0 = System . currentTimeMillis ( ) ; bb . eval ( agentId , query ) ; final long t1 = System . currentTimeMillis ( ) ; Log . info ( "Agent " + agentId + " searched for '" + query + "' " + Log . formattedDuration ( t0 , t1 ) ) ; }


Input: Gets the object at the given index of the catalog . [CODESPLIT] public AObject get ( int index ) { if ( index >= 0 && index < objects . length ) { return objects [ index ] ; } return null ; }


Input: Find an object by name . Can be very expensive for large catalogs since a name comparison is performed in sequence on the objects in the catalog until a match is found . Search is case sensitive . [CODESPLIT] public AObject find ( String name ) { for ( int i = 0 ; i < nextid ; i ++ ) { if ( objects [ i ] . getName ( ) . equals ( name ) ) { return objects [ i ] ; } } return null ; }


Input: Pushes a new object to the top of the catalog . [CODESPLIT] public void push ( AObject obj ) { if ( obj == null || obj . getId ( ) != GlobalConstant . NULLID ) { return ; } // Grow if we are at capacity if ( nextid == objects . length ) { grow ( ) ; } obj . setId ( nextid ) ; objects [ nextid ++ ] = obj ; }


Input: Pops ( removes ) the object at the top of the catalog . [CODESPLIT] public AObject pop ( ) { if ( nextid > GlobalConstant . NULLID ) { nextid -- ; AObject obj = objects [ nextid ] ; objects [ nextid ] = null ; return obj ; } return null ; }


Input: Grows the Catalog by a factor of { [CODESPLIT] private void grow ( ) { AObject [ ] temp = new AObject [ objects . length + increment ] ; System . arraycopy ( objects , 0 , temp , 0 , objects . length ) ; objects = temp ; }


Input: { [CODESPLIT] @ Override public boolean context ( ) { Agent agent = getAgent ( ) ; int myid = agent . getId ( ) ; int goalid = ( ( Token3 ) getGoal ( ) ) . getAgent ( ) ; try { return ( myid == goalid ) && agent . eval ( "neighbour.name = *" ) ; } catch ( BeliefBaseException e ) { Log . error ( e . getMessage ( ) ) ; } return false ; }


Input: { [CODESPLIT] @ Override public void setPlanVariables ( Map < String , Object > vars ) { for ( String attribute : vars . keySet ( ) ) { if ( "name" . equals ( attribute ) ) { neighbour = ( String ) ( vars . get ( attribute ) ) ; } } }


Input: Gets the object at the given index in the catalog . [CODESPLIT] public Object get ( int idx ) { int index = idx & 0xff ; if ( isEmpty ( ) ) { // System.err.println("index "+index+" is invalid as stack is empty"); return null ; } else if ( index < 0 || index >= size ) { // System.err.println("index "+index+" is outside of range [0,"+(size-1)+"]"); return null ; } return objects [ index ] ; }


Input: Pushes an object on to the top of the stack . [CODESPLIT] public boolean push ( Object obj ) { // Cannot add beyond maximum capacity if ( isFull ( ) ) { return false ; } // Grow if we are at capacity if ( size == objects . length ) { grow ( ) ; } objects [ size ++ ] = obj ; return true ; }


Input: Pops the Object at the top of the stack . [CODESPLIT] public Object pop ( ) { if ( isEmpty ( ) ) { return null ; } size -- ; Object obj = objects [ size ] ; objects [ size ] = null ; return obj ; }


Input: Grows the stack capacity by { @link #increment } up to the maximum capacity of 255 ( byte size ) . [CODESPLIT] private boolean grow ( ) { if ( objects . length == MAXIMUM_CAPACITY ) { // Cannot grow beyond the maximum capacity return false ; } int newsize = objects . length + increment ; if ( newsize > MAXIMUM_CAPACITY ) { newsize = MAXIMUM_CAPACITY ; } Object [ ] temp = new Object [ newsize ] ; System . arraycopy ( objects , 0 , temp , 0 , objects . length ) ; objects = temp ; return true ; }


Input: { [CODESPLIT] @ Override public void start ( PrintStream writer , String [ ] params ) { out = writer ; // Parse the arguments parse ( params ) ; // Create the board board = new Board ( ndiscs ) ; out . println ( "Initialised hanoi board with " + ndiscs + " discs:" ) ; out . println ( board . toString ( ) ) ; // Solve the board post ( new Solve ( "s" , ndiscs , 0 , 2 , 1 ) ) ; }


Input: { [CODESPLIT] @ Override public boolean createBeliefSet ( int agentid , String name , BeliefSetField [ ] fields ) throws BeliefBaseException { if ( beliefsets . containsKey ( name ) ) { return false ; } // Add the beliefset to the list of beliefsets BeliefSet bs = new BeliefSet ( beliefsets . size ( ) , name , fields ) ; beliefsets . put ( name , bs ) ; beliefsetsByID . put ( bs . getId ( ) , bs ) ; return true ; }


Input: { [CODESPLIT] @ Override public boolean addBelief ( int agentid , String beliefsetName , Object ... tuple ) throws BeliefBaseException { // Check that the beliefset exists if ( ! beliefsets . containsKey ( beliefsetName ) ) { throw new BeliefBaseException ( "Belief set '" + beliefsetName + "' does not exist" ) ; } // Create a new Belief Belief belief = new Belief ( beliefs . size ( ) , beliefsets . get ( beliefsetName ) . getId ( ) , tuple ) ; // Add it to the list of beliefs int id ; if ( ! beliefs . containsKey ( belief ) ) { id = beliefs . size ( ) ; beliefs . put ( belief , id ) ; beliefsByID . put ( belief . getId ( ) , belief ) ; } else { id = beliefs . get ( belief ) ; } // Add it to the agents beliefs SparseBitSet bits = agents2beliefs [ agentid ] ; if ( bits == null ) { bits = new SparseBitSet ( ) ; } bits . set ( id ) ; agents2beliefs [ agentid ] = bits ; // Update the cached results for ( String query : cachedresults . keySet ( ) ) { Set < Belief > results = cachedresults . get ( query ) ; if ( match ( belief , queries . get ( query ) ) ) { results . add ( belief ) ; } } return true ; }


Input: { [CODESPLIT] @ Override public boolean eval ( int agentid , String key ) throws BeliefBaseException { return ! query ( agentid , key ) . isEmpty ( ) ; }


Input: { [CODESPLIT] @ Override public Set < Belief > query ( int agentid , String key ) throws BeliefBaseException { // Get the cached query if we have seen it before, else parse it AQuery query = null ; if ( queries . containsKey ( key ) ) { query = queries . get ( key ) ; } else { // Valid queries have the following syntax // beliefset.field OP value // where OP is one of =, !=, <, or > if ( key == null ) { throw new BeliefBaseException ( logsuffix ( agentid ) + "'null' query" ) ; } Pattern pattern = Pattern . compile ( "(\\w+)\\.(\\w+)\\s*([=<>(!=)])\\s*(.+)" ) ; Matcher matcher = pattern . matcher ( key ) ; if ( ! matcher . matches ( ) ) { throw new BeliefBaseException ( logsuffix ( agentid ) + "invalid query '" + key + "' : syntax not of the form beliefset.field <op> value" ) ; } String strBeliefset = matcher . group ( 1 ) ; String strField = matcher . group ( 2 ) ; String strOp = matcher . group ( 3 ) ; String strVal = matcher . group ( 4 ) ; try { query = parseQuery ( agentid , strBeliefset , strField , strOp , strVal ) ; queries . put ( key , query ) ; } catch ( BeliefBaseException e ) { throw new BeliefBaseException ( logsuffix ( agentid ) + "could not parse query: " + key , e ) ; } } // Get the cached results if they exist, // else perform the query and cache the results Set < Belief > results = null ; if ( cachedresults . containsKey ( key ) ) { results = cachedresults . get ( key ) ; } else { results = performQuery ( query , beliefs ) ; cachedresults . put ( key , results ) ; } // Finally, filter the results for this agent Set < Belief > matches = filterResultsForAgent ( agentid , results ) ; Log . debug ( "Agent " + agentid + " found " + matches . size ( ) + " matches for the query" ) ; return matches ; }


Input: Gets the type of the given object . [CODESPLIT] public static String getType ( Object obj ) { if ( obj == null ) { return null ; } String type = null ; if ( obj instanceof String || obj instanceof Integer || obj instanceof Double || obj instanceof Boolean ) { type = obj . getClass ( ) . getName ( ) ; } return type ; }


Input: Checks if the given query run on the given belief returns a match . [CODESPLIT] private static boolean match ( Belief belief , AQuery query ) { assert ( belief != null ) ; assert ( query != null ) ; if ( belief . getBeliefset ( ) != query . getBeliefset ( ) ) { return false ; } switch ( query . getOp ( ) ) { case EQ : Object lhs = belief . getTuple ( ) [ query . getField ( ) ] ; Object rhs = query . getValue ( ) ; // Match wildcard or exact string return "*" . equals ( rhs ) || lhs . equals ( rhs ) ; case GT : // TODO: Handle Operator.GT case LT : // TODO: Handle Operator.LT default : break ; } return false ; }


Input: Sample program to test pattern matching . [CODESPLIT] public static void main ( String [ ] args ) throws BeliefBaseException { BeliefBase bb = new ABeliefStore ( 100 , 4 ) ; bb . eval ( 0 , "neighbour.age < 31" ) ; Console console = System . console ( ) ; if ( console == null ) { System . err . println ( "No console." ) ; System . exit ( 1 ) ; } while ( true ) { Pattern pattern = Pattern . compile ( console . readLine ( "%nEnter your regex: " ) ) ; Matcher matcher = pattern . matcher ( console . readLine ( "Enter input string to search: " ) ) ; boolean found = false ; while ( matcher . find ( ) ) { console . format ( "I found the text" + " \"%s\" starting at " + "index %d and ending at index %d.%n" , matcher . group ( ) , matcher . start ( ) , matcher . end ( ) ) ; found = true ; } if ( ! found ) { console . format ( "No match found.%n" ) ; } } }


Input: Gets the belief set field name ( see { @link io . github . agentsoz . jill . core . beliefbase . BeliefSetField } ) for the given belief set for the given agent . [CODESPLIT] public static String getFieldName ( int agentid , int beliefset , int index ) throws BeliefBaseException { if ( beliefset < 0 || beliefset > beliefsets . size ( ) ) { throw new BeliefBaseException ( "belief set id " + beliefset + " is invalid" ) ; } BeliefSetField [ ] bsf = beliefsetsByID . get ( beliefset ) . getFields ( ) ; if ( index < 0 || index >= bsf . length ) { throw new BeliefBaseException ( "belief set field id " + index + " is invalid" ) ; } return bsf [ index ] . getName ( ) ; }


Input: Encodes the String str into a sequence of bytes using the character set specified in CHARSET storing the result into a new byte array . [CODESPLIT] public static byte [ ] toBytes ( String str ) { if ( str == null ) { return new byte [ 0 ] ; } byte [ ] val = null ; try { val = str . getBytes ( CHARSET ) ; } catch ( UnsupportedEncodingException e ) { // NOPMD - ignore empty catch // Can never occur since CHARSET is correct and final } return val ; }


Input: Push the given goal to the given stack . [CODESPLIT] private void post ( Stack255 stack , Goal goal ) { synchronized ( stack ) { logger . debug ( "{} posting goal {}" , Log . logPrefix ( getId ( ) ) , goal . getClass ( ) . getSimpleName ( ) ) ; stack . push ( goal ) ; Main . setAgentIdle ( getId ( ) , false ) ; } Main . flagMessageTo ( Main . poolid ( getId ( ) ) ) ; }


Input: Send a message to an agent . [CODESPLIT] public boolean send ( int id , Goal msg ) { AObject obj = agents . get ( id ) ; if ( obj == null ) { logger . warn ( "{} attempted to send a message to unknown agent id '{}'" , Log . logPrefix ( getId ( ) ) , id ) ; return false ; } logger . debug ( "{} is sending message of type {} to agent {}" , Log . logPrefix ( getId ( ) ) , msg . getClass ( ) . getSimpleName ( ) , id ) ; ( ( Agent ) obj ) . post ( msg ) ; return true ; }


Input: Send a message to this agent . [CODESPLIT] public boolean send ( String name , Goal msg ) { AObject obj = agents . find ( name ) ; if ( obj == null ) { logger . warn ( "{} attempted to send a message to unknown agent '{}'" , Log . logPrefix ( getId ( ) ) , name ) ; return false ; } ( ( Agent ) obj ) . post ( msg ) ; return true ; }


Input: <p > start . < / p > [CODESPLIT] public void start ( PrintStream writer , String [ ] params ) { logger . debug ( "{} is starting" , Log . logPrefix ( getId ( ) ) ) ; }


Input: Returns this agent s top level goals . [CODESPLIT] public byte [ ] getGoals ( ) { byte [ ] arr = new byte [ goals . length ] ; System . arraycopy ( goals , 0 , arr , 0 , arr . length ) ; return arr ; }


Input: Set s this agent s top level goals i . e . { @link #goals } . [CODESPLIT] public void setGoals ( byte [ ] bs ) { goals = new byte [ bs . length ] ; System . arraycopy ( bs , 0 , goals , 0 , goals . length ) ; }


Input: Creates a new belief set with the given fields . [CODESPLIT] public void createBeliefSet ( String name , BeliefSetField [ ] fields ) throws BeliefBaseException { beliefbase . createBeliefSet ( getId ( ) , name , fields ) ; }


Input: Adds a new belief to the specified belief set . [CODESPLIT] public void addBelief ( String beliefsetName , Object ... tuple ) throws BeliefBaseException { beliefbase . addBelief ( getId ( ) , beliefsetName , tuple ) ; }


Input: Evaluates the given query against this agent s belief base . [CODESPLIT] public boolean eval ( String query ) throws BeliefBaseException { boolean result = beliefbase . eval ( getId ( ) , query ) ; lastresult = ( result ) ? beliefbase . query ( getId ( ) , query ) : new HashSet < Belief > ( ) ; return result ; }


Input: Forces this agent to enter an idle state irrespective of whether it has any active intentions or not . The agent will continue to remain in the suspected state until some event forces it to become active again at which point it will resume operation . [CODESPLIT] public void suspend ( boolean val ) { Main . setAgentIdle ( getId ( ) , val ) ; Main . flagMessageTo ( Main . poolid ( getId ( ) ) ) ; }


Input: { [CODESPLIT] @ Override public boolean context ( ) { try { return getAgent ( ) . eval ( "neighbour.gender = male" ) ; } catch ( BeliefBaseException e ) { Log . error ( e . getMessage ( ) ) ; } return false ; }


Input: Gets the field of this belief set that has the given name . [CODESPLIT] public BeliefSetField getFieldByName ( String name ) { BeliefSetField field = null ; for ( int i = 0 ; i < fields . length ; i ++ ) { if ( name . equals ( fields [ i ] . getName ( ) ) ) { field = fields [ i ] ; break ; } } return field ; }


Input: Gets the index ( column ) of the given field in this belief set . [CODESPLIT] public int getIndex ( BeliefSetField field ) { int index = - 1 ; for ( int i = 0 ; i < fields . length ; i ++ ) { if ( field . equals ( fields [ i ] ) ) { index = i ; } } return index ; }


Input: { [CODESPLIT] @ Override public void start ( PrintStream writer , String [ ] params ) { parse ( params ) ; out = writer ; if ( getId ( ) == 0 ) { Log . debug ( "round 1" ) ; send ( 1 , new Token2 ( 1 , 1 ) ) ; } }


Input: Parses the command line arguments . [CODESPLIT] public static void parse ( String [ ] args ) { for ( int i = 0 ; i < args . length ; i ++ ) { if ( "-rounds" . equals ( args [ i ] ) && i + 1 < args . length ) { i ++ ; try { rounds = Integer . parseInt ( args [ i ] ) ; } catch ( NumberFormatException e ) { Log . warn ( "Value '" + args [ i ] + "' is not a number" ) ; } } } }


Input: { [CODESPLIT] @ Override public void start ( PrintStream writer , String [ ] params ) { // Parse the arguments parse ( params ) ; // Create a new belief set about neighbours BeliefSetField [ ] fields = { new BeliefSetField ( "name" , String . class , true ) , new BeliefSetField ( "gender" , String . class , false ) , } ; try { // Attach this belief set to this agent this . createBeliefSet ( beliefset , fields ) ; // Add beliefs about neighbours registerNeighbours ( rand , numNeighbours ) ; Log . debug ( "Agent " + getName ( ) + " is initialising with " + numNeighbours + " neighbours" ) ; // Post the goal to be friendly post ( new BeFriendly ( "BeFriendly" ) ) ; } catch ( BeliefBaseException e ) { Log . error ( e . getMessage ( ) ) ; } }


Input: Helper function to add beliefs about neighbours . [CODESPLIT] private void registerNeighbours ( Random rand , int count ) throws BeliefBaseException { int size = ( count < 0 ) ? 0 : count ; for ( int i = 0 ; i < size ; i ++ ) { boolean male = ( rand . nextDouble ( ) < 0.5 ) ? true : false ; this . addBelief ( beliefset , buildName ( male ) , male ? "male" : "female" ) ; } }


Input: Builds a new name . [CODESPLIT] private static String buildName ( boolean male ) { StringBuilder name = new StringBuilder ( ) ; name . append ( male ? males [ rand . nextInt ( males . length ) ] : females [ rand . nextInt ( females . length ) ] ) . append ( ' ' ) . append ( middle [ rand . nextInt ( middle . length ) ] ) . append ( ' ' ) . append ( surnames [ rand . nextInt ( surnames . length ) ] ) ; return name . toString ( ) ; }


Input: Parses the command line arguments . [CODESPLIT] public static void parse ( String [ ] args ) { for ( int i = 0 ; i < args . length ; i ++ ) { switch ( args [ i ] ) { case "-seed" : if ( i + 1 < args . length ) { i ++ ; int seed = 0 ; try { seed = Integer . parseInt ( args [ i ] ) ; rand = new Random ( seed ) ; } catch ( NumberFormatException e ) { Log . warn ( "Seed value '" + args [ i ] + "' is not a number" ) ; } } break ; case "-neighbourhoodSize" : if ( i + 1 < args . length ) { i ++ ; try { numNeighbours = Integer . parseInt ( args [ i ] ) ; } catch ( NumberFormatException e ) { Log . warn ( "Neighbourhood size value '" + args [ i ] + "' is not a number" ) ; } } break ; default : // Ignore any other arguments break ; } } }


Input: Runs this intentions selction thread . [CODESPLIT] public void run ( ) { Set < Integer > toRemove = new HashSet < Integer > ( ) ; do { boolean idle = true ; // Remove agents that have have become idle due to an external event removeInactiveAgents ( ) ; // Add agents that have have become active due to an external event addActiveAgents ( ) ; for ( Integer i : activeAgents ) { Agent agent = ( Agent ) GlobalState . agents . get ( i ) ; Stack255 agentExecutionStack = ( Stack255 ) ( agent ) . getExecutionStack ( ) ; if ( ! isStackValid ( agent , agentExecutionStack ) ) { // Mark this agent for removal toRemove . add ( i ) ; continue ; } // At least one agent is active idle = false ; // Get the item at the top of the stack Object node = ( Object ) agentExecutionStack . get ( ( byte ) ( agentExecutionStack . size ( ) - 1 ) ) ; if ( node instanceof Plan ) { // If it is a plan then execute a plan step; and if it finished then remove it managePlan ( i , agentExecutionStack , ( Plan ) node , toRemove ) ; } else if ( node instanceof Goal ) { // If it is a goal then find a plan for it and put it on the stack manageGoal ( i , agent , agentExecutionStack , ( Goal ) node ) ; } agent . nextActiveStack ( ) ; // select the next active stack for next time } // remove agents that have finished executing plans and have gone idle in this cycle removeFinishedAgents ( toRemove ) ; if ( idle ) { waitOnExternalMessage ( ) ; if ( shutdown ) { break ; } } } while ( true ) ; logger . debug ( "Pool {} is exiting" , poolid ) ; }


Input: Checks if this agent s execution stack is valid . The stack is valid if it is not null or empty and has not exceeded the maximum size limit of 255 . [CODESPLIT] private boolean isStackValid ( Agent agent , Stack255 agentExecutionStack ) { if ( agentExecutionStack == null ) { return false ; } final int esSize = agentExecutionStack . size ( ) ; logger . trace ( "{} execution stack is {}/255 full" , Log . logPrefix ( agent . getId ( ) ) , esSize ) ; if ( esSize == 0 ) { return false ; } if ( esSize >= 255 ) { logger . error ( "{} execution stack reached size limit of 255. Cannot continue." , Log . logPrefix ( agent . getId ( ) ) ) ; return false ; } return true ; }


Input: Removes the given list of agents from the list of active agents . [CODESPLIT] private void removeFinishedAgents ( Set < Integer > toRemove ) { if ( ! toRemove . isEmpty ( ) ) { for ( int i : toRemove ) { activeAgents . remove ( i ) ; } toRemove . clear ( ) ; } }


Input: Manages the goal at the top of the execution stack of an agent . All relevant plans are evaluated to see if their context conditions hold . Plans deemed applicable are then added to the list of bindings from which a plan instane will be eventually selected . [CODESPLIT] private boolean manageGoal ( int agentIndex , Agent agent , Stack255 agentExecutionStack , Goal node ) { // Get the goal type for this goal GoalType gtype = ( GoalType ) GlobalState . goalTypes . find ( node . getClass ( ) . getName ( ) ) ; byte [ ] ptypes = gtype . getChildren ( ) ; assert ( ptypes != null ) ; // Clear any previous plan bindings before adding any new ones bindings . clear ( ) ; for ( int p = 0 ; p < ptypes . length ; p ++ ) { PlanType ptype = ( PlanType ) GlobalState . planTypes . get ( ptypes [ p ] ) ; try { // Create an object of this Plan type, so we can // access its context condition Plan planInstance = ( Plan ) ( ptype . getPlanClass ( ) . getConstructor ( Agent . class , Goal . class , String . class ) . newInstance ( GlobalState . agents . get ( agentIndex ) , node , "p" ) ) ; // Clear previously buffered context results if any agent . clearLastResults ( ) ; // Evaluate the context condition if ( planInstance . context ( ) ) { // Get the results of context query just performed Set < Belief > results = agent . getLastResults ( ) ; // Add the results to the bindings bindings . add ( planInstance , ( results == null ) ? null : new LinkedHashSet < Belief > ( results ) ) ; } } catch ( NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e ) { logger . error ( "Could not create plan object of type " + ptype . getClass ( ) . getName ( ) , e ) ; } } int numBindings = bindings . size ( ) ; if ( numBindings == 0 ) { // No plan options for this goal at this point in time, so move to the next agent logger . debug ( Log . logPrefix ( agent . getId ( ) ) + " has no applicable plans for goal " + gtype + " and will continue to wait indefinitely" ) ; return false ; } // Call the meta-level planning prior to plan selection agent . notifyAgentPrePlanSelection ( bindings ) ; // Pick a plan option using specified policy Plan planInstance = bindings . selectPlan ( GlobalConstant . PLAN_SELECTION_POLICY ) ; // Now push the plan on to the intention stack synchronized ( agentExecutionStack ) { logger . debug ( Log . logPrefix ( agent . getId ( ) ) + " choose an instance of plan " + planInstance . getClass ( ) . getSimpleName ( ) + " to handle goal " + node . getClass ( ) . getSimpleName ( ) ) ; agentExecutionStack . push ( planInstance ) ; } return true ; }


Input: Manages the plan at the top of this agent s execution stack . If the plan has finished it is removed else it is progresses by a single { @link PlanStep } . [CODESPLIT] private void managePlan ( int agentIndex , Stack255 agentExecutionStack , Plan node , Set < Integer > toRemove ) { // If done then pop this plan/goal if ( node . hasfinished ( ) ) { logger . debug ( Log . logPrefix ( agentIndex ) + " finished executing plan " + node . getClass ( ) . getSimpleName ( ) ) ; synchronized ( agentExecutionStack ) { // Pop the plan off the stack agentExecutionStack . pop ( ) ; // Pop the goal off the stack agentExecutionStack . pop ( ) ; if ( agentExecutionStack . isEmpty ( ) ) { // remove empty intention stacks Agent agent = ( Agent ) GlobalState . agents . get ( agentIndex ) ; int size = agent . cleanupStacks ( ) ; // If we are left with only one stack and that is empty, then agent is idle if ( size == 1 && agent . getExecutionStack ( ) . isEmpty ( ) ) { // Mark this agent as idle // Main.setAgentIdle(i, true); toRemove . add ( agentIndex ) ; } } } } else { logger . debug ( Log . logPrefix ( agentIndex ) + " is executing a step of plan " + node . getClass ( ) . getSimpleName ( ) ) ; node . step ( ) ; } }


Input: Removes from { [CODESPLIT] private void removeInactiveAgents ( ) { synchronized ( extToRemove ) { if ( ! extToRemove . isEmpty ( ) ) { for ( int i : extToRemove ) { activeAgents . remove ( i ) ; } extToRemove . clear ( ) ; } } }


Input: Adds to { [CODESPLIT] private void addActiveAgents ( ) { synchronized ( extToAdd ) { if ( ! extToAdd . isEmpty ( ) ) { for ( int i : extToAdd ) { activeAgents . add ( i ) ; } extToAdd . clear ( ) ; } } }


Input: Waits on { [CODESPLIT] private void waitOnExternalMessage ( ) { synchronized ( lock ) { while ( ! hasMessage ) { try { logger . debug ( "Pool {} is idle; will wait on external message" , poolid ) ; // Main.incrementPoolsIdle(); isIdle = true ; Main . flagPoolIdle ( ) ; lock . wait ( ) ; isIdle = false ; // Main.decrementPoolsIdle(); logger . debug ( "Pool {} just woke up on external message" , poolid ) ; } catch ( InterruptedException e ) { logger . error ( "Pool " + poolid + " failed to wait on external message: " , e ) ; } } hasMessage = false ; } }


Input: Terminates this intention selector thread . [CODESPLIT] public void shutdown ( ) { synchronized ( lock ) { logger . debug ( "Pool {} received shutdown message" , poolid ) ; shutdown = true ; hasMessage = true ; lock . notify ( ) ; // NOPMD - ignore notifyall() warning } }


Input: and this thread is still iterating over activeagents [CODESPLIT] public void setAgentIdle ( int agentId , boolean idle ) { // If agent is becoming active, and not already active if ( ! idle /* && !activeAgents.contains(agentId) */ ) { synchronized ( extToAdd ) { extToAdd . add ( agentId ) ; } } // If agent is becoming idle, and not already idle if ( idle /* && activeAgents.contains(agentId) */ ) { synchronized ( extToRemove ) { extToRemove . add ( agentId ) ; } } }


Input: Move a disc from pin A to pin B . [CODESPLIT] public boolean move ( int pinA , int pinB ) { // Nothing to do if the pin number is invalid if ( pinA < 0 || pinA >= pins . length || pinB < 0 || pinB >= pins . length ) { Log . warn ( "Invalid board pin specified " + pinA + ". Should be between 0.." + ( pins . length - 1 ) + " (inclusive)." ) ; return false ; } else if ( pins [ pinA ] . isEmpty ( ) ) { Log . warn ( "No disc on pin" + pinA ) ; return false ; } else if ( pinA == pinB ) { Log . info ( "Moving disc from pin" + pinA + " on to itself (means the board will not change)" ) ; return true ; } int discOnA = pins [ pinA ] . get ( pins [ pinA ] . size ( ) - 1 ) ; int discOnB = ( pins [ pinB ] . isEmpty ( ) ) ? Integer . MAX_VALUE : pins [ pinB ] . get ( pins [ pinB ] . size ( ) - 1 ) ; if ( discOnB < discOnA ) { Log . warn ( "Cannot move disc" + discOnA + " (pin" + pinA + ") on to smaller disc" + discOnB + " (pin" + pinB + ")" ) ; return false ; } pins [ pinB ] . add ( pins [ pinA ] . remove ( pins [ pinA ] . size ( ) - 1 ) ) ; return true ; }


Input: Program entry [CODESPLIT] public static void main ( String [ ] args ) { // Parse the command line options ArgumentsLoader . parse ( args ) ; // Load the configuration Config config = ArgumentsLoader . getConfig ( ) ; // Initialise the system with the given arguments if ( ! init ( config ) ) { return ; } // load all extensions if ( ! Program . loadExtensions ( config ) ) { return ; } // Start the engine start ( config ) ; // Wait until the agents become idle waitUntilIdle ( ) ; // finish up finish ( ) ; }


Input: Initialises the Jill engine . [CODESPLIT] public static boolean init ( Config config ) { // Pause for key press from user if requested if ( config . isDoPauseForUserInput ( ) ) { Program . pauseForUserInput ( ) ; } // Configure logging Log . createLogger ( Main . LOGGER_NAME , config . getLogLevel ( ) , config . getLogFile ( ) ) ; logger = LoggerFactory . getLogger ( Main . LOGGER_NAME ) ; int numAgents = 0 ; for ( Config . AgentTypeData agentType : config . getAgents ( ) ) { numAgents += agentType . getCount ( ) ; } final int increment = 10000 ; GlobalState . reset ( ) ; GlobalState . agents = new AObjectCatalog ( "agents" , numAgents , increment ) ; // Create the central belief base GlobalState . beliefbase = new ABeliefStore ( numAgents , config . getNumThreads ( ) ) ; long t0 ; // Create the agents t0 = System . currentTimeMillis ( ) ; for ( Config . AgentTypeData agentType : config . getAgents ( ) ) { if ( ! ProgramLoader . loadAgent ( agentType . getClassname ( ) , agentType . getCount ( ) , GlobalState . agents ) ) { // return unsuccessful return false ; } } long t1 = System . currentTimeMillis ( ) ; logger . info ( "Created " + GlobalState . agents . size ( ) + agentsIn + Log . formattedDuration ( t0 , t1 ) ) ; // Initialise the thread pools Program . initIntentionSelectionPools ( numAgents , config . getNumThreads ( ) ) ; // Redirect the agent program output if specified if ( config . getProgramOutputFile ( ) != null ) { try { writer = new PrintStream ( config . getProgramOutputFile ( ) , "UTF-8" ) ; } catch ( FileNotFoundException | UnsupportedEncodingException e ) { logger . error ( "Could not open program outout file " + config . getProgramOutputFile ( ) , e ) ; } } else { writer = System . out ; } // Initialise the intention selection threads Program . initIntentionSelectionThreads ( config ) ; // return success return true ; }


Input: Starts the Jill engine . Must have previously been initialised ( see { @link #init ( Config ) } ) . [CODESPLIT] public static void start ( Config config ) { // Start the agents long t0 = System . currentTimeMillis ( ) ; int index = 0 ; int subIndex = 0 ; for ( Config . AgentTypeData agentType : config . getAgents ( ) ) { index = subIndex ; String [ ] args = ( agentType . getArgs ( ) == null || agentType . getArgs ( ) . isEmpty ( ) ) ? new String [ 0 ] : agentType . getArgs ( ) . toArray ( new String [ agentType . getArgs ( ) . size ( ) ] ) ; for ( subIndex = index ; subIndex < index + agentType . getCount ( ) ; subIndex ++ ) { // Get the agent Agent agent = ( Agent ) GlobalState . agents . get ( subIndex ) ; // Start the agent agent . start ( writer , args ) ; } } long t1 = System . currentTimeMillis ( ) ; logger . info ( "Started " + GlobalState . agents . size ( ) + agentsIn + Log . formattedDuration ( t0 , t1 ) ) ; // Start the intention selection threads Program . startIntentionSelectionThreads ( ) ; }


Input: Blocks until all agents have finished executing plans and have gone idle . [CODESPLIT] public static void waitUntilIdle ( ) { // Wait till we are all done long t0 = System . currentTimeMillis ( ) ; synchronized ( poolsIdle ) { while ( ! arePoolsIdle ( ) ) { try { poolsIdle . wait ( ) ; } catch ( InterruptedException e ) { logger . error ( "Failed to wait on termination condition: " + e . getMessage ( ) ) ; } } } long t1 = System . currentTimeMillis ( ) ; logger . info ( "Finished running " + GlobalState . agents . size ( ) + agentsIn + Log . formattedDuration ( t0 , t1 ) ) ; }


Input: Termiantes the Jill engine . [CODESPLIT] public static void finish ( ) { // Terminate the extensions first for ( JillExtension extension : GlobalState . eventHandlers ) { extension . finish ( ) ; } // Now shut down the threads Program . shutdownIntentionSelectionThreads ( ) ; // Finish the agents long t0 = System . currentTimeMillis ( ) ; for ( int i = 0 ; i < GlobalState . agents . size ( ) ; i ++ ) { // Get the agent Agent agent = ( Agent ) GlobalState . agents . get ( i ) ; // Terminate the agent agent . finish ( ) ; } // Close the writer if ( writer != null ) { writer . close ( ) ; } long t1 = System . currentTimeMillis ( ) ; logger . info ( "Terminated " + GlobalState . agents . size ( ) + agentsIn + Log . formattedDuration ( t0 , t1 ) ) ; }


Input: Checks if the system is idle i . e . all the agents pools are idle [CODESPLIT] public static boolean arePoolsIdle ( ) { boolean idle = true ; for ( int i = 0 ; i < npools ; i ++ ) { idle &= ( intentionSelectors [ i ] == null ) || intentionSelectors [ i ] . isIdle ( ) ; } return idle ; }


Input: Checks if the { @link io . github . agentsoz . jill . core . IntentionSelector } pools have finished i . e . all agents in the pools are idle . [CODESPLIT] public static boolean arePoolsFinished ( ) { boolean finished = true ; for ( int i = 0 ; i < intentionSelectors . length ; i ++ ) { finished &= ( intentionSelectors [ i ] == null ) ; } return finished ; }


Input: Sets a bit in the agentsIdle cache to mark if this agent is idle ( or not ) . [CODESPLIT] public static void setAgentIdle ( int agentId , boolean isIdle ) { int poolid = poolid ( agentId ) ; intentionSelectors [ poolid ] . setAgentIdle ( agentId , isIdle ) ; }


Input: Gets the ID of the intention selection pool to which the given agent belongs . [CODESPLIT] public static int poolid ( int agentid ) { int poolid = agentid / poolsize ; if ( poolid + 1 > npools ) { poolid = npools - 1 ; } return poolid ; }


Input: Returns the expression currently active in the building context . [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public < E > Expression < E > pickExpression ( ) { Preconditions . checkState ( this . expression != null , "No expression has been set" ) ; Expression < E > result = ( Expression < E > ) this . expression ; expression = null ; return result ; }


Input: Sets the expression currently active in the building context . [CODESPLIT] public < E > void setExpression ( Expression < E > expression ) { Preconditions . checkState ( this . expression == null , "An expression is already set" ) ; this . expression = expression ; }


Input: Create a new join or find an existing join on the specified attribute . [CODESPLIT] public static Expression < ? > join ( String attribute , From < ? , ? > from ) { Expression < ? > path ; try { String [ ] properties = attribute . split ( "\\." ) ; if ( properties . length > 1 ) { path = joinRecursively ( properties , findOrCreateJoin ( properties [ 0 ] , from ) , 1 ) . get ( properties [ properties . length - 1 ] ) ; } else { path = from . get ( properties [ 0 ] ) ; } } catch ( IllegalArgumentException e ) { throw SeedException . wrap ( e , JpaErrorCode . UNABLE_TO_CREATE_JPA_JOIN_FOR_SPECIFICATION ) . put ( "property" , attribute ) ; } return path ; }


Input: Join recursively using the split property path . [CODESPLIT] private static Join < ? , ? > joinRecursively ( String [ ] properties , Join < ? , ? > join , int index ) { if ( index < properties . length - 1 ) { return joinRecursively ( properties , findOrCreateJoin ( properties [ index ] , join ) , index + 1 ) ; } else { return join ; } }


Input: Find an existing join for the property or create a new join . [CODESPLIT] private static Join < ? , ? > findOrCreateJoin ( String property , From < ? , ? > from ) { for ( Join < ? , ? > rootJoin : from . getJoins ( ) ) { if ( rootJoin . getAttribute ( ) . getName ( ) . equals ( property ) ) { return rootJoin ; } } return from . join ( property ) ; }


Input:
Dump managed instance of { @link InstanceType#PROXY } type and with { @link InstanceScope#APPLICATION } scope to container logger . For managed instance of other scope / type combinations this method does nothing . [CODESPLIT] @ Override public void postProcessInstance ( ManagedClassSPI managedClass , Object instance ) { if ( ! managedClass . getInstanceScope ( ) . equals ( InstanceScope . APPLICATION ) ) { return ; } if ( ! managedClass . getInstanceType ( ) . equals ( InstanceType . PROXY ) ) { return ; } Class < ? > [ ] interfaceClasses = managedClass . getInterfaceClasses ( ) ; StringBuilder interfaceNames = new StringBuilder ( interfaceClasses [ 0 ] . getName ( ) ) ; for ( int i = 1 ; i < interfaceClasses . length ; ++ i ) { interfaceNames . append ( ", " ) ; interfaceNames . append ( interfaceClasses [ i ] . getName ( ) ) ; } log . debug ( "Create managed container proxy:\r\n" + //
 "\t- implementation: %s\r\n" + //
 "\t- interface(s): %s\r\n" + //
 "\t- scope: %s\r\n" + //
 "\t- type: %s\r\n" + //
 "\t- transactional: %s\r\n" + //
 "\t- remote: %s" , managedClass . getImplementationClass ( ) , interfaceNames . toString ( ) , managedClass . getInstanceScope ( ) , managedClass . getInstanceType ( ) , managedClass . isTransactional ( ) , managedClass . isRemotelyAccessible ( ) ) ; }


Input: Indicates whether the response reaches the end of the elements available on the server . [CODESPLIT] public boolean isEndReached ( ) { if ( to == null || from == null ) { // No range specified, must be complete response return true ; } if ( length == null ) { // No lenth specified, can't be end return false ; } return to == length - 1 ; }


Input:
Parse multipart form from HTTP request create object instance of requested type and fill it with form field value ( s ) . If formal type is a stream store it to local thread so that to be able to close it after arguments processed by application code . [CODESPLIT] @ Override public Object [ ] read ( HttpServletRequest httpRequest , Type [ ] formalParameters ) throws IOException , IllegalArgumentException { if ( formalParameters . length != 1 ) { throw new IllegalArgumentException ( "Bad parameters count. Should be exactly one but is |%d|." , formalParameters . length ) ; } if ( formalParameters [ 0 ] instanceof ParameterizedType ) { throw new IllegalArgumentException ( "Parameterized type |%s| is not supported." , formalParameters [ 0 ] ) ; } Class < ? > type = ( Class < ? > ) formalParameters [ 0 ] ; Object [ ] arguments = new Object [ 1 ] ; if ( type . equals ( Form . class ) ) { arguments [ 0 ] = new FormImpl ( httpRequest ) ; } else if ( type . equals ( FormIterator . class ) ) { arguments [ 0 ] = new FormIteratorImpl ( httpRequest ) ; } else if ( type . equals ( UploadedFile . class ) ) { Form form = new FormImpl ( httpRequest ) ; // Form#getUploadedFile() throws IlegalArgumentException if form has not a single file upload part
 arguments [ 0 ] = form . getUploadedFile ( ) ; } else if ( type . equals ( UploadStream . class ) ) { threadLocal . set ( ( Closeable ) ( arguments [ 0 ] = getUploadStream ( httpRequest , formalParameters ) ) ) ; } else if ( type . equals ( InputStream . class ) ) { threadLocal . set ( ( Closeable ) ( arguments [ 0 ] = getUploadStream ( httpRequest , formalParameters ) . openStream ( ) ) ) ; } else { arguments [ 0 ] = new FormObject ( httpRequest , type ) . getValue ( ) ; } return arguments ; }


Input: Get upload stream from given HTTP request . This method expects on HTTP request a multipart form with a single part of byte stream type . Returns an upload stream instance wrapping the form stream part . [CODESPLIT] private static UploadStream getUploadStream ( HttpServletRequest httpRequest , Type [ ] formalParameters ) throws IOException { FormIterator form = new FormIteratorImpl ( httpRequest ) ; if ( ! form . hasNext ( ) ) { throw new IllegalArgumentException ( "Empty form." ) ; } Part part = form . next ( ) ; if ( ! ( part instanceof UploadStream ) ) { throw new IllegalArgumentException ( "Illegal form. Expected uploaded stream but got field |%s|." , part . getName ( ) ) ; } return ( UploadStream ) part ; }


Input: Looks up a class in the alias map . If <code > className< / code > exists as an alias it is resolved and returned . If the alias doesn t exist the original String is returned . [CODESPLIT] public String getClazz ( final String className ) { String realName = className ; while ( classMapper . containsKey ( realName ) ) { realName = classMapper . get ( realName ) ; } return realName ; }


Input: Performed super - initialization by { @link AppServlet#init ( ServletConfig ) } and loads REST methods cache . A REST method is a remotely accessible method that does not return a { @link Resource } . Map storage key is generated by { @link #key ( ManagedMethodSPI ) } based on managed class and REST method request paths and is paired with retrieval key - { @link #key ( String ) } generated from request path info when method invocation occurs . [CODESPLIT] @ Override public void init ( ServletConfig config ) throws UnavailableException { super . init ( config ) ; for ( ManagedMethodSPI managedMethod : container . getManagedMethods ( ) ) { if ( ! managedMethod . isRemotelyAccessible ( ) ) { continue ; } if ( ! Types . isKindOf ( managedMethod . getReturnType ( ) , Resource . class ) ) { restMethods . put ( key ( managedMethod ) , managedMethod ) ; } } }


Input:
Handle request for a REST resource . Locate REST method based on request path info execute method and serialize back to client returned value if any . See class description for general behavior . [CODESPLIT] @ Override protected void handleRequest ( RequestContext context ) throws IOException { HttpServletRequest httpRequest = context . getRequest ( ) ; HttpServletResponse httpResponse = context . getResponse ( ) ; ArgumentsReader argumentsReader = null ; Object value = null ; ManagedMethodSPI method = null ; try { method = restMethods . get ( key ( httpRequest . getPathInfo ( ) ) ) ; if ( method == null ) { throw new NoSuchMethodException ( ) ; } Type [ ] formalParameters = method . getParameterTypes ( ) ; argumentsReader = argumentsReaderFactory . getArgumentsReader ( httpRequest , formalParameters ) ; Object [ ] arguments = argumentsReader . read ( httpRequest , formalParameters ) ; Object instance = container . getInstance ( method . getDeclaringClass ( ) ) ; value = method . invoke ( instance , arguments ) ; } catch ( AuthorizationException e ) { sendUnauthorized ( context ) ; return ; } catch ( NoSuchMethodException e ) { sendNotFound ( context , e ) ; return ; } catch ( IllegalArgumentException e ) { // there are opinions that 422 UNPROCESSABLE ENTITY is more appropriate response
 // see https://httpstatuses.com/422
 sendBadRequest ( context ) ; return ; } catch ( InvocationException e ) { sendError ( context , e ) ; return ; } finally { if ( argumentsReader != null ) { argumentsReader . clean ( ) ; } } httpResponse . setCharacterEncoding ( "UTF-8" ) ; if ( method . isVoid ( ) ) { // expected servlet container behavior:
 // since there is nothing written to respond to output stream, container either set content length to zero
 // or closes connection signaling end of content
 httpResponse . setStatus ( HttpServletResponse . SC_NO_CONTENT ) ; return ; } // expected servlet container behavior:
 // if client request connection header is close container uses an internal buffer for serialized JSON, add content
 // length response header based on buffer size and closes connection
 // if client request connection header is not explicitly set to close, container uses an internal buffer for serialized
 // JSON but with limited capacity; if capacity is not exceeded set response content length; if capacity is exceeded
 // switch to chunked transfer
 ContentType contentType = valueWriterFactory . getContentTypeForValue ( value ) ; httpResponse . setStatus ( HttpServletResponse . SC_OK ) ; httpResponse . setContentType ( contentType . getValue ( ) ) ; ValueWriter valueWriter = valueWriterFactory . getValueWriter ( contentType ) ; valueWriter . write ( httpResponse , value ) ; }


Input: Generate retrieval key for REST methods cache . This key is used by request routing logic to locate REST method about to invoke . It is based on request path extracted from request URI see { @link RequestPreprocessor } and { @link RequestContext#getRequestPath () } - and should be identical with storage key . <p > Retrieval key syntax is identical with storage key but is based on request path that on its turn is extracted from request URI . In fact this method just trim query parameters and extension if any . [CODESPLIT] private static String key ( String requestPath ) { int queryParametersIndex = requestPath . lastIndexOf ( ' ' ) ; if ( queryParametersIndex == - 1 ) { queryParametersIndex = requestPath . length ( ) ; } int extensionIndex = requestPath . lastIndexOf ( ' ' , queryParametersIndex ) ; if ( extensionIndex == - 1 ) { extensionIndex = queryParametersIndex ; } return requestPath . substring ( 0 , extensionIndex ) ; }


Input: Create a content type instance suitable to represent requested file . It is a trivial a approach using a map of common used file extension . Recognizes only couple most used types ; if extension is not recognized returns { @link #TEXT_HTML } . [CODESPLIT] public static ContentType forFile ( File file ) { Params . notNull ( file , "File" ) ; ContentType contentType = FILE_TYPES . get ( Files . getExtension ( file ) ) ; if ( contentType == null ) { log . debug ( "Unknown content type for |%s|. Replace with default |%s|." , file , TEXT_HTML ) ; contentType = TEXT_HTML ; } return contentType ; }


Input: Parses content type value and returns newly created instance . Given value should obey syntax described by this class . This factory method just delegates { @link #ContentType ( String ) } . If <code > value< / code > argument is null uses { @link #APPLICATION_JSON } as default . [CODESPLIT] public static ContentType valueOf ( String value ) { if ( value == null ) { return ContentType . APPLICATION_JSON ; } return new ContentType ( value ) ; }


Input: Test if content type has a parameter with requested name and value . [CODESPLIT] public boolean hasParameter ( String name , String value ) { Params . notNullOrEmpty ( name , "Parameter name" ) ; Params . notNullOrEmpty ( value , "Parameter value" ) ; return value . equals ( parameters . get ( name ) ) ; }


Input: Get parameter value or null if parameter does not exist . [CODESPLIT] public String getParameter ( String name ) { Params . notNullOrEmpty ( name , "Parameter name" ) ; return parameters . get ( name ) ; }


Input:
Parse content type parameters . Given parameters expression should be valid accordingly grammar from class description ; it should not start with parameters separator that is semicolon . [CODESPLIT] private static Map < String , String > parseParameters ( String expression ) { // charset = UTF-8
 Map < String , String > parameters = new HashMap <> ( ) ; int parametersSeparatorIndex = 0 ; for ( ; ; ) { int valueSeparatorIndex = expression . indexOf ( ' ' , parametersSeparatorIndex ) ; if ( valueSeparatorIndex == - 1 ) { break ; } String name = expression . substring ( parametersSeparatorIndex , valueSeparatorIndex ) . trim ( ) ; ++ valueSeparatorIndex ; parametersSeparatorIndex = expression . indexOf ( ' ' , valueSeparatorIndex ) ; if ( parametersSeparatorIndex == - 1 ) { parametersSeparatorIndex = expression . length ( ) ; } if ( valueSeparatorIndex == parametersSeparatorIndex ) { throw new SyntaxException ( "Invalid content type parameters |%s|. Value is empty." , expression ) ; } if ( parameters . put ( name , expression . substring ( valueSeparatorIndex , parametersSeparatorIndex ) . trim ( ) ) != null ) { throw new SyntaxException ( "Invalid content type parameters |%s|. Name override |%s|." , expression , name ) ; } ++ parametersSeparatorIndex ; } if ( parameters . isEmpty ( ) ) { throw new SyntaxException ( "Invalid content type parameters |%s|. Missing name/value separator." , expression ) ; } return parameters ; }


Input: Configure underlying transaction manager . [CODESPLIT] @ Override public void config ( Config config ) throws Exception { log . trace ( "config(Config.Element)" ) ; log . debug ( "Configure transaction manager |%s|." , transactionManager . getClass ( ) ) ; transactionManager . config ( config ) ; }


Input:
Returns the target file for a given artifact type and filename . This method takes care about eventually creating non existing directories or protect existing files to be overridden . [CODESPLIT] protected final GeneratedFile getTargetFile ( final String artifactName , final String filename , final String logInfo ) { final Folder folder = getGeneratorConfig ( ) . findTargetFolder ( artifactName ) ; final File dir = folder . getCanonicalDir ( ) ; final File file = new File ( dir , filename ) ; // Make sure the folder exists
 if ( ! dir . exists ( ) ) { if ( folder . isCreate ( ) ) { dir . mkdirs ( ) ; } else { throw new IllegalStateException ( "Directory '" + dir + "' does not exist, but configuration does not allow creation: " + "<folder name=\"" + folder . getName ( ) + "\" create=\"false\" ... />" ) ; } } // Make sure the parent directory for the file exists
 if ( ! file . getParentFile ( ) . exists ( ) ) { file . getParentFile ( ) . mkdirs ( ) ; } if ( file . exists ( ) && ! folder . overrideAllowed ( file ) ) { // Skip file because override is not allowed
 return new GeneratedFile ( file , logInfo , true ) ; } return new GeneratedFile ( file , logInfo ) ; }


Input: Writes a generated artifact to a file . [CODESPLIT] protected final void write ( @ NotNull final GeneratedArtifact artifact ) throws GenerateException { Contract . requireArgNotNull ( "artifact" , artifact ) ; final GeneratedFile genFile = getTargetFile ( artifact . getName ( ) , artifact . getPathAndName ( ) , null ) ; if ( genFile . isSkip ( ) ) { LOG . debug ( "Omitted already existing file: {} [{}]" , genFile , artifact ) ; } else { LOG . debug ( "Writing file:  {} [{}]" , genFile , artifact ) ; try { final OutputStream out = new BufferedOutputStream ( new FileOutputStream ( genFile . getTmpFile ( ) ) ) ; try { out . write ( artifact . getData ( ) ) ; } finally { out . close ( ) ; } genFile . persist ( ) ; } catch ( final IOException ex ) { throw new GenerateException ( "Error writing artifact '" + artifact + "' to '" + artifact . getPathAndName ( ) + "'!" , ex ) ; } } }


Input: Initialize instance fields from managed class configuration object . [CODESPLIT] @ Override public void postProcessInstance ( ManagedClassSPI managedClass , Object instance ) { Config config = managedClass . getConfig ( ) ; if ( config == null ) { return ; } List < Config > fields = config . findChildren ( "instance-field" ) ; if ( ! fields . isEmpty ( ) && ! InstanceType . POJO . equals ( managedClass . getInstanceType ( ) ) ) { throw new BugError ( "Cannot assign instance field on non %s type." , InstanceType . POJO ) ; } for ( Config field : fields ) { Classes . setFieldValue ( instance , field . getAttribute ( "name" ) , field . getAttribute ( "value" ) ) ; } }