<commit_before>/* $This file is distributed under the terms of the license in /doc/license.txt$ */

package edu.cornell.mannlib.vitro.webapp.ontology.update;

import java.io.IOException;
import java.util.List;

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.NodeIterator;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.vocabulary.RDFS;

import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;

/**  
* Performs knowledge base updates to the tbox to align with a new ontology version
*   
*/ 
public class TBoxUpdater {

	private OntModel oldTboxAnnotationsModel;
	private OntModel newTboxAnnotationsModel;
	private OntModel siteModel;
	private OntologyChangeLogger logger;  
	private OntologyChangeRecord record;
	private boolean detailLogs = false;

	/**
	 * 
	 * Constructor 
	 *  
	 * @param   oldTboxAnnotationsModel - previous version of the annotations in the ontology
	 * @param   newTboxAnnotationsModel - new version of the annotations in the ontology
	 * @param   siteModel    - the knowledge base to be updated
	 * @param   logger       - for writing to the change log
	 *                         and the error log.
	 * @param   record       - for writing to the additions model 
	 *                         and the retractions model.
	 *                    
	 */
	public TBoxUpdater(OntModel oldTboxAnnotationsModel,
			           OntModel newTboxAnnotationsModel,
			           OntModel siteModel,
		               OntologyChangeLogger logger,
		               OntologyChangeRecord record) {
		
		this.oldTboxAnnotationsModel = oldTboxAnnotationsModel;
		this.newTboxAnnotationsModel = newTboxAnnotationsModel;
		this.siteModel = siteModel;
		this.logger = logger;
		this.record = record;
	}
	
	/**
	 * 
	 * Update a knowledge base to align with changes to vitro annotation property default 
	 * values in a new version of the ontology. The two versions of the ontology and the
	 * knowledge base to be updated are provided in the class constructor and are
	 * referenced via class level variables. 
	 *                    
	 * If the default value (i.e. the value that is provided in the vivo-core 
	 * annotations files) of a vitro annotation property has been changed for a vivo
	 * core class, and that default value has not been changed in the site knowledge
	 * base, then update the value in the site knowledge base to be the new default.
	 * Also, if a new vitro annotation property setting (i.e. either an existing 
	 * setting applied to an existing class where it wasn't applied before, or
	 * an existing setting applied to a new class) has been applied to a vivo
	 * core class then copy that new property statement into the site model.
	 * If a property setting for a class exists in the old ontology but
	 * not in the new one, then that statement will be removed from the
	 * site knowledge base.
	 *                    
	 *  Writes to the change log file, the error log file, and the incremental change
	 *  knowledge base.                  
	 *  
	 *  Note: as specified, this method for now assumes that no new vitro annotation
	 *  properties have been introduced. This should be updated for future versions.
	 */
	public void updateVitroPropertyDefaultValues() throws IOException {
				
		siteModel.enterCriticalSection(Lock.WRITE);
		
		try {
			
	       Model additions = ModelFactory.createDefaultModel();
	       Model retractions = ModelFactory.createDefaultModel();
		
    	 //  Update defaults values for vitro annotation properties in the site model
         //  if the default has changed in the new version of the ontology AND if 
         //  the site hasn't overidden the previous default in their knowledge base.
    		    
		  StmtIterator iter = oldTboxAnnotationsModel.listStatements();
		  		  
		  int stmtCount = 0;
		  
		  while (iter.hasNext()) {
			  
			 stmtCount++;
			 Statement stmt = iter.next();
			 Resource subject = stmt.getSubject();
			 Property predicate = stmt.getPredicate();
			 RDFNode oldObject = stmt.getObject();
			 
			 if (! ( (RDFS.getURI().equals(predicate.getNameSpace())) || 
					 (VitroVocabulary.vitroURI.equals(predicate.getNameSpace())) 
					) ) {
				 // this annotation updater is only concerned with properties
				 // such as rdfs:comment and properties in the vitro application
				 // namespace
				 continue;
			 }
			 
			 if (VitroVocabulary.TAB_AUTOLINKEDTOTAB.equals(predicate.getURI())) {
				 continue;
				 // the tab autolinks are not like the other annotations
				 // and should never be updated automatically
			 }
			 			 
			 NodeIterator newObjects = newTboxAnnotationsModel.listObjectsOfProperty(subject, predicate);
			 
			 if ((newObjects == null) || (!newObjects.hasNext()) ) {
				 // first check to see if the site has a local value change
				 // that should override the deletion
				 List<RDFNode> siteObjects = siteModel.listObjectsOfProperty(subject, predicate).toList();
				 if (siteObjects.size() > 1) {
					 logger.logError("Error: found " + siteObjects.size() +
							 " statements with subject = " + subject.getURI() + 
							 " and property = " + predicate.getURI() +
							 " in the site database. (maximum of one is expected)");
				 }
				 if (siteObjects.size() > 0) {
					 RDFNode siteNode = siteObjects.get(0);
					 if (siteNode.equals(oldObject)) {
						 retractions.add(siteModel.listStatements(subject, predicate, (RDFNode) null));		 
					 }
				 }
				 continue;				 			 
			 }
			
			 RDFNode newObject = newObjects.next();
			 
			 int i = 1;
			 while (newObjects.hasNext()) {
                 i++;
                 newObjects.next();
             } 
			 
			 if (i > 1) {
				 logger.log("WARNING: found " + i +
						 " statements with subject = " + subject.getURI() + 
						 " and property = " + predicate.getURI() +
						 " in the new version of the annotations ontology. (maximum of one is expected)");
				 continue; 
			 }
			 <commit_msg>incremental development for NIHVIVO-1286<commit_after>/* $This file is distributed under the terms of the license in /doc/license.txt$ */

package edu.cornell.mannlib.vitro.webapp.ontology.update;

import java.io.IOException;
import java.util.List;

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.NodeIterator;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.vocabulary.RDFS;

import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;

/**  
* Performs knowledge base updates to the tbox to align with a new ontology version
*   
*/ 
public class TBoxUpdater {

	private OntModel oldTboxAnnotationsModel;
	private OntModel newTboxAnnotationsModel;
	private OntModel siteModel;
	private OntologyChangeLogger logger;  
	private OntologyChangeRecord record;
	private boolean detailLogs = false;

	/**
	 * 
	 * Constructor 
	 *  
	 * @param   oldTboxAnnotationsModel - previous version of the annotations in the ontology
	 * @param   newTboxAnnotationsModel - new version of the annotations in the ontology
	 * @param   siteModel    - the knowledge base to be updated
	 * @param   logger       - for writing to the change log
	 *                         and the error log.
	 * @param   record       - for writing to the additions model 
	 *                         and the retractions model.
	 *                    
	 */
	public TBoxUpdater(OntModel oldTboxAnnotationsModel,
			           OntModel newTboxAnnotationsModel,
			           OntModel siteModel,
		               OntologyChangeLogger logger,
		               OntologyChangeRecord record) {
		
		this.oldTboxAnnotationsModel = oldTboxAnnotationsModel;
		this.newTboxAnnotationsModel = newTboxAnnotationsModel;
		this.siteModel = siteModel;
		this.logger = logger;
		this.record = record;
	}
	
	/**
	 * 
	 * Update a knowledge base to align with changes to vitro annotation property default 
	 * values in a new version of the ontology. The two versions of the ontology and the
	 * knowledge base to be updated are provided in the class constructor and are
	 * referenced via class level variables. 
	 *                    
	 * If the default value (i.e. the value that is provided in the vivo-core 
	 * annotations files) of a vitro annotation property has been changed for a vivo
	 * core class, and that default value has not been changed in the site knowledge
	 * base, then update the value in the site knowledge base to be the new default.
	 * Also, if a new vitro annotation property setting (i.e. either an existing 
	 * setting applied to an existing class where it wasn't applied before, or
	 * an existing setting applied to a new class) has been applied to a vivo
	 * core class then copy that new property statement into the site model.
	 * If a property setting for a class exists in the old ontology but
	 * not in the new one, then that statement will be removed from the
	 * site knowledge base.
	 *                    
	 *  Writes to the change log file, the error log file, and the incremental change
	 *  knowledge base.                  
	 *  
	 *  Note: as specified, this method for now assumes that no new vitro annotation
	 *  properties have been introduced. This should be updated for future versions.
	 */
	public void updateVitroPropertyDefaultValues() throws IOException {
				
		siteModel.enterCriticalSection(Lock.WRITE);
		
		try {
			
	       Model additions = ModelFactory.createDefaultModel();
	       Model retractions = ModelFactory.createDefaultModel();
		
    	 //  Update defaults values for vitro annotation properties in the site model
         //  if the default has changed in the new version of the ontology AND if 
         //  the site hasn't overidden the previous default in their knowledge base.
    		    
		  StmtIterator iter = oldTboxAnnotationsModel.listStatements();
		  		  
		  int stmtCount = 0;
		  
		  while (iter.hasNext()) {
			  
			 stmtCount++;
			 Statement stmt = iter.next();
			 Resource subject = stmt.getSubject();
			 Property predicate = stmt.getPredicate();
			 RDFNode oldObject = stmt.getObject();
			 
			 if (! ( (RDFS.getURI().equals(predicate.getNameSpace())) || 
					 (VitroVocabulary.vitroURI.equals(predicate.getNameSpace())) 
					) ) {
				 // this annotation updater is only concerned with properties
				 // such as rdfs:comment and properties in the vitro application
				 // namespace
				 continue;
			 }
			 
			 if (VitroVocabulary.TAB_AUTOLINKEDTOTAB.equals(predicate.getURI())) {
				 continue;
				 // the tab autolinks are not like the other annotations
				 // and should never be updated automatically
			 }
			 			 
			 NodeIterator newObjects = newTboxAnnotationsModel.listObjectsOfProperty(subject, predicate);
			 
			 if ((newObjects == null) || (!newObjects.hasNext()) ) {
				 // first check to see if the site has a local value change
				 // that should override the deletion
				 List<RDFNode> siteObjects = siteModel.listObjectsOfProperty(subject, predicate).toList();
				
				 if (siteObjects.size() > 1) {
					 logger.log("WARNING: found " + siteObjects.size() +
							 " statements with subject = " + subject.getURI() + 
							 " and property = " + predicate.getURI() +
							 " in the site database. (maximum of one is expected)");
				 }
				 
				 if (siteObjects.size() > 0) {
					 RDFNode siteNode = siteObjects.get(0);
					 if (siteNode.equals(oldObject)) {
						 retractions.add(siteModel.listStatements(subject, predicate, (RDFNode) null));		 
					 }
				 }
				 
				 continue;				 			 
			 }
			
			 RDFNode newObject = newObjects.next();
			 
			 int i = 1;
			 while (newObjects.hasNext()) {
                 i++;
                 newObjects.next();
             } 
			 
			 if (i > 1) {
				 logger.log("WARNING: found " + i +
						 " statements with subject = " + subject.getURI() + 
						 " and property = " + predicate.getURI() +
						 " in the new version of the annotations ontology. (maximum of one is expected)");
				 continue; 
			 }
			 
{'fraction_non_alphanumeric': 0.08198019801980198, 'fraction_numerical': 0.0012673267326732674, 'mean_word_length': 2.6831971995332555, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2895532', 'n_tokens_mistral': 4179, 'n_tokens_neox': 3391, 'n_words': 1177}