/**
   * This prepares the package builder, loads the jars/classpath.
   *
   * @return true if everything is good to go, false if its all gone horribly wrong, and we can't
   *     even get the package header up.
   */
  private boolean preparePackage() {

    // firstly we loadup the classpath
    builder.addPackage(new PackageDescr(pkg.getName()));

    // now we deal with the header (imports, templates, globals).
    addDrl(ServiceImplementation.getDroolsHeader(pkg));
    loadDeclaredTypes();
    if (builder.hasErrors()) {
      recordBuilderErrors(pkg);
      // if we have any failures, lets drop out now, no point in going
      // any further
      return false;
    }

    loadDSLFiles();

    // finally, any functions we will load at this point.
    AssetItemIterator it = this.pkg.listAssetsByFormat(new String[] {AssetFormats.FUNCTION});
    while (it.hasNext()) {
      AssetItem func = (AssetItem) it.next();
      addDrl(func.getContent());
      if (builder.hasErrors()) {
        recordBuilderErrors(func);
        builder.clearErrors();
      }
    }

    return errors.size() == 0;
  }
  public PageResponse<QueryPageRow> queryMetaData(QueryMetadataPageRequest request)
      throws SerializationException {
    if (request == null) {
      throw new IllegalArgumentException("request cannot be null");
    }
    if (request.getPageSize() != null && request.getPageSize() < 0) {
      throw new IllegalArgumentException("pageSize cannot be less than zero.");
    }

    // Setup parameters for generic repository query
    Map<String, String[]> queryMap = createQueryMap(request.getMetadata());

    DateQuery[] dates = createDateQueryForRepository(request);

    long start = System.currentTimeMillis();
    AssetItemIterator iterator = rulesRepository.query(queryMap, request.isSearchArchived(), dates);
    log.debug("Search time: " + (System.currentTimeMillis() - start));

    List<QueryPageRow> rowList =
        new QueryMetadataPageRowBuilder().withPageRequest(request).withContent(iterator).build();
    boolean bHasMoreRows = iterator.hasNext();
    PageResponse<QueryPageRow> response =
        new PageResponseBuilder<QueryPageRow>()
            .withStartRowIndex(request.getStartRowIndex())
            .withPageRowList(rowList)
            .withLastPage(!bHasMoreRows)
            .buildWithTotalRowCount(
                -1); // its impossible to know the exact selected count until we'v reached
    // the end of iterator
    long methodDuration = System.currentTimeMillis() - start;
    log.debug("Queried repository (Metadata) in " + methodDuration + " ms.");
    return response;
  }
  public PageResponse<QueryPageRow> queryFullText(QueryPageRequest request)
      throws SerializationException {
    if (request == null) {
      throw new IllegalArgumentException("request cannot be null");
    }
    if (request.getPageSize() != null && request.getPageSize() < 0) {
      throw new IllegalArgumentException("pageSize cannot be less than zero.");
    }

    long start = System.currentTimeMillis();
    AssetItemIterator iterator =
        rulesRepository.queryFullText(request.getSearchText(), request.isSearchArchived());
    log.debug("Search time: " + (System.currentTimeMillis() - start));

    List<QueryPageRow> rowList =
        new QueryFullTextPageRowBuilder().withPageRequest(request).withContent(iterator).build();
    boolean bHasMoreRows = iterator.hasNext();
    PageResponse<QueryPageRow> response =
        new PageResponseBuilder<QueryPageRow>()
            .withStartRowIndex(request.getStartRowIndex())
            .withPageRowList(rowList)
            .withLastPage(!bHasMoreRows)
            .buildWithTotalRowCount(-1);

    long methodDuration = System.currentTimeMillis() - start;
    log.debug(
        "Queried repository (Full Text) for ("
            + request.getSearchText()
            + ") in "
            + methodDuration
            + " ms.");
    return response;
  }
  /** @deprecated in favour of {@link #queryMetaData(QueryMetadataPageRequest)} */
  public TableDataResult queryMetaData(
      final MetaDataQuery[] qr,
      Date createdAfter,
      Date createdBefore,
      Date modifiedAfter,
      Date modifiedBefore,
      boolean seekArchived,
      int skip,
      int numRows)
      throws SerializationException {
    if (numRows == 0) {
      throw new DetailedSerializationException(
          "Unable to return zero results (bug)",
          "probably have the parameters around the wrong way, sigh...");
    }

    Map<String, String[]> q =
        new HashMap<String, String[]>() {
          {
            for (MetaDataQuery aQr : qr) {
              String vals = (aQr.valueList == null) ? "" : aQr.valueList.trim();
              if (vals.length() > 0) {
                put(aQr.attribute, vals.split(",\\s?"));
              }
            }
          }
        };

    DateQuery[] dates = new DateQuery[2];

    dates[0] =
        new DateQuery(
            "jcr:created", DateUtil.isoDate(createdAfter), DateUtil.isoDate(createdBefore));
    dates[1] =
        new DateQuery(
            AssetItem.LAST_MODIFIED_PROPERTY_NAME,
            DateUtil.isoDate(modifiedAfter),
            DateUtil.isoDate(modifiedBefore));
    AssetItemIterator it = rulesRepository.query(q, seekArchived, dates);
    // Add Filter to check Permission
    List<AssetItem> resultList = new ArrayList<AssetItem>();

    RepositoryFilter categoryFilter = new CategoryFilter();

    while (it.hasNext()) {
      AssetItem ai = it.next();

      resultList.add(ai);
    }

    return new TableDisplayHandler("searchresults").loadRuleListTable(resultList, skip, numRows);
  }
 private void loadDeclaredTypes() {
   AssetItemIterator it = this.pkg.listAssetsByFormat(new String[] {AssetFormats.DRL_MODEL});
   while (it.hasNext()) {
     AssetItem as = it.next();
     try {
       builder.addPackageFromDrl(new StringReader(as.getContent()));
     } catch (DroolsParserException e) {
       this.errors.add(new ContentAssemblyError(as, "Parser exception: " + e.getMessage()));
     } catch (IOException e) {
       this.errors.add(new ContentAssemblyError(as, "IOException: " + e.getMessage()));
     }
   }
 }
  /**
   * Get the function DRLs as one string because they might be calling each others.
   *
   * @return
   */
  private StringBuilder getAllFunctionsAsOneString() {
    AssetItemIterator functionsIterator =
        this.packageItem.listAssetsWithVersionsSpecifiedByDependenciesByFormat(
            AssetFormats.FUNCTION);
    StringBuilder stringBuilder = new StringBuilder();

    while (functionsIterator.hasNext()) {
      AssetItem function = functionsIterator.next();
      if (!function.getDisabled()) {
        stringBuilder.append(function.getContent());
      }
    }

    return stringBuilder;
  }
  private void addDRLRulesToVerifier() {

    AssetItemIterator rules = packageItem.listAssetsByFormat(AssetFormats.DRL);

    while (rules.hasNext()) {
      AssetItem rule = rules.next();

      ContentHandler contentHandler = ContentManager.getHandler(rule.getFormat());
      if (contentHandler.isRuleAsset()) {
        IRuleAsset ruleAsset = (IRuleAsset) contentHandler;
        String drl = ruleAsset.getRawDRL(rule);
        verifier.addResourcesToVerify(
            ResourceFactory.newReaderResource(new StringReader(drl)), ResourceType.DRL);
      }
    }
  }
  private void loadDeclaredTypes() {
    AssetItemIterator declaredTypesIterator =
        this.packageItem.listAssetsWithVersionsSpecifiedByDependenciesByFormat(
            AssetFormats.DRL_MODEL);

    while (declaredTypesIterator.hasNext()) {
      AssetItem assetItem = declaredTypesIterator.next();
      if (!assetItem.getDisabled()) {
        try {
          addDrl(assetItem.getContent());
        } catch (DroolsParserException e) {
          errorLogger.addError(assetItem, "Parser exception: " + e.getMessage());
        } catch (IOException e) {
          errorLogger.addError(assetItem, "IOException: " + e.getMessage());
        }
      }
    }
  }
  public String getDRL() {
    StringBuffer src = new StringBuffer();
    src.append("package " + this.pkg.getName() + "\n");
    src.append(ServiceImplementation.getDroolsHeader(this.pkg) + "\n\n");

    // now we load up the DSL files
    builder.setDSLFiles(
        BRMSPackageBuilder.getDSLMappingFiles(
            pkg,
            new BRMSPackageBuilder.DSLErrorEvent() {
              public void recordError(AssetItem asset, String message) {
                errors.add(new ContentAssemblyError(asset, message));
              }
            }));

    // do the functions and declared types.
    AssetItemIterator it =
        this.pkg.listAssetsByFormat(new String[] {AssetFormats.FUNCTION, AssetFormats.DRL_MODEL});
    while (it.hasNext()) {
      AssetItem func = (AssetItem) it.next();
      if (!func.isArchived()) {
        src.append(func.getContent() + "\n\n");
      }
    }

    // now the rules
    Iterator iter = pkg.getAssets();
    while (iter.hasNext()) {
      AssetItem asset = (AssetItem) iter.next();
      if (!asset.isArchived()) {

        ContentHandler h = ContentManager.getHandler(asset.getFormat());
        if (h instanceof IRuleAsset) {
          IRuleAsset ruleAsset = (IRuleAsset) h;
          ruleAsset.assembleDRL(builder, asset, src);
        }

        src.append("\n\n");
      }
    }

    return src.toString();
  }
  private void addToVerifier(AssetItemIterator assets, ResourceType resourceType) {
    while (assets.hasNext()) {
      AssetItem asset = assets.next();
      if (!asset.isArchived() && !asset.getDisabled()) {
        if (resourceType == ResourceType.DTABLE) {
          DecisionTableConfiguration dtableconfiguration =
              KnowledgeBuilderFactory.newDecisionTableConfiguration();
          dtableconfiguration.setInputType(DecisionTableInputType.XLS);

          verifier.addResourcesToVerify(
              ResourceFactory.newByteArrayResource(asset.getBinaryContentAsBytes()),
              resourceType,
              (ResourceConfiguration) dtableconfiguration);
        } else {
          verifier.addResourcesToVerify(
              ResourceFactory.newReaderResource(new StringReader(asset.getContent())),
              resourceType);
        }
      }
    }
  }
  private void searchTheFunctionWithAnError() {
    builder.clearErrors();
    AssetItemIterator functionsIterator =
        this.packageItem.listAssetsWithVersionsSpecifiedByDependenciesByFormat(
            AssetFormats.FUNCTION);

    while (functionsIterator.hasNext()) {
      AssetItem function = functionsIterator.next();
      if (!function.getDisabled()) {
        try {
          addDrl(function.getContent());
        } catch (IOException e) {
          errorLogger.addError(function, "IOException: " + e.getMessage());
        } catch (DroolsParserException e) {
          errorLogger.addError(packageItem, "Parser exception: " + e.getMessage());
        }

        if (builder.hasErrors()) {
          logErrors(function);
        }
      }
    }
  }
  public SuggestionCompletionEngine getSuggestionEngine(
      PackageItem packageItem, String droolsHeader) {

    StringBuilder buf = new StringBuilder();
    AssetItemIterator it = packageItem.listAssetsByFormat(new String[] {AssetFormats.DRL_MODEL});
    while (it.hasNext()) {
      AssetItem as = it.next();
      buf.append(as.getContent());
      buf.append('\n');
    }

    ClassLoaderBuilder classLoaderBuilder =
        new ClassLoaderBuilder(
            packageItem.listAssetsWithVersionsSpecifiedByDependenciesByFormat(AssetFormats.MODEL));

    //        String packageName = packageItem.getName();
    //        return super.getSuggestionEngine("package " + packageName + "\n\n" + droolsHeader +
    // "\n" + buf.toString(),
    return super.getSuggestionEngine(
        droolsHeader + "\n" + buf.toString(),
        classLoaderBuilder.getJarInputStreams(),
        getDSLMappingFiles(packageItem),
        getDataEnums(packageItem));
  }