/**
   * Goes through all files in a deployment, and processes them so that they are then ready for use
   * after deployment.
   *
   * @param module The {@link InternalKieModule}, necessary to get form content
   * @param files The {@link List} of file (names) to process.
   * @param kieContainer The {@link KieContainer}, necesary in order to load classes
   * @param deploymentUnit The {@link DeploymentUnit}, necessary to get the deployment id
   * @param deployedUnit The {@link DeployedUnit}, which contains the results of actions here
   */
  protected void processResources(
      InternalKieModule module,
      Collection<String> files,
      KieContainer kieContainer,
      DeploymentUnit unit,
      DeployedUnitImpl deployedUnit,
      ReleaseId releaseId,
      Map<String, ProcessDescriptor> processes) {
    for (String fileName : files) {
      if (fileName.matches(".+bpmn[2]?$")) {
        ProcessAssetDesc process;
        try {
          String processString = new String(module.getBytes(fileName), "UTF-8");
          String processId = getProcessId(processString);
          ProcessDescriptor processDesriptor = processes.get(processId);
          if (processDesriptor != null) {
            process = processDesriptor.getProcess();
            if (process == null) {
              throw new IllegalArgumentException("Unable to read process " + fileName);
            }
            process.setEncodedProcessSource(Base64.encodeBase64String(processString.getBytes()));
            process.setDeploymentId(unit.getIdentifier());

            deployedUnit.addAssetLocation(process.getId(), process);
            bpmn2Service.addProcessDefinition(
                unit.getIdentifier(), processId, processDesriptor, kieContainer);
          }
        } catch (UnsupportedEncodingException e) {
          throw new IllegalArgumentException(
              "Unsupported encoding while processing process " + fileName);
        }
      } else if (fileName.matches(".+ftl$")
          || fileName.matches(".+form$")
          || fileName.matches(".+frm$")) {
        try {
          String formContent = new String(module.getBytes(fileName), "UTF-8");
          if (fileName.indexOf("/") != -1)
            fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
          formManagerService.registerForm(unit.getIdentifier(), fileName, formContent);
        } catch (UnsupportedEncodingException e) {
          throw new IllegalArgumentException(
              "Unsupported encoding while processing form " + fileName);
        }
      } else if (fileName.matches(".+class$")) {
        // Classes 1: classes from deployment added
        String className = fileName.replaceAll("/", ".");
        className = className.substring(0, fileName.length() - ".class".length());
        Class deploymentClass = null;
        try {
          deploymentClass = kieContainer.getClassLoader().loadClass(className);
        } catch (ClassNotFoundException cnfe) {
          throw new IllegalArgumentException("Class " + className + " not found in the project");
        } catch (NoClassDefFoundError e) {
          throw new IllegalArgumentException("Class " + className + " not found in the project");
        }
        addClassToDeployedUnit(deploymentClass, deployedUnit);
      }
    }
  }
  @Test
  public void processIdAndProcessDefinitionTest() throws Exception {
    // JaxbProcessDefinition
    ProcessAssetDesc assetDesc =
        new ProcessAssetDesc(
            "org.test.proc.id",
            "The Name Of The Process",
            "1.999.23.Final",
            "org.test.proc",
            "RuleFlow",
            KnowledgeType.PROCESS.toString(),
            "org.test.proc",
            "org.test.proc:procs:1.999.Final");

    JaxbProcessDefinition jaxbProcDef = new JaxbProcessDefinition();
    jaxbProcDef.setDeploymentId(assetDesc.getDeploymentId());
    jaxbProcDef.setId(assetDesc.getId());
    jaxbProcDef.setName(assetDesc.getName());
    jaxbProcDef.setPackageName(assetDesc.getPackageName());
    jaxbProcDef.setVersion(assetDesc.getVersion());
    Map<String, String> forms = new HashMap<String, String>();
    forms.put("locationForm", "GPS: street: post code: city: state: land: planet: universe: ");
    jaxbProcDef.setForms(forms);

    JaxbProcessDefinition copyJaxbProcDef = testRoundTrip(jaxbProcDef);
    ComparePair.compareObjectsViaFields(jaxbProcDef, copyJaxbProcDef);
  }
  /**
   * This creates and fills a {@link RuntimeEnvironmentBuilder} instance, which is later used when
   * creating services. A lot of the logic here is used to process the information in the {@link
   * DeploymentDescriptor} instance, which is part of the {@link DeploymentUnit}.
   *
   * @param deploymentUnit The {@link KModuleDeploymentUnit}, which is filled by the method
   * @param deployedUnit The {@link DeployedUnit}, which is also filled by the method
   * @param kieContainer The {@link KieContainer}, which contains information needed to fill the
   *     above two arguments
   * @param mode The {@link MergeMode} used to resolve conflicts in the {@link
   *     DeploymentDescriptor}.
   * @return A {@link RuntimeEnvironmentBuilder} instance ready for use
   */
  protected RuntimeEnvironmentBuilder boostrapRuntimeEnvironmentBuilder(
      KModuleDeploymentUnit deploymentUnit,
      DeployedUnit deployedUnit,
      KieContainer kieContainer,
      MergeMode mode) {
    DeploymentDescriptor descriptor = deploymentUnit.getDeploymentDescriptor();
    if (descriptor == null
        || ((DeploymentDescriptorImpl) descriptor)
            .isEmpty()) { // skip empty descriptors as its default can override settings
      DeploymentDescriptorManager descriptorManager =
          new DeploymentDescriptorManager("org.jbpm.domain");
      List<DeploymentDescriptor> descriptorHierarchy =
          descriptorManager.getDeploymentDescriptorHierarchy(kieContainer);

      descriptor = merger.merge(descriptorHierarchy, mode);
      deploymentUnit.setDeploymentDescriptor(descriptor);
    } else if (descriptor != null && !deploymentUnit.isDeployed()) {
      DeploymentDescriptorManager descriptorManager =
          new DeploymentDescriptorManager("org.jbpm.domain");
      List<DeploymentDescriptor> descriptorHierarchy =
          descriptorManager.getDeploymentDescriptorHierarchy(kieContainer);

      descriptorHierarchy.add(0, descriptor);
      descriptor = merger.merge(descriptorHierarchy, mode);
      deploymentUnit.setDeploymentDescriptor(descriptor);
    }

    // first set on unit the strategy
    deploymentUnit.setStrategy(descriptor.getRuntimeStrategy());

    // setting up runtime environment via builder
    RuntimeEnvironmentBuilder builder = null;
    if (descriptor.getPersistenceMode() == PersistenceMode.NONE) {
      builder = RuntimeEnvironmentBuilder.Factory.get().newDefaultInMemoryBuilder();
    } else {
      builder = RuntimeEnvironmentBuilder.Factory.get().newDefaultBuilder();
    }
    // populate various properties of the builder
    EntityManagerFactory emf =
        EntityManagerFactoryManager.get().getOrCreate(descriptor.getPersistenceUnit());
    builder.entityManagerFactory(emf);

    Map<String, Object> contaxtParams = new HashMap<String, Object>();
    contaxtParams.put("entityManagerFactory", emf);
    contaxtParams.put("classLoader", kieContainer.getClassLoader());
    // process object models that are globally configured (environment entries, session
    // configuration)
    for (NamedObjectModel model : descriptor.getEnvironmentEntries()) {
      Object entry = getInstanceFromModel(model, kieContainer, contaxtParams);
      builder.addEnvironmentEntry(model.getName(), entry);
    }

    for (NamedObjectModel model : descriptor.getConfiguration()) {
      Object entry = getInstanceFromModel(model, kieContainer, contaxtParams);
      builder.addConfiguration(model.getName(), (String) entry);
    }
    ObjectMarshallingStrategy[] mStrategies =
        new ObjectMarshallingStrategy[descriptor.getMarshallingStrategies().size() + 1];
    int index = 0;
    for (ObjectModel model : descriptor.getMarshallingStrategies()) {
      Object strategy = getInstanceFromModel(model, kieContainer, contaxtParams);
      mStrategies[index] = (ObjectMarshallingStrategy) strategy;
      index++;
    }
    // lastly add the main default strategy
    mStrategies[index] =
        new SerializablePlaceholderResolverStrategy(ClassObjectMarshallingStrategyAcceptor.DEFAULT);
    builder.addEnvironmentEntry(EnvironmentName.OBJECT_MARSHALLING_STRATEGIES, mStrategies);

    builder.addEnvironmentEntry("KieDeploymentDescriptor", descriptor);
    builder.addEnvironmentEntry("KieContainer", kieContainer);
    if (executorService != null) {
      builder.addEnvironmentEntry("ExecutorService", executorService);
    }
    // populate all assets with roles for this deployment unit
    List<String> requiredRoles = descriptor.getRequiredRoles(DeploymentDescriptor.TYPE_VIEW);
    if (requiredRoles != null && !requiredRoles.isEmpty()) {
      for (DeployedAsset desc : deployedUnit.getDeployedAssets()) {
        if (desc instanceof ProcessAssetDesc) {
          ((ProcessAssetDesc) desc).setRoles(requiredRoles);
        }
      }
    }

    // Classes 3: classes added from descriptor
    List<String> remoteableClasses = descriptor.getClasses();
    if (remoteableClasses != null && !remoteableClasses.isEmpty()) {
      for (String className : remoteableClasses) {
        Class descriptorClass = null;
        try {
          descriptorClass = kieContainer.getClassLoader().loadClass(className);
          logger.debug(
              "Loaded {} into the classpath from deployment descriptor {}",
              className,
              kieContainer.getReleaseId().toExternalForm());
        } catch (ClassNotFoundException cnfe) {
          throw new IllegalArgumentException("Class " + className + " not found in the project");
        } catch (NoClassDefFoundError e) {
          throw new IllegalArgumentException("Class " + className + " not found in the project");
        }
        addClassToDeployedUnit(descriptorClass, (DeployedUnitImpl) deployedUnit);
      }
    }

    return builder;
  }