Commits

Raza Ali committed 7ced8f1

Added documentation to recently modified/added code.

  • Participants
  • Parent commits f24d67f

Comments (0)

Files changed (6)

File grails-app/jobs/net/biomodels/jummp/core/RegistrationCheckerJob.groovy

 import org.quartz.JobExecutionException
 import org.quartz.JobExecutionContext
 /**
- * @short Job for cleaning the exchange directory after RTCs if they have been in the
- * exchange for a long time. This can happen if the GC based cleaner doesnt clean up
- * the files in the first place (which could be because the program ended before GC ran,
- * or the GC decided theres lots of memory so it doesnt need to run. 
+ * @short Job for checking the status of the modelfileformatconfig which was getting
+ * lost (so long as it was in the service). While its running anyway, it updates the 
+ * search provider's index, ensuring we have (relatively) recent results.
  *
  * @author Raza Ali <raza.ali@ebi.ac.uk>
  */

File src/groovy/net/biomodels/jummp/core/ModelFileFormatConfig.groovy

 package net.biomodels.jummp.core
-
+/**
+ * @short Class written as a spring-bean singleton to hold modelfileformatservice config data
+ * 
+ * The class exists to store config required by the modelfileformatservice, which was getting lost
+ * after jummp was left running for a long time.
+ *
+ * @author Raza Ali, raza.ali@ebi.ac.uk
+ * @date   9/09/2013
+ */
 class ModelFileFormatConfig {
     /**
     * The registered services to handle ModelFormats

File src/groovy/net/biomodels/jummp/core/ReferenceTracker.groovy

 import net.biomodels.jummp.core.WrappedRevisionReference
 import net.biomodels.jummp.core.model.RevisionTransportCommand
 
+/**
+ * @short Class written as a spring-bean singleton to track references to revisionTCs
+ * 
+ * The class maintains a reference queue that will be populated by the Java garbage collector
+ * along with references to revisions. A separate quartz job polls the reference queue to see
+ * if any revisions have been marked as weak, to clean up resources associated with them
+ *
+ * @author Raza Ali, raza.ali@ebi.ac.uk
+ * @date   9/09/2013
+ */
 class ReferenceTracker {
     /*
     * Weak references to revision transport command objects, so that files can be deleted from exchange.
     private final static ReferenceQueue referenceQueue = new ReferenceQueue()
 
     /*
-    * Functions used by the quartz job for removing files from the exchange
+    * Self explanatory functions used by the quartz job for getting the reference queue and
+    * accessing the references map
     */
     ReferenceQueue getRefQueue() {
     	    return referenceQueue
     	    weakRefs.remove(id)
     }
     
+    /**
+	* Tracks a revision and the folder path associated with it. 
+	*
+	* Wraps a @param revision into a wrappedrevisionreference, enabling its tracking. Also
+	* stores the folder location so it can be deleted easily.
+	*
+	* @param revision The revision to be added to the references
+	* @param path The folder associated with the revision in the exchange
+	**/
+	
     void addReference(RevisionTransportCommand revision, String path) {
     	    String folder=(new File(path)).getParent()
     	    WrappedRevisionReference ref=new WrappedRevisionReference(revision, folder, referenceQueue)

File src/groovy/net/biomodels/jummp/search/SearchProvider.groovy

 import org.apache.lucene.util.Version
 import org.apache.lucene.document.Document
 /**
- * @short Listener for new revisions and models for indexing
+ * @short Class written as a spring-bean singleton to execute search queries using lucene
  * 
+ * The class maintains a searchermanager linked to an indexwriter maintained by
+ * UpdatedRepositoryListener bean. 
+ *
  * @author Raza Ali, raza.ali@ebi.ac.uk
  * @date   9/09/2013
  */
 	
 	SearcherManager mgr
 	
+	/**
+	* Internal method to executes a query 
+	*
+	* Gets the searchermanager if necessary from the indexwriter, 
+	* executes the supplied @param query,
+	* filters out duplicates (as we index revisions and return models),
+	*
+	* @param query The query to be executed
+	* @return A set of documents corresponding to search results
+	**/
 	private Set<Document> search(Query q) {
 		Set<Document> docs=new HashSet<Document>()
 		if (!mgr) {
 		}
 		IndexSearcher indexSearcher = mgr.acquire();
 		try {
-			TopDocs topDocs = indexSearcher.search(q,1000);
+			TopDocs topDocs = indexSearcher.search(q,1000); //make less arbitrary
 			for (int i=0; i<topDocs.totalHits; i++) {
 				docs.add(indexSearcher.doc(topDocs.scoreDocs[i].doc))
 			}
 			indexSearcher = null;
 		}
 		return docs
-		
 	}
 	
+	
+	/**
+	* Executes a search on the specified fields 
+	*
+	* Performs search on the @param query, using the supplied @param fields
+	*
+	* @param query The query to be executed
+	* @param fields The ids of the fields in the documents
+	* @return A set of documents corresponding to search results
+	**/
 	public Set<Document> performSearch(String[] fields, String query) {
 		QueryParser queryParser=new MultiFieldQueryParser(Version.LUCENE_44, fields, new StandardAnalyzer(Version.LUCENE_44))		
 		return search(queryParser.parse(query))
 	}
 	
+	/**
+	* Executes a search on a single field
+	*
+	* Performs search on the @param query, using the supplied @param field
+	*
+	* @param query The query to be executed
+	* @param field The ids of the field in the documents
+	* @return A set of documents corresponding to search results
+	**/
 	public Set<Document> performSearch(String field, String query) {
 		QueryParser queryParser = new QueryParser(Version.LUCENE_44,field,new StandardAnalyzer(Version.LUCENE_44));
 		return search(queryParser.parse(query))
 	}
 	
+	/**
+	* Gets the searcher to update its view of the index, if necessary
+	**/
 	public void refreshIndex() {
 		if (mgr) {
 			mgr.maybeRefresh()

File src/groovy/net/biomodels/jummp/search/UpdatedRepositoryListener.groovy

 import grails.util.Environment
 /**
  * @short Listener for new revisions and models for indexing
- * 
+ *
+ * This class is meant to be executed as a (singleton) spring bean
+ * which listens for events generated by the model service (new models/new revisions).
+ * An indexwriter is kept open (maintaining an exclusive lock on the search index)
+ * and new models/revisions are indexed as they arrive. The class is also used to
+ * get a searchermanager, utilising the Lucene Near Realtime Search mechanism.
+ *
  * @author Raza Ali, raza.ali@ebi.ac.uk
  * @date   9/09/2013
  */
 	def modelDelegateService
 	def grailsApplication = ApplicationHolder.application
 	
+	/**
+	* Creates/Opens a lucene index based on the config properties (unless test, 
+	* otherwise a default location is used, to avoid corrupting the index). 
+	*/
 	public UpdatedRepositoryListener() {
 		String path=grailsApplication.config.jummp.search.index
 		if (Environment.current == Environment.TEST) {
 		indexWriter =new IndexWriter(fsDirectory,conf);
 	}
 	
+	/**
+	* Responds to model creation/update events
+	*
+	* Responds to the @param event, if it is a model create/update, it is indexed
+	* in the lucene index.
+	* @param event The event, to be handled if it a model create/update event
+	**/
 	public void onApplicationEvent(ApplicationEvent event) {
 		if (event instanceof RevisionCreatedEvent) {
 			updateIndex((event as RevisionCreatedEvent).revision)
 		}
 	}
 	
+	/**
+	* Adds a revision to the index
+	*
+	* Adds the specified @param revision to the lucene index
+	* @param revision The revision to be indexed
+	**/
 	public void updateIndex(RevisionTransportCommand revision) {
 		
 		String name = revision.name
 		doc.add(submitterField)
 		
 		indexWriter.addDocument(doc);
-		indexWriter.commit();
+		indexWriter.commit(); // To do: investigate a more optimised commit mechanism
 	}
 	
+	/**
+	* Gets a searchermanager linked to the indexwriter
+	*
+	* @returns A searchermanager linked to the indexwriter, so that changes made in the writer will be
+	* reflected in the searcher.
+	**/
 	public SearcherManager getSearcherManager() {
 		boolean applyAllDeletes = true;
 		SearcherManager mgr = new SearcherManager(indexWriter, true, new SearcherFactory());

File test/integration/net/biomodels/jummp/core/SearchTests.groovy

     def fileSystemService
     def grailsApplication
 
+    @Test
+    void testGetLatestRevision() {
+    	    
+    	// generate unique ids for the name and description
+        String nameTag=UUID.randomUUID().toString()
+        String descriptionTag=UUID.randomUUID().toString()
+        authenticateAsTestUser()
+        GitManagerFactory gitService = new GitManagerFactory()
+        gitService.grailsApplication = grailsApplication
+        grailsApplication.config.jummp.plugins.git.enabled = true
+        grailsApplication.config.jummp.vcs.exchangeDirectory = "target/vcs/exchange"
+        grailsApplication.config.jummp.vcs.workingDirectory = "target/vcs/git"
+        grailsApplication.config.jummp.plugins.sbml.validation = false
+        modelService.vcsService.vcsManager = gitService.getInstance()
+
+    	// upload the model
+        def rf = new RepositoryFileTransportCommand(path: smallModel("importModel.xml", nameTag, descriptionTag).absolutePath, mainFile:true, description: "")
+        Model upped = modelService.uploadModelAsFile(rf, new ModelTransportCommand(format:
+                new ModelFormatTransportCommand(identifier: "SBML"), comment: "test", name: "Test"))
+        // refresh the search index (we dont want to wait 5 mins)       
+        grailsApplication.mainContext.getBean("searchEngine").refreshIndex()
+        
+        // Search for the model using the unique name and description, and ensure its the same we uploaded       
+        assertSame(upped.id,searchForModel(nameTag).id)
+        assertSame(upped.id, searchForModel(descriptionTag).id)
+    }
+
     @Before
     void setUp() {
         def container = new File("target/vcs/git/ggg/")
     	 }
     	 return mods.first()
     }
-    
-    @Test
-    void testGetLatestRevision() {
-        // create Model with one revision, without ACL
-        String nameTag=UUID.randomUUID().toString()
-        String descriptionTag=UUID.randomUUID().toString()
-        authenticateAsTestUser()
-        GitManagerFactory gitService = new GitManagerFactory()
-        gitService.grailsApplication = grailsApplication
-        grailsApplication.config.jummp.plugins.git.enabled = true
-        grailsApplication.config.jummp.vcs.exchangeDirectory = "target/vcs/exchange"
-        grailsApplication.config.jummp.vcs.workingDirectory = "target/vcs/git"
-        grailsApplication.config.jummp.plugins.sbml.validation = false
-        modelService.vcsService.vcsManager = gitService.getInstance()
 
-        def rf = new RepositoryFileTransportCommand(path: smallModel("importModel.xml", nameTag, descriptionTag).absolutePath, mainFile:true, description: "")
-        Model upped = modelService.uploadModelAsFile(rf, new ModelTransportCommand(format:
-                new ModelFormatTransportCommand(identifier: "SBML"), comment: "test", name: "Test"))
-        grailsApplication.mainContext.getBean("searchEngine").refreshIndex()
-        
-        
-        assertSame(upped.id,searchForModel(nameTag).id)
-        assertSame(upped.id, searchForModel(descriptionTag).id)
-    }
+    
+    // Convenience functions follow..
+    
     
     private File smallModel(String filename, String id, String desc) {
         return getFileForTest(filename, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><sbml xmlns=\"http://www.sbml.org/sbml/level1\" level=\"1\" version=\"1\">  <model name=\"${id}\">"