code: package experiment.parser;
  
  import experiment.ont.*;
  import experiment.util.*;
  import experiment.structure.*;
  import experiment.structure.nodes.*;
  
  import java.io.*;
  import java.util.*;
  import java.util.stream.*;
  import org.semanticweb.owlapi.util.*;
  import org.semanticweb.owlapi.model.OWLOntologyManager;
  import org.semanticweb.owlapi.apibinding.OWLManager;
  import org.semanticweb.owlapi.model.parameters.Imports;
  import org.semanticweb.owlapi.model.parameters.*;
  import org.semanticweb.owlapi.formats.OWLXMLDocumentFormat;
  import org.semanticweb.owlapi.formats.RDFXMLDocumentFormat;
  import org.semanticweb.owlapi.model.*;
  import org.semanticweb.owlapi.reasoner.*;
  import org.semanticweb.HermiT.ReasonerFactory;
  import java.util.logging.Logger;
  import java.util.logging.ConsoleHandler;
  import java.util.logging.Level;
  import java.util.logging.*;
  import org.semanticweb.elk.owlapi.ElkReasonerFactory;
  import org.semanticweb.owlapi.change.AxiomChangeData;
  import org.semanticweb.owlapi.search.EntitySearcher; 
  
  import org.jgrapht.*;
  import org.jgrapht.graph.*;
  import org.jgrapht.traverse.*;
  
  
  import uk.ac.manchester.cs.owlapi.modularity.SyntacticLocalityModuleExtractor;
  import uk.ac.manchester.cs.owlapi.modularity.ModuleType;
  
  /**
   * Class Expression Visitor 
   */
  public class SyntaxTreeBuilder extends TreeBuilder
      implements OWLAxiomVisitor,
                 OWLClassExpressionVisitor,
                 OWLPropertyExpressionVisitor,
                 OWLIndividualVisitor,
                 OWLDataRangeVisitor,
                 OWLDataVisitor {
  
  
      private SimpleDirectedGraph<SyntaxNode, DefaultEdge> syntaxTree;
      private SyntaxNode root;
      private SyntaxNode previousCall;
  
      private AxiomVisitor axiomVisitor;
  
      public SyntaxTreeBuilder(){
          this.axiomVisitor = new AxiomVisitor();
      }
  
      public SyntaxTree build(OWLAxiom axiom){
          this.syntaxTree = new SimpleDirectedGraph<>(DefaultEdge.class);
          axiom.accept(this);
          return new SyntaxTree(this.syntaxTree, this.root);
      }
  
      public SyntaxTree build(OWLClassExpression ce){
          this.syntaxTree = new SimpleDirectedGraph<>(DefaultEdge.class);
          this.parseRoot(ce); 
          return new SyntaxTree(this.syntaxTree, this.root);
      }
  
  //===============================================================
  //===================AXIOM VISITOR===========================
  //===============================================================
  
      private void parseRoot(OWLAxiom axiom){
          axiom.accept(this.axiomVisitor);
          SyntaxNode node = this.axiomVisitor.getSyntaxNode();
          this.root = node;
          this.syntaxTree.addVertex(node);
          this.previousCall = node; 
      }
  
      public void visit(OWLAsymmetricObjectPropertyAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLClassAssertionAxiom axiom){
          this.parseRoot(axiom); 
      }
      public void visit(OWLDataPropertyAssertionAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLDataPropertyDomainAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLDataPropertyRangeAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLDifferentIndividualsAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLDisjointClassesAxiom axiom){
          this.parseRoot(axiom);
  
          Stream<OWLClassExpression> ops = axiom.operands();
          Set<OWLClassExpression> classes = ops.collect(Collectors.toSet()); 
          SyntaxNode parent = this.previousCall;
          for(OWLClassExpression c : classes){
              this.previousCall = parent;
              this.addNode(c);
              c.accept(this);
          }
      }
      public void visit(OWLDisjointDataPropertiesAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLDisjointObjectPropertiesAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLDisjointUnionAxiom axiom){
          this.parseRoot(axiom);
  
          SyntaxNode parent = this.previousCall;
          OWLClassExpression union = axiom.getOWLClass();
  
          UnionNode node = new UnionNode(union); 
          this.syntaxTree.addVertex(node);
          this.syntaxTree.addEdge(this.previousCall,node); 
          this.previousCall = node; 
          union.accept(this);
  
          this.previousCall = parent;
          Stream<OWLClassExpression> ops = axiom.operands();
          Set<OWLClassExpression> operands = ops.collect(Collectors.toSet()); 
  
          for(OWLClassExpression o : operands){
              this.previousCall = parent;
              this.addNode(o);
              o.accept(this); 
          }
  
      }
      public void visit(OWLEquivalentClassesAxiom axiom){
          this.parseRoot(axiom);
          Stream<OWLClassExpression> ops = axiom.operands();
          Set<OWLClassExpression> classes = ops.collect(Collectors.toSet());
  
          SyntaxNode parent = this.previousCall;
          for(OWLClassExpression c : classes){
              this.previousCall = parent;
  
              this.addNode(c);
  
              c.accept(this);
          }
      }
      public void visit(OWLEquivalentDataPropertiesAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLEquivalentObjectPropertiesAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLFunctionalDataPropertyAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLFunctionalObjectPropertyAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLHasKeyAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLInverseFunctionalObjectPropertyAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLInverseObjectPropertiesAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLIrreflexiveObjectPropertyAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLNegativeDataPropertyAssertionAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLNegativeObjectPropertyAssertionAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLObjectPropertyAssertionAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLObjectPropertyDomainAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLObjectPropertyRangeAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLReflexiveObjectPropertyAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLSameIndividualAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLSubClassOfAxiom axiom){
          this.parseRoot(axiom);
          SyntaxNode parent = this.previousCall;
  
          OWLClassExpression subClass = axiom.getSubClass(); 
          SubClassOfNode subnode = new SubClassOfNode(subClass); 
          this.syntaxTree.addVertex(subnode);
          this.syntaxTree.addEdge(this.previousCall,subnode); 
          this.previousCall = subnode; 
          subClass.accept(this);
  
          this.previousCall = parent;
          OWLClassExpression superClass = axiom.getSuperClass();
          SuperClassOfNode node = new SuperClassOfNode(superClass); 
          this.syntaxTree.addVertex(node);
          this.syntaxTree.addEdge(this.previousCall,node); 
          this.previousCall = node; 
          superClass.accept(this); 
      }
      public void visit(OWLSubDataPropertyOfAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLSubObjectPropertyOfAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLSubPropertyChainOfAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLSymmetricObjectPropertyAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLTransitiveObjectPropertyAxiom axiom) {
          this.parseRoot(axiom);
      }
  
  
      public void visit(SWRLRule node){
          System.out.println("Parsed a SWRLRule - cannot be handled");
      }
      public void doDefault(Object object){
          System.out.println("Parsed an Object in 'doDefault' - cannot be handled"); 
      }
      public void getDefaultReturnValue(Object object){
          System.out.println("Parsed an Object in 'getDefaultReturnValue' - cannot be handled"); 
      }
      public void handleDefault(Object c){
          System.out.println("Parsed an Object in 'handleDefault' - cannot be handled"); 
      }
      //-----------------
      public void visit(OWLAnnotationAssertionAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLAnnotationPropertyDomainAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLAnnotationPropertyRangeAxiom axiom){
          this.parseRoot(axiom);
      }
      public void visit(OWLSubAnnotationPropertyOfAxiom axiom){
          this.parseRoot(axiom);
      }
  //===============================================================
  //============CLASS EXPRESSIONS VISITOR==========================
  //===============================================================
  //
      private void parseRoot(OWLClassExpression ce){
          SyntaxNode node = new ClassNode(ce);
          this.root = node;
          this.syntaxTree.addVertex(node);
          this.previousCall = node; 
          ce.accept(this);
      }
  
      private void addNode(OWLClassExpression expr){ 
          ClassNode node = new ClassNode(expr); 
          this.syntaxTree.addVertex(node);
          if(this.previousCall != null){
              this.syntaxTree.addEdge(this.previousCall,node); 
          }
          this.previousCall = node; 
      }
  
      public void visit(OWLClass ce){ 
          this.previousCall = null; 
      }
  
      public void visit(OWLDataAllValuesFrom ce){ 
  
          SyntaxNode parent = this.previousCall;
          OWLPropertyExpression property = ce.getProperty();
          this.addNode(property);
  
          this.previousCall = parent; 
          OWLDataRange range = (OWLDataRange) ce.getFiller(); 
          this.addNode(range);
          range.accept(this);
      }
      public void visit(OWLDataExactCardinality ce){ 
          int cardinality = ce.getCardinality();
          CardinalityNode cardNode = new CardinalityNode(cardinality);
          this.syntaxTree.addVertex(cardNode); 
          this.syntaxTree.addEdge(this.previousCall,cardNode); 
  
          SyntaxNode parent = this.previousCall;
  
          OWLDataPropertyExpression pe = ce.getProperty(); 
          this.addNode(pe);
          pe.accept(this);
  
          this.previousCall = parent;
  
          OWLDataRange dataRange = ce.getFiller();
          if(dataRange != null){
              this.addNode(dataRange);
              dataRange.accept(this);
          }
      }
      public void visit(OWLDataHasValue ce){ 
          SyntaxNode parent = this.previousCall;
          OWLDataPropertyExpression pe = ce.getProperty();
          this.addNode(pe);
          pe.accept(this);
  
          this.previousCall = parent;
  
          OWLLiteral filler = ce.getFiller();
          this.addNode(filler);
          filler.accept(this); 
      }
      public void visit(OWLDataMaxCardinality ce){ 
          int cardinality = ce.getCardinality();
          CardinalityNode cardNode = new CardinalityNode(cardinality);
          this.syntaxTree.addVertex(cardNode); 
          this.syntaxTree.addEdge(this.previousCall,cardNode); 
  
          SyntaxNode parent = this.previousCall;
  
          OWLDataPropertyExpression pe = ce.getProperty(); 
          this.addNode(pe);
          pe.accept(this);
  
          this.previousCall = parent;
  
          OWLDataRange dataRange = ce.getFiller();
          if(dataRange != null){
              this.addNode(dataRange);
              dataRange.accept(this);
          }
      }
      public void visit(OWLDataMinCardinality ce){ 
          int cardinality = ce.getCardinality();
          CardinalityNode cardNode = new CardinalityNode(cardinality);
          this.syntaxTree.addVertex(cardNode); 
          this.syntaxTree.addEdge(this.previousCall,cardNode); 
  
          SyntaxNode parent = this.previousCall;
  
          OWLDataPropertyExpression pe = ce.getProperty(); 
          this.addNode(pe);
          pe.accept(this);
  
          this.previousCall = parent;
  
          OWLDataRange dataRange = ce.getFiller();
          if(dataRange != null){
              this.addNode(dataRange);
              dataRange.accept(this);
          }
      }
      public void visit(OWLDataSomeValuesFrom ce){ 
          SyntaxNode parent = this.previousCall;
          OWLPropertyExpression property = ce.getProperty();
          this.addNode(property);
  
          this.previousCall = parent; 
          OWLDataRange range = (OWLDataRange) ce.getFiller(); 
          this.addNode(range);
          range.accept(this);
      }
  
      public void visit(OWLObjectOneOf ce){ 
          Set<OWLIndividual> individuals = ce.getIndividuals();
          SyntaxNode parent = this.previousCall;
          for(OWLIndividual i : individuals){
              this.previousCall = parent;
              this.addNode(i);
          }
          this.previousCall = null;
      }
  
      public void visit(OWLObjectHasSelf ce){ 
          OWLObjectPropertyExpression pe = ce.getProperty();
          this.addNode(pe);
          pe.accept(this);
      }
  
      public void visit(OWLObjectHasValue ce){ 
          OWLIndividual individual = (OWLIndividual) ce.getFiller();
          SyntaxNode parent = this.previousCall;
          this.addNode(individual);
  
          this.previousCall = parent; 
          OWLPropertyExpression property = ce.getProperty();
          this.addNode(property);
          property.accept(this); 
      }
  
      public void visit(OWLObjectAllValuesFrom ce){ 
          SyntaxNode parent = this.previousCall;
  
          OWLPropertyExpression property = ce.getProperty();
          this.addNode(property);
          property.accept(this);
  
          this.previousCall = parent;
  
          OWLClassExpression filler = ce.getFiller();
          this.addNode(filler);
          filler.accept(this); 
      }
      public void visit(OWLObjectComplementOf ce){ 
          OWLClassExpression complement = ce.getOperand();
          this.addNode(complement); 
          complement.accept(this);
      }
      public void visit(OWLObjectExactCardinality ce){
          SyntaxNode parent = this.previousCall;
  
          int cardinality = ce.getCardinality();
          CardinalityNode cardNode = new CardinalityNode(cardinality);
          this.syntaxTree.addVertex(cardNode); 
          this.syntaxTree.addEdge(this.previousCall,cardNode); 
  
          OWLPropertyExpression property = ce.getProperty();
          this.addNode(property);
          property.accept(this);
  
          this.previousCall = parent;
  
          OWLClassExpression filler = ce.getFiller();
          this.addNode(filler);
          filler.accept(this); 
  
      }
      public void visit(OWLObjectIntersectionOf ce){
          Set<OWLClassExpression> operands = ce.getOperands();
          SyntaxNode parent = this.previousCall;
  
          for(OWLClassExpression o : operands){
              this.previousCall = parent;
              this.addNode(o);
              o.accept(this);
          }
      }
      public void visit(OWLObjectMaxCardinality ce){
          SyntaxNode parent = this.previousCall;
  
          int cardinality = ce.getCardinality();
          CardinalityNode cardNode = new CardinalityNode(cardinality);
          this.syntaxTree.addVertex(cardNode); 
          this.syntaxTree.addEdge(this.previousCall,cardNode); 
  
          OWLPropertyExpression property = ce.getProperty();
          this.addNode(property);
          property.accept(this);
  
          this.previousCall = parent;
  
          OWLClassExpression filler = ce.getFiller();
          this.addNode(filler);
          filler.accept(this); 
      }
      public void visit(OWLObjectMinCardinality ce){
          SyntaxNode parent = this.previousCall;
  
          int cardinality = ce.getCardinality();
          CardinalityNode cardNode = new CardinalityNode(cardinality);
          this.syntaxTree.addVertex(cardNode); 
          this.syntaxTree.addEdge(this.previousCall,cardNode); 
  
          OWLPropertyExpression property = ce.getProperty();
          this.addNode(property);
          property.accept(this);
  
          this.previousCall = parent;
  
          OWLClassExpression filler = ce.getFiller();
          this.addNode(filler);
          filler.accept(this); 
      }
      public void visit(OWLObjectSomeValuesFrom ce){
          SyntaxNode parent = this.previousCall;
          OWLPropertyExpression property = ce.getProperty();
          this.addNode(property);
          property.accept(this);
  
          this.previousCall = parent;
  
          OWLClassExpression filler = ce.getFiller();
          this.addNode(filler);
          filler.accept(this); 
      }
      public void visit(OWLObjectUnionOf ce){
          Set<OWLClassExpression> operands = ce.getOperands();
          SyntaxNode parent = this.previousCall;
          for(OWLClassExpression o : operands){
              this.previousCall = parent;
              this.addNode(o);
              o.accept(this);
          }
      } 
  
  
      //===============================================================
      //============Property EXPRESSIONS VISITOR==========================
      //===============================================================
      private void addNode(OWLPropertyExpression expr){ 
          PropertyNode node = new PropertyNode(expr); 
          this.syntaxTree.addVertex(node);
          if(this.previousCall != null){
              this.syntaxTree.addEdge(this.previousCall,node); 
          }
          this.previousCall = node; 
      }
  
      public void visit(OWLObjectInverseOf property){
          OWLObjectPropertyExpression pe = property.getInverse();
          this.addNode(pe);
          pe.accept(this); 
      }
  
      public void visit(OWLObjectProperty property){
          this.previousCall = null; 
      }
  
      public void visit(OWLDataProperty property){
          this.previousCall = null;
      }
  
      public void visit(OWLAnnotationProperty property){
          ;
      }
  
      //===============================================================
      //============Individual VISITOR==========================
      //===============================================================
      private void addNode(OWLIndividual i){ 
          IndividualNode node = new IndividualNode(i); 
          this.syntaxTree.addVertex(node);
          if(this.previousCall != null){
              this.syntaxTree.addEdge(this.previousCall,node); 
          }
          this.previousCall = node; 
      }
  
      public void visit(OWLAnonymousIndividual individual){
          this.previousCall = null; 
      }
      public void visit(OWLNamedIndividual individual){
          this.previousCall = null; 
      }
  
      //===============================================================
      //============Data Range VISITOR==========================
      //===============================================================
      private void addNode(OWLDataRange r){
          DataRangeNode node = new DataRangeNode(r);
          this.syntaxTree.addVertex(node);
          if(this.previousCall != null){
              this.syntaxTree.addEdge(this.previousCall,node); 
          }
          this.previousCall = node; 
      }
  
      private void addNode(OWLLiteral l){
          LiteralNode node = new LiteralNode(l);
          this.syntaxTree.addVertex(node);
          if(this.previousCall != null){
              this.syntaxTree.addEdge(this.previousCall,node); 
          }
          this.previousCall = node; 
      }
  
      private void addNode(OWLFacetRestriction r){
          FacetRestrictionNode node = new FacetRestrictionNode(r);
          this.syntaxTree.addVertex(node);
          if(this.previousCall != null){
              this.syntaxTree.addEdge(this.previousCall,node); 
          }
          this.previousCall = node; 
      }
  
      public void visit(OWLDataComplementOf node){
          OWLDataRange r = node.getDataRange();
          this.addNode(r);
          r.accept(this);
      }
      public void visit(OWLDataIntersectionOf node){
          Set<OWLDataRange> rs = node.getOperands();
          SyntaxNode parent = this.previousCall;
          for(OWLDataRange r : rs){
              this.previousCall = parent;
              this.addNode(r);
              r.accept(this); 
          } 
      }
      public void visit(OWLDataOneOf node){
          Set<OWLLiteral> ls = node.getValues();
          SyntaxNode parent = this.previousCall;
          for(OWLLiteral l : ls){
              this.previousCall = parent;
              this.addNode(l);
              l.accept(this); 
          }
  
      }
      public void visit(OWLDatatypeRestriction node){
          SyntaxNode parent = this.previousCall;
  
          OWLDatatype dt = node.getDatatype();
          this.addNode(dt);
          dt.accept(this);
  
          Set<OWLFacetRestriction> rs = node.getFacetRestrictions();
          for(OWLFacetRestriction r : rs){
              this.previousCall = parent;
              this.addNode(r);
              r.accept(this);
          } 
      }
      public void visit(OWLDataUnionOf node){
          Set<OWLDataRange> rs = node.getOperands();
          SyntaxNode parent = this.previousCall;
          for(OWLDataRange r : rs){
              this.previousCall = parent;
              this.addNode(r);
              r.accept(this); 
          } 
      } 
  
      public void visit(OWLDatatype node){
          this.previousCall = null;
      } 
      public void visit(OWLLiteral node){
          this.previousCall = null;
      }
      public void visit(OWLFacetRestriction node){
          OWLLiteral facetValue = node.getFacetValue();
          this.addNode(facetValue);
          facetValue.accept(this);
      }
  }
  