private void waitForTBoxReasoning(PelletListener pelletListener) throws InterruptedException {
   int sleeps = 0;
   while (sleeps < 1000 && pelletListener.isReasoning()) {
     if ((sleeps % 10) == 0) { // print message at 10 second intervals
       log.info("Waiting for initial TBox reasoning to complete");
     }
     Thread.sleep(1000);
     sleeps++;
   }
 }
    public void run() {
      while (pelletListener.isDirty()) {
        // pipeOpen = false;
        try {
          pelletListener.setDirty(false);
          inferenceRounds++;
          log.info("Getting new inferences");
          long startTime = System.currentTimeMillis();
          LinkedList<ObjectPropertyStatementPattern> irpl =
              new LinkedList<ObjectPropertyStatementPattern>();

          if (inferenceReceivingPatternAllowSet != null) {
            irpl.addAll(inferenceReceivingPatternAllowSet);
          } else {
            irpl.add(ObjectPropertyStatementPatternFactory.getPattern(null, null, null));
          }

          if (reasonerConfiguration.getQueryForAllObjectProperties()) {
            pelletModel.enterCriticalSection(Lock.READ);
            try {
              ClosableIterator closeIt = pelletModel.listObjectProperties();
              try {
                for (Iterator objPropIt = closeIt; objPropIt.hasNext(); ) {
                  ObjectProperty objProp = (ObjectProperty) objPropIt.next();
                  if (!("http://www.w3.org/2002/07/owl#".equals(objProp.getNameSpace()))) {
                    irpl.add(ObjectPropertyStatementPatternFactory.getPattern(null, objProp, null));
                  }
                }
              } finally {
                closeIt.close();
              }
            } finally {
              pelletModel.leaveCriticalSection();
            }
            deletedObjectProperties.enterCriticalSection(Lock.WRITE);
            try {
              ClosableIterator sit = deletedObjectProperties.listSubjects();
              try {
                while (sit.hasNext()) {
                  Resource subj = (Resource) sit.next();
                  irpl.add(
                      ObjectPropertyStatementPatternFactory.getPattern(
                          null, ResourceFactory.createProperty(subj.getURI()), null));
                }
              } finally {
                sit.close();
              }
              deletedObjectProperties.removeAll();
            } finally {
              deletedObjectProperties.leaveCriticalSection();
            }
          }

          if (reasonerConfiguration.getQueryForAllDatatypeProperties()) {
            pelletModel.enterCriticalSection(Lock.READ);
            try {
              ClosableIterator closeIt = pelletModel.listDatatypeProperties();
              try {
                for (Iterator dataPropIt = closeIt; dataPropIt.hasNext(); ) {
                  DatatypeProperty dataProp = (DatatypeProperty) dataPropIt.next();
                  if (!("http://www.w3.org/2002/07/owl#".equals(dataProp.getNameSpace()))) {
                    // TODO: THIS WILL WORK, BUT NEED TO GENERALIZE THE PATTERN CLASSES
                    irpl.add(
                        ObjectPropertyStatementPatternFactory.getPattern(null, dataProp, null));
                  }
                }
              } finally {
                closeIt.close();
              }
            } finally {
              pelletModel.leaveCriticalSection();
            }
            deletedDataProperties.enterCriticalSection(Lock.WRITE);
            try {
              ClosableIterator sit = deletedDataProperties.listSubjects();
              try {
                while (sit.hasNext()) {
                  Resource subj = (Resource) sit.next();
                  irpl.add(
                      ObjectPropertyStatementPatternFactory.getPattern(
                          null, ResourceFactory.createProperty(subj.getURI()), null));
                }
              } finally {
                sit.close();
              }
              deletedDataProperties.removeAll();
            } finally {
              deletedDataProperties.leaveCriticalSection();
            }
          }

          int addCount = 0;
          int retractCount = 0;

          // force new reasoner (disabled)
          if (false && !reasonerConfiguration.isIncrementalReasoningEnabled()) {
            Model baseModel = pelletModel.getBaseModel();
            pelletModel = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
            pelletModel.getDocumentManager().setProcessImports(false);
            pelletModel.add(baseModel);
          }

          pelletModel.enterCriticalSection(Lock.WRITE);
          try {
            pelletModel.rebind();
            pelletModel.prepare();
          } finally {
            pelletModel.leaveCriticalSection();
          }

          for (Iterator<ObjectPropertyStatementPattern> patIt = irpl.iterator();
              patIt.hasNext(); ) {
            ObjectPropertyStatementPattern pat = patIt.next();

            if (log.isDebugEnabled()) {
              String subjStr = (pat.getSubject() != null) ? pat.getSubject().getURI() : "*";
              String predStr = (pat.getPredicate() != null) ? pat.getPredicate().getURI() : "*";
              String objStr = (pat.getObject() != null) ? pat.getObject().getURI() : "*";
              log.debug("Querying for " + subjStr + " : " + predStr + " : " + objStr);
            }

            Model tempModel = ModelFactory.createDefaultModel();

            pelletModel.enterCriticalSection(Lock.READ);
            try {

              ClosableIterator ci =
                  pelletModel.listStatements(pat.getSubject(), pat.getPredicate(), pat.getObject());
              try {
                for (ClosableIterator i = ci; i.hasNext(); ) {
                  Statement stmt = (Statement) i.next();

                  boolean reject = false;

                  // this next part is only needed if we're using Jena's OWL reasoner instead of
                  // actually using Pellet
                  try {
                    if ((((Resource) stmt.getObject()).equals(RDFS.Resource))) {
                      reject = true;
                    } else if ((((Resource) stmt.getSubject()).equals(OWL.Nothing))) {
                      reject = true;
                    } else if ((((Resource) stmt.getObject()).equals(OWL.Nothing))) {
                      reject = true;
                    }
                  } catch (Exception e) {
                  }

                  if (!reject) {
                    tempModel.add(stmt);

                    boolean fullModelContainsStatement = false;
                    fullModel.enterCriticalSection(Lock.READ);
                    try {
                      fullModelContainsStatement = fullModel.contains(stmt);
                    } finally {
                      fullModel.leaveCriticalSection();
                    }

                    if (!fullModelContainsStatement) {
                      // in theory we should be able to lock only the inference model, but I'm not
                      // sure yet if Jena propagates the locking upward
                      fullModel.enterCriticalSection(Lock.WRITE);
                      closePipe();
                      try {
                        inferenceModel.add(stmt);
                        addCount++;
                      } finally {
                        openPipe();
                        fullModel.leaveCriticalSection();
                      }
                    }
                  }
                }
              } finally {
                ci.close();
              }
            } finally {
              pelletModel.leaveCriticalSection();
            }

            // now we see what's in the inference model that isn't in the temp model and remove it

            try {
              Queue<Statement> localRemovalQueue = new LinkedList<Statement>();
              inferenceModel.enterCriticalSection(Lock.READ);
              try {
                ClosableIterator ci =
                    inferenceModel.listStatements(
                        pat.getSubject(), pat.getPredicate(), pat.getObject());
                try {
                  for (ClosableIterator i = ci; i.hasNext(); ) {
                    Statement stmt = (Statement) i.next();
                    if (!tempModel.contains(stmt)) {
                      localRemovalQueue.add(stmt);
                    }
                  }
                } finally {
                  ci.close();
                }
              } finally {
                inferenceModel.leaveCriticalSection();
              }
              for (Iterator<Statement> i = localRemovalQueue.iterator(); i.hasNext(); ) {
                fullModel.enterCriticalSection(Lock.WRITE);
                closePipe();
                try {
                  retractCount++;
                  inferenceModel.remove(i.next());
                } finally {
                  openPipe();
                  fullModel.leaveCriticalSection();
                }
              }

              localRemovalQueue.clear();
            } catch (Exception e) {
              log.error("Error getting inferences", e);
            }
            tempModel = null;
          }
          this.pelletListener.isConsistent = true;
          this.pelletListener.inErrorState = false;
          this.pelletListener.explanation = "";
          if (log.isDebugEnabled()) {
            log.info("Added " + addCount + " statements entailed by assertions");
            log.info("Retracted " + retractCount + " statements no longer entailed by assertions");
            log.info(
                "Done getting new inferences: "
                    + (System.currentTimeMillis() - startTime) / 1000
                    + " seconds");
          }
        } catch (InconsistentOntologyException ioe) {
          this.pelletListener.isConsistent = false;
          String explanation = ((PelletInfGraph) pelletModel.getGraph()).getKB().getExplanation();
          this.pelletListener.explanation = explanation;
          log.error(ioe);
          log.error(explanation);
        } catch (Exception e) {
          this.pelletListener.inErrorState = true;
          log.error("Exception during inference", e);
        } finally {
          pelletListener.endReasoning();
        }
      }
    }
  @Override
  public void contextInitialized(ServletContextEvent sce) {
    try {
      // set up Pellet reasoning for the TBox

      OntModelSelector assertionsOms =
          ModelContext.getBaseOntModelSelector(sce.getServletContext());
      OntModelSelector inferencesOms =
          ModelContext.getInferenceOntModelSelector(sce.getServletContext());
      OntModelSelector unionOms = ModelContext.getUnionOntModelSelector(sce.getServletContext());

      WebappDaoFactoryJena wadf =
          (WebappDaoFactoryJena) sce.getServletContext().getAttribute("webappDaoFactory");

      if (!assertionsOms
          .getTBoxModel()
          .getProfile()
          .NAMESPACE()
          .equals(OWL.NAMESPACE.getNameSpace())) {
        log.error("Not connecting Pellet reasoner - the TBox assertions model is not an OWL model");
        return;
      }

      // Set various Pellet options for incremental consistency checking, etc.
      PelletOptions.DL_SAFE_RULES = true;
      PelletOptions.USE_COMPLETION_QUEUE = true;
      PelletOptions.USE_TRACING = true;
      PelletOptions.TRACK_BRANCH_EFFECTS = true;
      PelletOptions.USE_INCREMENTAL_CONSISTENCY = true;
      PelletOptions.USE_INCREMENTAL_DELETION = true;

      PelletListener pelletListener =
          new PelletListener(
              unionOms.getTBoxModel(),
              assertionsOms.getTBoxModel(),
              inferencesOms.getTBoxModel(),
              ReasonerConfiguration.DEFAULT);
      sce.getServletContext().setAttribute("pelletListener", pelletListener);
      sce.getServletContext().setAttribute("pelletOntModel", pelletListener.getPelletModel());

      if (wadf != null) {
        wadf.setPelletListener(pelletListener);
      }

      log.info("Pellet reasoner connected for the TBox");

      // set up simple reasoning for the ABox

      ServletContext ctx = sce.getServletContext();
      BasicDataSource bds = JenaDataSourceSetupBase.getApplicationDataSource(ctx);
      String dbType =
          ConfigurationProperties.getBean(ctx)
              .getProperty( // database type
                  "VitroConnection.DataSource.dbtype", "MySQL");

      Model rebuildModel =
          JenaDataSourceSetupBase.makeDBModel(
              bds,
              JENA_INF_MODEL_REBUILD,
              JenaDataSourceSetupBase.DB_ONT_MODEL_SPEC,
              TripleStoreType.SDB,
              dbType,
              ctx);
      Model scratchModel =
          JenaDataSourceSetupBase.makeDBModel(
              bds,
              JENA_INF_MODEL_SCRATCHPAD,
              JenaDataSourceSetupBase.DB_ONT_MODEL_SPEC,
              TripleStoreType.SDB,
              dbType,
              ctx);

      // the simple reasoner will register itself as a listener to the ABox assertions
      SimpleReasoner simpleReasoner =
          new SimpleReasoner(
              unionOms.getTBoxModel(),
              assertionsOms.getABoxModel(),
              inferencesOms.getABoxModel(),
              rebuildModel,
              scratchModel);
      sce.getServletContext().setAttribute(SimpleReasoner.class.getName(), simpleReasoner);

      StartupStatus ss = StartupStatus.getBean(ctx);
      List<ReasonerPlugin> pluginList = new ArrayList<ReasonerPlugin>();
      List<String> pluginClassnameList = this.readFileOfListeners(ctx);
      for (String classname : pluginClassnameList) {
        try {
          ReasonerPlugin plugin =
              (ReasonerPlugin) Class.forName(classname).getConstructors()[0].newInstance();
          pluginList.add(plugin);
        } catch (Throwable t) {
          ss.info(this, "Could not instantiate reasoner plugin " + classname);
        }
      }
      simpleReasoner.setPluginList(pluginList);

      if (isRecomputeRequired(sce.getServletContext())) {
        log.info("ABox inference recompute required.");
        waitForTBoxReasoning(pelletListener);
        if (JenaDataSourceSetupBase.isFirstStartup()) {
          simpleReasoner.recompute();
        } else {
          log.info("starting ABox inference recompute in a separate thread.");
          new Thread(new ABoxRecomputer(simpleReasoner), "ABoxRecomputer").start();
        }

      } else if (isMSTComputeRequired(sce.getServletContext())) {
        log.info("mostSpecificType computation required. It will be done in a separate thread.");
        waitForTBoxReasoning(pelletListener);
        new Thread(new MostSpecificTypeRecomputer(simpleReasoner), "MostSpecificTypeComputer")
            .start();
      }

      SimpleReasonerTBoxListener simpleReasonerTBoxListener =
          new SimpleReasonerTBoxListener(simpleReasoner);
      sce.getServletContext()
          .setAttribute(SimpleReasonerTBoxListener.class.getName(), simpleReasonerTBoxListener);
      assertionsOms.getTBoxModel().register(simpleReasonerTBoxListener);
      inferencesOms.getTBoxModel().register(simpleReasonerTBoxListener);

      log.info("Simple reasoner connected for the ABox");

    } catch (Throwable t) {
      t.printStackTrace();
    }
  }