/**
  * Get the site that the siteMaster references
  *
  * @param siteMaster
  * @return
  */
 private String getSiteMasterSite(SearchBuilderItem siteMaster) {
   if (siteMaster.getName().startsWith(SearchBuilderItem.INDEX_MASTER)
       && !SearchBuilderItem.GLOBAL_CONTEXT.equals(siteMaster.getContext())) {
     // this depends on the pattern, perhapse it should be a parse
     return siteMaster.getName().substring(SearchBuilderItem.INDEX_MASTER.length() + 1);
   }
   return null;
 }
 /**
  * get the action for the site master
  *
  * @param siteMaster
  * @return
  */
 private Integer getSiteMasterAction(SearchBuilderItem siteMaster) {
   if (siteMaster.getName().startsWith(SearchBuilderItem.INDEX_MASTER)
       && !SearchBuilderItem.GLOBAL_CONTEXT.equals(siteMaster.getContext())) {
     if (SearchBuilderItem.STATE_PENDING.equals(siteMaster.getSearchstate())) {
       return siteMaster.getSearchaction();
     }
   }
   return SearchBuilderItem.STATE_UNKNOWN;
 }
  private void refreshIndex(Connection connection, SearchBuilderItem controlItem)
      throws SQLException {
    // delete all and return the master action only
    // the caller will then rebuild the index from scratch
    log.debug(
        "UPDATE ALL RECORDS =========================================================="); //$NON-NLS-1$
    Statement stm = null;
    try {
      stm = connection.createStatement();
      if (SearchBuilderItem.GLOBAL_CONTEXT.equals(controlItem.getContext())) {
        stm.execute(
            "update searchbuilderitem set searchstate = " //$NON-NLS-1$
                + SearchBuilderItem.STATE_PENDING
                + " where itemscope = "
                + SearchBuilderItem.ITEM); // $NON-NLS-1$

      } else {
        stm.execute(
            "update searchbuilderitem set searchstate = " //$NON-NLS-1$
                + SearchBuilderItem.STATE_PENDING
                + " where itemscope = "
                + SearchBuilderItem.ITEM_SITE_MASTER
                + " and context = '"
                + controlItem.getContext() // $NON-NLS-1$
                + "' and name <> '"
                + controlItem.getName()
                + "'"); //$NON-NLS-1$ //$NON-NLS-2$
      }
      controlItem.setSearchstate(SearchBuilderItem.STATE_COMPLETED);
      updateOrSave(connection, controlItem);
      connection.commit();
    } finally {
      try {
        stm.close();
      } catch (Exception ex) {
        log.debug(ex);
      }
      ;
    }
  }
  private void rebuildIndex(
      Connection connection, SearchBuilderItem controlItem, SearchIndexBuilderWorker worker)
      throws SQLException {
    // delete all and return the master action only
    // the caller will then rebuild the index from scratch
    log.info(
        "DELETE ALL RECORDS =========================================================="); //$NON-NLS-1$
    Statement stm = null;
    try {
      stm = connection.createStatement();
      if (SearchBuilderItem.GLOBAL_CONTEXT.equals(controlItem.getContext())) {
        stm.execute(
            "delete from searchbuilderitem where itemscope = "
                + SearchBuilderItem.ITEM
                + " or itemscope = "
                + SearchBuilderItem.ITEM_SITE_MASTER); // $NON-NLS-1$
      } else {
        stm.execute("delete from searchbuilderitem where itemscope = " + SearchBuilderItem.ITEM);
        stm.execute(
            "delete from searchbuilderitem where context = '" //$NON-NLS-1$
                + controlItem.getContext()
                + "' and name <> '" //$NON-NLS-1$
                + controlItem.getName()
                + "' "); //$NON-NLS-1$
      }

      log.debug(
          "DONE DELETE ALL RECORDS ==========================================================="); //$NON-NLS-1$
      connection.commit();
      log.debug(
          "ADD ALL RECORDS ==========================================================="); //$NON-NLS-1$
      long lastupdate = System.currentTimeMillis();
      List<String> contextList = new ArrayList<String>();
      if (SearchBuilderItem.GLOBAL_CONTEXT.equals(controlItem.getContext())) {

        for (Iterator<Site> i =
                SiteService.getSites(SelectionType.ANY, null, null, null, SortType.NONE, null)
                    .iterator();
            i.hasNext(); ) {
          Site s = (Site) i.next();
          if (!SiteService.isSpecialSite(s.getId())) {
            if (searchIndexBuilder.isOnlyIndexSearchToolSites()) {
              ToolConfiguration t = s.getToolForCommonId("sakai.search"); // $NON-NLS-1$
              if (t != null) {
                contextList.add(s.getId());
              }
            } else if (!(searchIndexBuilder.isExcludeUserSites()
                && SiteService.isUserSite(s.getId()))) {
              contextList.add(s.getId());
            }
          }
        }
      } else {
        contextList.add(controlItem.getContext());
      }
      for (Iterator<String> c = contextList.iterator(); c.hasNext(); ) {
        String siteContext = (String) c.next();
        log.debug("Rebuild for " + siteContext); // $NON-NLS-1$
        for (Iterator<EntityContentProducer> i =
                searchIndexBuilder.getContentProducers().iterator();
            i.hasNext(); ) {
          EntityContentProducer ecp = (EntityContentProducer) i.next();

          Iterator<String> contentIterator = null;
          contentIterator = ecp.getSiteContentIterator(siteContext);
          log.debug("Using ECP " + ecp); // $NON-NLS-1$

          int added = 0;
          for (; contentIterator.hasNext(); ) {
            if ((System.currentTimeMillis() - lastupdate) > 60000L) {
              lastupdate = System.currentTimeMillis();
              if (!worker.getLockTransaction(15L * 60L * 1000L, true)) {
                throw new RuntimeException(
                    "Transaction Lock Expired while Rebuilding Index "); //$NON-NLS-1$
              }
            }
            String resourceName = (String) contentIterator.next();
            log.debug("Checking " + resourceName); // $NON-NLS-1$
            if (resourceName == null || resourceName.length() > 255) {
              log.warn(
                  "Entity Reference Longer than 255 characters, ignored: Reference=" //$NON-NLS-1$
                      + resourceName);
              continue;
            }
            SearchBuilderItem sbi = new SearchBuilderItemImpl();
            sbi.setName(resourceName);
            sbi.setSearchaction(SearchBuilderItem.ACTION_ADD);
            sbi.setSearchstate(SearchBuilderItem.STATE_PENDING);
            sbi.setId(UUID.randomUUID().toString());
            sbi.setVersion(new Date(System.currentTimeMillis()));
            sbi.setItemscope(SearchBuilderItem.ITEM);
            String context = null;
            try {
              context = ecp.getSiteId(resourceName);
            } catch (Exception ex) {
              log.debug(
                  "No context for resource "
                      + resourceName //$NON-NLS-1$
                      + " defaulting to none"); //$NON-NLS-1$
            }
            if (context == null || context.length() == 0) {
              context = "none"; // $NON-NLS-1$
            }
            sbi.setContext(context);
            try {
              updateOrSave(connection, sbi);
            } catch (SQLException sqlex) {
              log.error("Failed to update " + sqlex.getMessage()); // $NON-NLS-1$
            }
            connection.commit();
          }
          log.debug(" Added " + added); // $NON-NLS-1$
        }
      }
      log.info(
          "DONE ADD ALL RECORDS ==========================================================="); //$NON-NLS-1$
      controlItem.setSearchstate(SearchBuilderItem.STATE_COMPLETED);
      updateOrSave(connection, controlItem);
      connection.commit();
    } finally {
      try {
        stm.close();
      } catch (Exception ex) {
        log.debug(ex);
      }
    }
  }