code: package cc.hrLDA.topics;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Arrays;
  import java.io.*;
  import java.sql.*;
  
  import cc.hrLDA.topics.HierarchicalRLDA;
  import cc.hrLDA.topics.HierarchicalRLDA.NCRPNode;
  import cc.mallet.types.*;
  import cc.mallet.util.Randoms;
  import cc.mallet.util.MySqlDB;
  import gnu.trove.*;
  
  import com.hp.hpl.jena.ontology.OntClass;
  import com.hp.hpl.jena.ontology.OntModel;
  import com.hp.hpl.jena.ontology.OntModelSpec;
  import com.hp.hpl.jena.rdf.model.Model;
  import com.hp.hpl.jena.rdf.model.ModelFactory;
  import com.hp.hpl.jena.rdf.model.Resource;
  import com.hp.hpl.jena.vocabulary.RDFS;
  import com.hp.hpl.jena.ontology.Individual;
  import com.hp.hpl.jena.ontology.OntProperty;
  
  import org.modeshape.common.text.Inflector;
  
  public class HierarchicalRLDAInferencer {
  	
  	private NCRPNode rootNode;
  	int numWordsToDisplay=25;
  
  	//global variable
      int numLevels;
      int numOfThreads;
      int numDocuments;
      int numTypes;
      int totalNodes;
      int duplicateCounts = 0;
      public int counter=0;
      HashSet<String> topicSet = new HashSet<String>();
  	Inflector inflector = new Inflector();    
  
      double alpha; // smoothing on topic distributions
      double gamma; // "imaginary" customers at the next, as yet unused table
      double eta;   // smoothing on word distributions
      double etaSum;
      MySqlDB mySqlDB;
  
  
      HashMap <Integer, HashSet<NCRPNode>> golbalDocumentLeaves;
  	
  	int localLevels[];
  	FeatureSequence fs;
  	
  	NCRPNode leaveNode;
      
  
  	Randoms random;
  
  	final private static String NS = "http://semiconductor-packaging/ontology/";
      final private static OntModel model = ModelFactory.createOntologyModel( OntModelSpec.RDFS_MEM );
  	
  	
  	public HierarchicalRLDAInferencer(HierarchicalRLDA hLDA){
  		this.setRootNode(hLDA.rootNode);
  		this.numLevels = hLDA.numLevels;
  		this.numOfThreads = hLDA.numOfThreads;
  		this.numDocuments = hLDA.numDocuments;
  		this.numTypes = hLDA.numTypes;
  		this.mySqlDB = hLDA.mySqlDB;
  		
  		this.alpha = hLDA.alpha;
  		this.gamma = hLDA.gamma;
  		this.eta = hLDA.eta;
  		this.etaSum = hLDA.etaSum;
  		this.totalNodes =hLDA.totalNodes;
  
  		this.golbalDocumentLeaves = hLDA.documentLeaves;
  		this.random = hLDA.random;	
  		topicSet.add("semiconductor-packaging");
  	}
  
  	 
  	 public StringBuffer printTopicDistribution(HashSet<NCRPNode> leaves, int[][] levels){
  			int[] tokenToNodeID;
  			int token, nodeID;
  			
  			StringBuffer out = new StringBuffer();
  			for (NCRPNode leaf : leaves){
  				 NCRPNode node =leaf;
  				 NCRPNode[] path = new NCRPNode[numLevels];
  			     for (int level = numLevels - 1; level >= 0; level--) {
  					 path[level] = node;
  				     node = node.parent;
  				}
  				 
  				double[] result = new double[totalNodes];
  				 
  				 
  				int[] levelCounts = new int[numLevels];
  			
  				for (int level = 1; level < numLevels; level++){
  					node = path[level];
  					tokenToNodeID = levels[level];
  						
  					for (token = 0; token < tokenToNodeID.length; token++) {
  						nodeID = tokenToNodeID[token];
  							
  						if (nodeID == path[level].nodeID){
  								levelCounts[ level]++;
  						}
  					}
  				}			 
  
  				double sum =0.0;
  				for (int level=0; level < numLevels; level++) {	 
  					 sum+=(alpha + levelCounts[level]);
  				}
  				 
  				for (int level=0; level < numLevels; level++) {	 
  					 result[ path[level].nodeID ] = (double)(alpha + levelCounts[level]/sum) ;
  				}
  				 
  				for(int i=0; i < numLevels; i++){
  					 /*
  				 out.append("Level:" + i + ",");
  				 out.append("nodeID:" + path[i].nodeID + ",");
  				 out.append("prob:" + (double)((alpha + levelCounts[i])/sum) + ",");
  				 */
  				 //out.append("Level:" + i + ",");
  				 out.append("nodeID:" + path[i].nodeID + ",");
  				 out.append((double)((alpha + levelCounts[i])/sum) + ",");
  				 }			 
  			 }
  		 return(out);
  	 }
  
  	 
  	 
  	 public void printNode(NCRPNode node, int indent) {
  		    //reset nodes counter
  		    if(node.nodeID==0){
  		    	counter=0;
  		    }
  			StringBuffer out = new StringBuffer();
  			for (int i=0; i<indent; i++) {
  				out.append("  ");
  			}
  			out.append("ID:" + node.nodeID + ",Topic:"+  "/ ");
  			out.append(node.getAllTopWords());
  			System.out.println(out);
  			counter++;
  		
  			for (NCRPNode child: node.children) {
  				printNode(child, indent + 1);
  			}
  	    }
  
  	 public String cleanPhrase(String s){
  		 s = s.replaceAll("\\s+", "_");
  		 return s;
  	 }
  	 
  	 public OntModel printRDFNode(NCRPNode node, OntClass ontparentClass) {
  		 	
  		 	int type =0;
  			String topic ="";
  			String [] topicWithType = new String [2];
  			ArrayList <String []> result = new ArrayList <String []>();
  
  			/*root node*/
  			/*in latest algorithm, root does not contain anything except children list*/
  		    if(ontparentClass == null){
  		    	
  		    	result = node.getAllTopHashWords();
  		    	if (result != null){
  			    	for (int i = 0; i < result.size(); i++){
  			    		topicWithType = new String [2];
  			    		topicWithType = result.get(i);
  				    	//topicWithType = node.getTopHashWords(topicSet);//old topicWithType
  				    	if (topicWithType != null){		  
  				    		topic = cleanPhrase(topicWithType[0]);  
  				    		//System.out.println("RECEIVING ... "+topic);
  							type = Integer.parseInt(topicWithType[1].trim());
  							
  							/*a new topic*/
  							if (!topic.equals("") && !topicSet.contains(topic)){
  								topicSet.add(topic);	
  								ontparentClass = model.createClass( NS+ topic);				
  
  								
  								
  								try{
  									ResultSet rs = mySqlDB.queryRelations(topic.replaceAll("_"," "));
  									/*S -> O relation*/
  									if (rs != null){
  										while(rs.next()){
  							               String relation=rs.getString(1);
  							               String object=rs.getString(2);
  							               String file_name=rs.getString(3);
  							               if (!object.equals("")){
  								               //column starts at 1
  							            	   
  //									               System.out.println("PARENT********************");
  //									               System.out.println("TOPIC: "+topic);
  //									               System.out.println("RELATION: "+relation);
  //									               System.out.println("OBJECT: "+object);
  //									               System.out.println("FILE_NAME: "+file_name);
  //									               System.out.println("PARENT********************\n");
  							            	   
  								               OntProperty  property = model.createOntProperty( NS+ cleanPhrase(relation));
  								               // bind relation with related object
  								               ontparentClass.addProperty(property, cleanPhrase(object));
  											}// end of if (!object.equals("")){
  							          	}// end of while(rs.next()){								
  									}// end of if (rs != null){
  									
  									
  									/*O -> S OP relation*/
  									ResultSet oRs = mySqlDB.queryObjectRelations(topic.replaceAll("_"," "));
  																
  									if (oRs != null){
  										while(oRs.next()){
  							               String relation="OP "+oRs.getString(1);
  							               String object=oRs.getString(2);
  							               String file_name=oRs.getString(3);
  							               if (!object.equals("")){
  								               //column starts at 1
  							            	   
  //									               System.out.println("PARENT********************");
  //									               System.out.println("TOPIC: "+topic);
  //									               System.out.println("OP RELATION: "+relation);
  //									               System.out.println("OBJECT: "+object);
  //									               System.out.println("FILE_NAME: "+file_name);
  //									               System.out.println("PARENT********************\n");
  							            	   
  								               OntProperty  property = model.createOntProperty( NS+ cleanPhrase(relation));
  								               // bind relation with related object
  								               ontparentClass.addProperty(property, cleanPhrase(object));
  											}else{
  												   /*open print it out*/	
  //									               System.out.println("PARENT********************");
  //									               System.out.println("TOPIC: "+topic);
  //									               System.out.println("THIS IS A TITLE");
  //									               System.out.println("FILE_NAME: "+file_name);
  //									               System.out.println("PARENT********************\n");		
  												
  											}// end of  if (!object.equals("")){
  							          	}// end of while(oRs.next()){								
  									}// end of if (oRs != null){
  							
  								}catch(Exception e){
  									System.err.println("Parent node ---- Fail to query relation talbe!");
  								}// end of try
  								
  								
  								/*add doc paths*/
  								ArrayList <String>arrayList = node.getDocs(type);
  								for (String doc : arrayList){
  									
  									System.out.println(doc);
  									ontparentClass.createIndividual( NS + doc.trim() );
  								}//end of for (String doc : arrayList){
  								
  							}// end of if (!topic.equals("") && !topicSet.contains(topic)){
  							
  						}// end of if (topicWithType != null){	
  			    	}// end of for (int i = 0; i < result.size(); i++){		    		
  		    	}// end of if (result != null){
  		    				
  
  		    }// end of if(ontparentClass == null){ 
  		    
  		    
  		    
  		    /*for each child*/
  			for (NCRPNode child: node.children) {		
  						
  		    	result = child.getAllTopHashWords();
  		    	if (result != null){
  			    	for (int j = 0; j < result.size(); j++){
  			    		topicWithType = new String [2];
  			    		topicWithType = result.get(j);
  			    		
  						if (topicWithType != null){
  							topic = cleanPhrase(topicWithType[0]);
  							//System.out.println("RECEIVING ... "+topic);
  							type = Integer.parseInt(topicWithType[1].trim());
  							
  							/*a new topic*/
  							if (!topic.equals("") && !topicSet.contains(topic)){
  								topicSet.add(topic);
  								OntClass ontChildClass = model.createClass( NS+ topic);			
  								
  
  								try{
  									/*S -> O relation*/
  									ResultSet rs = mySqlDB.queryRelations(topic.replaceAll("_"," "));
  									if (rs != null){
  										while(rs.next()){
  							               String relation=rs.getString(1);
  							               String object=rs.getString(2);
  							               String file_name=rs.getString(3);
  							               if (!object.equals("")){
  								               //column starts at 1
  							            	   
  //									               System.out.println("CHILD********************");
  //									               System.out.println("TOPIC: "+topic);
  //									               System.out.println("RELATION: "+relation);
  //									               System.out.println("OBJECT: "+object);
  //									               System.out.println("FILE_NAME: "+file_name);
  //									               System.out.println("CHILD********************\n");
  							            	   
  								               OntProperty  property = model.createOntProperty( NS+ cleanPhrase(relation));
  								               // bind relation with related object
  								               ontChildClass.addProperty(property, cleanPhrase(object));
  											}// end of  if (!object.equals("")){
  							          	}// end of while(rs.next()){
  									}// end of if (rs != null){	
  
  									/*O -> P OP relation*/
  									ResultSet oRs = mySqlDB.queryObjectRelations(topic.replaceAll("_"," "));
  
  									if (oRs != null){
  										while(oRs.next()){
  							               String relation="OP "+oRs.getString(1);
  							               String object=oRs.getString(2);
  							               String file_name=oRs.getString(3);
  							               if (!object.equals("")){
  								               //column starts at 1
  							            	   
  //								               System.out.println("CHILD********************");
  //								               System.out.println("TOPIC: "+topic);
  //								               System.out.println("OP RELATION: "+relation);
  //								               System.out.println("OBJECT: "+object);
  //								               System.out.println("FILE_NAME: "+file_name);
  //								               System.out.println("CHILD********************\n");
  							            	   
  								               OntProperty  property = model.createOntProperty( NS+ cleanPhrase(relation));
  								               // bind relation with related object
  								               ontChildClass.addProperty(property, cleanPhrase(object));
  
  							               }else{
  							            	   /*only pint it out*/
  //								               System.out.println("CHILD********************");
  //								               System.out.println("TOPIC: "+topic);
  //								               System.out.println("THIS IS A TITLE");
  //								               System.out.println("FILE_NAME: "+file_name);
  //								               System.out.println("CHILD********************\n");										
  											}// end of if (!object.equals("")){
  							          	}// end of while(oRs.next()){								
  									}// end of if (oRs != null){												
  								}catch(Exception e){
  									System.err.println("Child node ---- Fail to query relation talbe!");
  								}// end of try					
  
  								/*add doc paths*/
  								ArrayList <String>arrayList = child.getDocs(type);
  								for (String doc : arrayList){
  //									System.out.println(doc);
  									ontChildClass.createIndividual( NS + doc.trim() );
  								}// end of for (String doc : arrayList){
  
  								/*current node is not rootnode*/
  								if(node.nodeID!=0 && ontparentClass != null){
  									ontChildClass.addSuperClass(ontparentClass);
  								}
  								
  								printRDFNode(child, ontChildClass);					
  							}else if (!topic.equals("")){
  								// delete the child and upgrade its children to its location
  								//But the two lines are wrong
  								//node.addChildren(child.children);
  								//node.remove(child);
  								for (NCRPNode new_child: child.children)
  									printRDFNode(new_child, ontparentClass);
  								
  							}// end of if (!topicSet.contains(topic)){
  						}// end of if (topicWithType != null){
  			    	}// end of for (int i = 0; i < result.size(); i++){		    		
  		    	}// end of if (result != null)
  		    	
  
  			}// end of for (NCRPNode child: node.children) {
  		
  			return model;
  	    }	    
  	 
  	  public void printNodeTofile(NCRPNode node, int indent, BufferedWriter writer) {
  		 
  		 //reset nodes counter
  		    if(node.nodeID==0){
  		    	counter=0;
  		    }
  			StringBuffer out = new StringBuffer();
  			
  			
  			for (int i=0; i<indent; i++) {
  				out.append("  ");
  			}
  			
              out.append("layer:"+indent+",");
  			out.append("ID:" + node.nodeID + ",Tokens:"+ node.totalTokens + ",");
  			out.append(node.getTopWords(numWordsToDisplay));
  			out.append("\n");
  			
  			
  			out.append(indent+",");
  			out.append(node.nodeID + ","+ node.totalTokens + ",");
  			out.append(node.getTopWords(numWordsToDisplay));
  			out.append("\n");
  			
  			
  			try {
  				writer.write(out.toString());
  			} catch (IOException e) {
  				// TODO Auto-generated catch block
  				e.printStackTrace();
  			}
  			counter++;
  		
  			for (NCRPNode child: node.children) {
  				printNodeTofile(child, indent + 1, writer);
  			}
  	    }
  
  
  	public NCRPNode getRootNode() {
  		return rootNode;
  	}
  
  	public void setRootNode(NCRPNode rootNode) {
  		this.rootNode = rootNode;
  	}
  }//end class
  
  