/**
   * Procesar los resultados de búsqueda: acceder a algunos datos: - MetaDatos comunes como el
   * nombre del contenido y versión idiomática - MetaDatos específicos: XML del tipo de contenido
   *
   * @param items los items a procesar
   * @return
   */
  private static ServiceData _resultItemToServiceData(final R01MSearchResultItem item)
      throws IOException {
    ServiceData itemData = new ServiceData();

    // Algunos metaDatos comunes
    // -------------------------
    itemData.setContentName(item.getContentName());
    itemData.setLang(item.getDocumentLanguage());
    itemData.setLangVersionName(item.getDocumentName());

    // Algunos meta-datos relevantes dependientes del tipo de contenido
    // pero que son devueltos por el buscador
    // ----------------------------------------------------------------
    Map<String, ?> indexedMD = item.getDocumentMetaData();
    itemData.setProcedureStatus(
        indexedMD != null ? indexedMD.get("procedureStatus").toString() : null);

    // MetaDatos específicos disponibles en un XML que hay que descargar de euskadi.net
    // --------------------------------------------------------------------------------
    String dataFileXML = _downloadDataFileXML(item);
    if (dataFileXML != null) itemData.setDataFileXML(dataFileXML);

    // Assets reusables (ZIP con el contenido)
    // ---------------------------------------
    Map<String, Path> assets = item.getReusableAssets();
    if (CollectionUtils.hasData(assets)) itemData.setReusableAssets(assets);

    return itemData;
  }
 public CONTAINER_TYPE withLabelInStructurePicks(final R01MLabelInStructurePick... picks) {
   if (CollectionUtils.hasData(picks)) {
     Collection<R01MLabelInStructurePick> picksCol = Arrays.asList(picks);
     return this.withLabelInStructurePicks(picksCol);
   }
   return _parentType;
 }
 /**
  * Returns a map with the labels of a certain structure indexed by their oid
  *
  * @param cats
  * @param structureOid
  * @param role
  * @return
  */
 private static Map<String, String> _labelsInStructure(
     final List<R01MSearchResultItemStructureCatalog> cats,
     final String structureOid,
     final String role) {
   if (CollectionUtils.isNullOrEmpty(cats)) return null;
   Collection<R01MSearchResultItemStructureCatalog> roleCats =
       FluentIterable.from(cats)
           .filter(
               new Predicate<R01MSearchResultItemStructureCatalog>() {
                 @Override
                 public boolean apply(final R01MSearchResultItemStructureCatalog cat) {
                   return cat.getStructureOid().equals(structureOid) && cat.getRole().equals(role);
                 }
               })
           .toList();
   // Get the labels descriptions
   Map<String, String> outCats = new HashMap<String, String>(roleCats.size());
   Labels labels = LABELS.get(structureOid);
   for (R01MSearchResultItemStructureCatalog cat : roleCats) {
     String labelOid = cat.getLabelOid();
     String label = labels.getByOid(labelOid);
     if (label != null) outCats.put(labelOid, label);
   }
   return outCats;
 }
Ejemplo n.º 4
0
  /////////////////////////////////////////////////////////////////////////////////////////
  //  JPQL
  /////////////////////////////////////////////////////////////////////////////////////////
  protected String _jpqlQueryFrom(final BooleanQueryClause qryClause) {
    if (qryClause == null || CollectionUtils.isNullOrEmpty(qryClause.getClauses())) {
      log.warn("A filter with NO filter parameters was received... al records will be returned");
      return null;
    }

    String dbFieldId = qryClause.getFieldId().asString();

    StringBuilder outJPQL = new StringBuilder();
    outJPQL.append("(");

    Set<QualifiedQueryClause<? extends QueryClause>> clauses = qryClause.getClauses();

    QueryClauseOccur prevClauseOccur = null;
    for (Iterator<QualifiedQueryClause<? extends QueryClause>> clauseIt = clauses.iterator();
        clauseIt.hasNext(); ) {
      QualifiedQueryClause<? extends QueryClause> clause = clauseIt.next();

      String jpqlQuery = _jpqlQueryFrom(clause.getClause());
      String jpqlJoin = _jpqlJoinFor(clause.getOccur());

      if (jpqlQuery != null) {
        if (prevClauseOccur != null) outJPQL.append(jpqlJoin);
        if (clauseIt.hasNext()) prevClauseOccur = clause.getOccur();

        outJPQL.append("(");
        outJPQL.append(jpqlQuery); // The clause
        outJPQL.append(")");
      } else {
        log.error("A null lucene query was returned for field {}", dbFieldId);
      }
    }
    outJPQL.append(")");
    return outJPQL.toString();
  }
Ejemplo n.º 5
0
  /** @return the standard terms as a {@link LanguageTexts} */
  public LanguageTexts getStandardTermsAsLanguageTexts() {
    Collection<R01MStructureLabelTerm> standardTerms = this.getStandardTerms();

    if (CollectionUtils.isNullOrEmpty(standardTerms)) return null;
    LanguageTexts outTerms = new R01MStructureLabelTermsAsLanguageTextsView(standardTerms);
    return outTerms;
  }
 public CONTAINER_TYPE withLabelInStructurePicks(
     final Collection<R01MLabelInStructurePick> picks) {
   if (CollectionUtils.hasData(picks)) {
     _modelObject.asStructureCatalogable().addPicks(picks);
   }
   return _parentType;
 }
Ejemplo n.º 7
0
  /**
   * Sets the synonymous terms by language
   *
   * @param theSynonymousTerms The synonimousTerms to set.
   */
  public void addSynonymousTerms(final Collection<R01MStructureLabelTerm> theSynonymousTerms) {
    if (CollectionUtils.isNullOrEmpty(theSynonymousTerms)) return;
    if (_terms == null) _terms = new HashSet<R01MStructureLabelTerm>();

    // Ensure that the provided term is NOT a synonymous term and add it to the list
    for (R01MStructureLabelTerm term : theSynonymousTerms) {
      term.setType(R01MStructureLabelTermType.SYNONIMOUS);
      _terms.add(term);
    }
  }
Ejemplo n.º 8
0
 /** @return a {@link Map} with the external {@link OID}s indexed by {@link AppCode} */
 public Map<AppCode, String> getExtOidsByAppCode() {
   Map<AppCode, String> outMap = null;
   if (CollectionUtils.hasData(_extOIDs)) {
     outMap = Maps.newHashMapWithExpectedSize(_extOIDs.size());
     for (R01MStructureLabelOidInApp extOid : _extOIDs) {
       outMap.put(extOid.getAppCode(), extOid.getOid());
     }
   }
   return outMap;
 }
Ejemplo n.º 9
0
 @Override
 public void setNamesByLanguage(final LanguageTexts langTexts) {
   if (langTexts != null) {
     Set<Language> definedLangs = langTexts.getDefinedLanguages();
     if (CollectionUtils.hasData(definedLangs)) {
       for (Language lang : definedLangs) {
         this.setStandardTermIn(lang, langTexts.get(lang));
       }
     }
   }
 }
Ejemplo n.º 10
0
 /**
  * Gets the standard descriptions
  *
  * @return
  */
 public Set<R01MStructureLabelTerm> getStandardTerms() {
   if (CollectionUtils.isNullOrEmpty(_terms)) return null;
   return FluentIterable.from(_terms)
       .filter(
           new Predicate<R01MStructureLabelTerm>() {
             @Override
             public boolean apply(final R01MStructureLabelTerm term) {
               return term.isStandarized();
             }
           })
       .toSet();
 }
Ejemplo n.º 11
0
 /**
  * The label terms in a language
  *
  * @param lang
  * @return
  */
 public Set<R01MStructureLabelTerm> getTermsIn(final Language lang) {
   if (CollectionUtils.isNullOrEmpty(_terms)) return null;
   return FluentIterable.from(_terms)
       .filter(
           new Predicate<R01MStructureLabelTerm>() {
             @Override
             public boolean apply(final R01MStructureLabelTerm term) {
               return term.getLang() == lang;
             }
           })
       .toSet();
 }
Ejemplo n.º 12
0
 /**
  * @return the found entities' oids if the persistence find operation was successful or a
  *     PersistenteException if not
  * @throws PersistenceException
  */
 public <O extends OID> Collection<O> getOidsOrThrow() throws PersistenceException {
   if (CollectionUtils.isNullOrEmpty(_operationExecResult)) return Lists.newArrayList();
   return FluentIterable.from(_operationExecResult)
       .transform(
           new Function<M, O>() {
             @Override
             @SuppressWarnings("unchecked")
             public O apply(final M entity) {
               return (O) entity.getOid();
             }
           })
       .toList();
 }
Ejemplo n.º 13
0
  /**
   * Gets the standard term in a language
   *
   * @param
   * @return
   */
  public R01MStructureLabelTerm getStandardTermIn(final Language lang) {
    Set<R01MStructureLabelTerm> standardTerms = this.getStandardTerms();

    if (CollectionUtils.isNullOrEmpty(standardTerms)) return null;
    R01MStructureLabelTerm outTerm = null;
    for (R01MStructureLabelTerm term : standardTerms) {
      if (term.isStandarized() && term.getLang() == lang) {
        outTerm = term;
        break;
      }
    }
    return outTerm;
  }
Ejemplo n.º 14
0
  /** @return the standard terms defined languages */
  public Set<Language> getStandardTermsLanguages() {
    Set<R01MStructureLabelTerm> standardTerms = this.getStandardTerms();

    if (CollectionUtils.isNullOrEmpty(standardTerms)) return null;
    return FluentIterable.from(standardTerms)
        .transform(
            new Function<R01MStructureLabelTerm, Language>() {
              @Override
              public Language apply(final R01MStructureLabelTerm term) {
                return term.getLang();
              }
            })
        .toSet();
  }
Ejemplo n.º 15
0
  /**
   * Gets the synonymous terms in a language
   *
   * @param lang
   * @return
   */
  public Set<String> getSynonimousTermsTextIn(final Language lang) {
    if (CollectionUtils.isNullOrEmpty(_terms)) return null;

    return FluentIterable.from(_terms)
        .filter(
            new Predicate<R01MStructureLabelTerm>() {
              @Override
              public boolean apply(final R01MStructureLabelTerm term) {
                return term.isSynomimous() && term.getLang().is(lang);
              }
            })
        .transform(
            new Function<R01MStructureLabelTerm, String>() {
              @Override
              public String apply(final R01MStructureLabelTerm term) {
                return term.getValue();
              }
            })
        .toSet();
  }
  //	@After
  public void tearDown() throws Exception {
    AA88ClientAPI api = TestAPIBase.getClientApi(AA88ClientAPI.class);

    if (CollectionUtils.hasData(_testedGuaranteesOids)) {
      for (AA88GuaranteeOID oid : _testedGuaranteesOids) {
        // [1]: Delete the guarantee publish requests at the DB (if exists)

        Collection<AA88GuaranteePublishRequestOID> deletedGuaranteePubRequestOids =
            api.guaranteesAPI()
                .getForPublishRequestCRUD()
                .deleteAllPublishRequestsForGuaranteeWithOid(oid);
        // [2]: Delete the guarantee record at the DB
        AA88Guarantee deletedGuarantee = api.guaranteesAPI().getForCRUD().delete(oid);
        // [3] - Delete the guarantee zip file & folder
        STORAGE_SERVICES.deleteGuaranteedUnitStorage(
            api.getUserContext(),
            deletedGuarantee.getSourceSystemId(),
            deletedGuarantee.getGuaranteedUnitId());
      }
    }
  }
  /**
   * Captures java generics to do the service interface to implementation / proxy bindings
   *
   * @param binder
   * @param apiDef
   */
  @SuppressWarnings({"unchecked"})
  private static <S extends ServiceInterface> Class<S> _bindServiceInterfaceToImplOrProxy(
      final Binder binder, final ServiceToImplAndProxyDef<S> serviceToImplDef) {
    Class<S> serviceImplOrProxyType = null;

    log.warn("\t\t> {} ", serviceToImplDef.debugInfo());

    // [1] - The bean impl ia available... NO proxy is needed
    if (serviceToImplDef.getBeanServiceImplType() != null) {

      log.warn(
          "\t\t\t>Bind {} to the BEAN IMPLEMENTATION: {} (no proxy needed)",
          serviceToImplDef.getInterfaceType(),
          serviceToImplDef.getBeanServiceImplType());

      // The implementation is available:  Bind the service implementation to the interface
      // 									 annotated with @ServicesCoreImplementation
      serviceImplOrProxyType = (Class<S>) serviceToImplDef.getBeanServiceImplType();

      binder
          .bind(serviceToImplDef.getBeanServiceImplType())
          .in(Singleton.class); // the service impl as singleton
      binder
          .bind(serviceToImplDef.getInterfaceType())
          .to(serviceImplOrProxyType); // not annotated binding			
    }
    // [2] The bean implementation is NOT available: use the configured (REST, EJB...) proxy impl
    else {
      // bind the service interface default proxy or any other if the default one is NOT present
      ServicesImpl defaultServiceImpl = serviceToImplDef.getConfiguredDefaultProxyImpl();

      if (serviceToImplDef.getServiceProxyImplTypeOrNullFor(defaultServiceImpl) != null) {
        // the configured default proxy was found (the normal case)
        serviceImplOrProxyType =
            (Class<S>) serviceToImplDef.getServiceProxyImplTypeFor(defaultServiceImpl);
        binder.bind(serviceToImplDef.getInterfaceType()).to(serviceImplOrProxyType);
        log.warn(
            "\t\t\t>Bind {} to the DEFAULT PROXY: {}",
            serviceToImplDef.getInterfaceType(),
            serviceImplOrProxyType);

      } else if (serviceToImplDef.getServiceProxyImplTypeOrNullFor(ServicesImpl.REST) != null) {
        // the configured default proxy was not found BUT the REST impl proxy is available
        serviceImplOrProxyType =
            (Class<S>) serviceToImplDef.getServiceProxyImplTypeFor(ServicesImpl.REST);
        binder.bind(serviceToImplDef.getInterfaceType()).to(serviceImplOrProxyType);
        log.warn(
            "\t\t\t>Bind {} to the DEFAULT PROXY: {} (the default={} was NOT found so used {} instead)",
            serviceToImplDef.getInterfaceType(),
            ServicesImpl.REST,
            defaultServiceImpl,
            serviceImplOrProxyType);

      } else if (CollectionUtils.hasData(serviceToImplDef.getProxyTypeByImpl())) {
        // The configured proxy was not found... try to get another
        ServicesImpl anyImpl =
            CollectionUtils.pickOneElement(serviceToImplDef.getProxyTypeByImpl().keySet());
        serviceImplOrProxyType = (Class<S>) serviceToImplDef.getServiceProxyImplTypeFor(anyImpl);
        binder.bind(serviceToImplDef.getInterfaceType()).to(serviceImplOrProxyType);
        log.warn(
            "\t\t\t>Bind {} to the DEFAULT PROXY: {} (the default={} was NOT found so used {} instead)",
            serviceToImplDef.getInterfaceType(),
            anyImpl,
            defaultServiceImpl,
            serviceImplOrProxyType);
      }

      // c) bind the proxy to service impl to be used at
      // ServicesClientProxyLazyLoaderGuiceMethodInterceptor
      if (CollectionUtils.isNullOrEmpty(serviceToImplDef.getProxyTypeByImpl())) {
        log.error(
            "\t\t\t>NO proxy for {} was not found: Is there any proxy type implementing {} available in the classpath?",
            serviceToImplDef.getInterfaceType(),
            serviceToImplDef.getInterfaceType());
      }
    }
    return serviceImplOrProxyType;
  }
Ejemplo n.º 18
0
 /**
  * Adds a synonymous term in a language
  *
  * @param theSynonimousTerm
  */
 public void addSynonymousTerms(final R01MStructureLabelTerm... theSynonymousTerms) {
   if (CollectionUtils.isNullOrEmpty(theSynonymousTerms)) return;
   Collection<R01MStructureLabelTerm> terms = CollectionUtils.of(theSynonymousTerms).asSet();
   this.addSynonymousTerms(terms);
 }
  //	@Test
  public void testRefresh() {
    log.warn("=============================================================");
    log.warn("Test Refresh");
    log.warn("=============================================================");

    AA88ClientAPI api = TestAPIBase.getClientApi(AA88ClientAPI.class);

    // Use a type that encapsulates all the tests
    final AA88LifeCycleServicesTestHelper testHelp =
        new AA88LifeCycleServicesTestHelper(api, STORAGE_SERVICES);

    // [1] - Create guarantees
    File testFileListsContainerFolder = new File(TEST_FILELIST_FOLDER_PATH.asAbsoluteString());
    File[] testFileLists = testFileListsContainerFolder.listFiles();

    Observable.from(testFileLists)
        .map(
            new Func1<File, AA88Guarantee>() {
              @Override
              public AA88Guarantee call(final File fileList) {
                log.warn("\n\n\n");
                log.warn(
                    "CREATE & DO A FIRST REFRESH for MOCK guarantee using fileList at {}",
                    Paths.forPaths()
                        .join(TEST_FILELIST_FOLDER_PATH, fileList.getName())
                        .asAbsoluteString());

                AA88Guarantee guarantee =
                    testHelp.testLifeCycle(
                        TEST_FILELIST_FOLDER_PATH,
                        FileName.of(fileList.getName()),
                        Arrays.asList(AA88MethodToBeTested.START, AA88MethodToBeTested.REFRESH));
                log.warn(
                    "MOCK guarantee with oid={} CREATED & REFRESHED FOR THE FIRST TIME for fileList at {}",
                    guarantee.getOid(),
                    Paths.forPaths()
                        .join(TEST_FILELIST_FOLDER_PATH, fileList.getName())
                        .asAbsoluteString());
                log.warn("\n\n\n");
                return guarantee;
              }
            })
        .subscribe(
            new Observer<AA88Guarantee>() {
              @Override
              public void onNext(final AA88Guarantee guarantee) {
                _testedGuaranteesOids.add(guarantee.getOid());
              }

              @Override
              public void onCompleted() {
                log.warn("\n\n\n\n\n\n");
                log.warn(
                    ":::::::: {} test guarantees with oids={} created__________________________",
                    _testedGuaranteesOids.size(),
                    _testedGuaranteesOids);
              }

              @Override
              public void onError(final Throwable th) {
                // BEWARE!!! RxJava will catch Exception and most Error.
                //			 Exceptions cannot be propagated out of RxJava
                //			 ... so even if Throwables.propagate(th) is used, the exception is NEVER thrown
                // outside RxJava
                //		 	 the only option is to use Exceptions.throwIfFatal(th)
                //			 (see https://github.com/ReactiveX/RxJava/issues/969)
                // Exceptions.throwIfFatal(th);
                th.printStackTrace(System.out);
              }
            });

    // [2] - With the created guarantees, call refresh guarantee
    if (CollectionUtils.hasData(_testedGuaranteesOids)) {
      log.warn(
          ":::::::: With the created guarantees --> Refesh all Actives Guarantees _____________________________________________________________________");

      // Call refresh all active guarantees and wait a moment to the scheduler to start
      api.guaranteesAPI()
          .getForLifeCycle()
          .refreshAllActiveGuarantees(AA88SourceSystemID.forId("PLATEA-Internet"));
      Threads.safeSleep(TimeLapse.createFor("5s"));

      // Check the process
      final Collection<BeingRefreshedGuarantee> refreshPendingGuarantees =
          FluentIterable.from(_testedGuaranteesOids)
              .transform(
                  new Function<AA88GuaranteeOID, BeingRefreshedGuarantee>() {
                    @Override
                    public BeingRefreshedGuarantee apply(final AA88GuaranteeOID oid) {
                      return new BeingRefreshedGuarantee(oid);
                    }
                  })
              .toList();
      long startTS = System.currentTimeMillis();
      long elapsedMilis = 0;
      boolean anyRefreshPendingGuarantee = false;
      do {
        for (BeingRefreshedGuarantee b : refreshPendingGuarantees) {
          if (b.isRefreshed()) continue;

          // Check that there's NO minor version in requested status
          AA88Guarantee mockGuarantee = api.guaranteesAPI().getForCRUD().load(b.getOid());
          if (mockGuarantee.existsMinorVersionInRequestedStatus()) {
            log.warn(
                "...the guarantee with oid={} unitId={} is still being refreshed (the notary is working)...give a moment to the notary to do it's work...",
                mockGuarantee.getOid(),
                mockGuarantee.getGuaranteedUnitId());
          } else {
            log.warn(
                "The guarantee with oid={} unitId={} has been refreshed!... stop guaranteeing it",
                mockGuarantee.getOid(),
                mockGuarantee.getGuaranteedUnitId());
            b.setRefreshed(true);
          }
        }
        anyRefreshPendingGuarantee = _anyRefreshPendingGuarantee(refreshPendingGuarantees);
        if (anyRefreshPendingGuarantee) {
          elapsedMilis = System.currentTimeMillis() - startTS;
          Threads.safeSleep(TimeLapse.createFor("5s"));
        }
        Assert.assertTrue(
            elapsedMilis
                < AA88LifeCycleServicesTestHelper.MAX_REFRESH_TIME_PER_GUARANTEE
                    * _testedGuaranteesOids.size());
      } while (anyRefreshPendingGuarantee);

      // Stop guaranteeing
      for (AA88GuaranteeOID oid : _testedGuaranteesOids) {
        log.warn("Stop guaranteein guarantee with oid={}", oid);
        api.guaranteesAPI().getForLifeCycle().stopGuaranteeingNow(oid);
      }

      // Check that all guarantees has been stoped
      for (AA88GuaranteeOID oid : _testedGuaranteesOids) {
        AA88Guarantee mockGuarantee = api.guaranteesAPI().getForCRUD().load(oid);
        Assert.assertTrue(!mockGuarantee.isActive());
      }
    } else {
      log.warn("Could NOT create any mock guarantee!!!");
    }
  }
  /**
   * Finds types extending {@link ServicesCoreBootstrapGuiceModule}: {@link
   * BeanImplementedServicesCoreGuiceModule}, {@link RESTImplementedServicesCoreGuiceModuleBase},
   * etc and returns them indexed by appCode / component
   *
   * @param coreAppCode
   * @param coreModule
   * @return
   */
  private Map<CoreAppAndModule, Collection<Class<? extends ServicesCoreBootstrapGuiceModule>>>
      _findCoreBootstrapGuiceModuleTypesByAppModule(
          final Collection<CoreAppAndModule> coreAppAndComponents) {
    // get the core appcodes from the collection of core appCode/module
    Collection<CoreAppCode> coreAppCodes =
        FluentIterable.from(coreAppAndComponents)
            .transform(
                new Function<CoreAppAndModule, CoreAppCode>() {
                  @Override
                  public CoreAppCode apply(final CoreAppAndModule appAndComponent) {
                    return appAndComponent.getAppCode();
                  }
                })
            .toSet();

    // Find the types implementing ServicesCoreGuiceModule at all the core appcodes (ie: r01t,
    // aa14b, aa81b, etc)
    Set<Class<? extends ServicesCoreBootstrapGuiceModule>> foundBootstrapModuleTypes =
        _findCoreGuiceModulesOrNull(coreAppCodes, ServicesCoreBootstrapGuiceModule.class);

    // Group the found core bootstrap module types by appCode/module
    Map<CoreAppAndModule, Collection<Class<? extends ServicesCoreBootstrapGuiceModule>>>
        outCoreModules = null;
    if (CollectionUtils.hasData(foundBootstrapModuleTypes)) {

      outCoreModules = Maps.newHashMapWithExpectedSize(coreAppCodes.size());
      for (Class<? extends ServicesCoreBootstrapGuiceModule> bootstrapModuleType :
          foundBootstrapModuleTypes) {

        // get type appCode from the bootstrap module type's package (ie: r01t.internal.XXX) and
        // it's @ServiceCore annotation
        CoreAppCode appCode =
            ServicesPackages.appCodeFromCoreBootstrapModuleType(
                bootstrapModuleType); // use the service's core bootstrap type's package to get the
                                      // appCode
        CoreModule coreModule =
            ServicesPackages.appComponentFromCoreBootstrapModuleTypeOrThrow(
                bootstrapModuleType); // use the service's @ServicesCore annotation to get the
                                      // module
        CoreAppAndModule coreAppAndModule = CoreAppAndModule.of(appCode, coreModule);

        Collection<Class<? extends ServicesCoreBootstrapGuiceModule>> appModuleTypes =
            outCoreModules.get(coreAppAndModule);
        if (appModuleTypes == null) {
          appModuleTypes = Sets.newHashSet();
          outCoreModules.put(coreAppAndModule, appModuleTypes);
        }
        appModuleTypes.add(bootstrapModuleType);
      }
    } else {
      log.warn(
          "There's NO type implementing {} in the classpath! For the CORE app codes {}, there MUST be AT LEAST a guice binding module extending {} at package {}",
          ServicesCoreBootstrapGuiceModule.class.getSimpleName(),
          coreAppCodes,
          ServicesCoreBootstrapGuiceModule.class,
          ServicesPackages.coreGuiceModulePackage(CoreAppCode.forId("[coreAppCode]")),
          ServicesCoreBootstrapGuiceModule.class);
      outCoreModules = Maps.newHashMap();
    }
    return outCoreModules;
  }
  /**
   * Returns the implementation type (REST, Bean, Mock, etc) of every services bootstrap module
   * listed at [appCode].client.properties.xml file to do so, it scans the packages under {core
   * appCode}.internal for types implementing {@link ServicesCoreBootstrapGuiceModule}
   *
   * <p>Some times a services implementation NEEDS (or DEPENDS UPON) another service implementation,
   * for example, the REST services implementation NEEDS the Bean services implementation because
   * REST services is only an ACCESS LAYER on top of the Bean services layer that is where the real
   * services logic resides.
   *
   * @return
   */
  public Map<CoreAppAndModule, Collection<Class<? extends ServicesCoreBootstrapGuiceModule>>>
      findBootstrapGuiceModuleTypes() {
    if (_coreAppAndModules == null) return Maps.newHashMap(); // do not return a null config

    Map<CoreAppAndModule, Collection<Class<? extends ServicesCoreBootstrapGuiceModule>>>
        outModuleTypes = Maps.newHashMap();

    // Iterate over all the app/module collection (each app/module can have many
    // ServicesCoreGuiceModules, ie: REST, Bean, etc.. one of them is the DEFAULT one)
    // NOTE: If more than one implementation is found, the BEAN has the highest priority followed by
    // the REST implementation
    //
    // for each app/module
    //		1.- Find the available ServicesCoreGuiceModules
    //		2.- For each found module found, try to find the needed modules
    //			(sometimes a module (ie REST) NEEDS another modules (ie Bean or EJB) to do delegate the
    // work)
    //			... this task is a bit tricky since the order in which the modules are found is important
    //		    ... the checking of the presence of needed modules MUST be done AFTER all modules are
    // processed

    // Find guice modules implementing ServicesCoreGuiceModule either
    // BeanImplementedServicesGuiceModuleBase, RESTImplementedServicesGuiceModuleBase,
    // EJBImplementedServicesGuiceModuleBase, etc)
    Map<CoreAppAndModule, Collection<Class<? extends ServicesCoreBootstrapGuiceModule>>>
        coreBootstrapModuleTypesByApp =
            _findCoreBootstrapGuiceModuleTypesByAppModule(_coreAppAndModules);

    Collection<BootstrapModuleDependency> dependencies = Lists.newArrayList();
    for (CoreAppAndModule coreAppModule : _coreAppAndModules) {

      CoreAppCode coreAppCode = coreAppModule.getAppCode();
      CoreModule module = coreAppModule.getModule();

      // [1] - Get the modules for the appCode
      Collection<Class<? extends ServicesCoreBootstrapGuiceModule>>
          appModuleCoreBootstrapModuleTypes = coreBootstrapModuleTypesByApp.get(coreAppModule);
      if (appModuleCoreBootstrapModuleTypes == null) {
        log.warn(
            "\t\t-{} core will NOT be bootstraped: There's NO type implementing {} at package {} or the {} package is NOT in the classpath. "
                + "If the {} core is to be bootstraped there MUST be AT LEAST a guice binding module extending {} at {} ",
            coreAppModule,
            ServicesCoreBootstrapGuiceModule.class,
            ServicesPackages.coreGuiceModulePackage(coreAppCode),
            ServicesPackages.coreGuiceModulePackage(coreAppCode),
            coreAppModule,
            ServicesCoreBootstrapGuiceModule.class,
            ServicesPackages.coreGuiceModulePackage(coreAppCode));
        continue;
      }
      log.warn(
          "\t\t-{} core will be bootstraped with: {}",
          coreAppModule,
          coreBootstrapModuleTypesByApp.get(coreAppModule));

      // [2] - for each found core bootstrap module try to find the needed modules (ie REST
      // bootstrap modules depends on BEAN bootstrap modules)
      for (Class<? extends ServicesCoreBootstrapGuiceModule> foundModuleType :
          appModuleCoreBootstrapModuleTypes) {
        if (ReflectionUtils.isInterface(foundModuleType)) continue;

        // Check if there's any module dependency set at @ServicesCore annotation
        ServicesCore servicesCoreAnnot =
            ReflectionUtils.typeAnnotation(foundModuleType, ServicesCore.class);

        // find the needed impl (the ServicesGuiceModule-implementing type MUST be annotated with
        // ServicesGuiceModuleDependencies)
        // (sometimes a service impl requires of another service impl, for example, REST services
        // USES Bean services)
        if (!CollectionUtils.of(servicesCoreAnnot.dependsOn()).contains(ServicesImpl.NULL)) {
          CoreAppAndModule ac =
              Strings.isNullOrEmpty(servicesCoreAnnot.fromOtherCoreAppCodeAndModule())
                  ? coreAppModule // by default dependencies are at the same coreAppCode/module
                  : CoreAppAndModule.of(servicesCoreAnnot.fromOtherCoreAppCodeAndModule());
          Collection<ServicesImpl> impls = Arrays.asList(servicesCoreAnnot.dependsOn());
          BootstrapModuleDependency dependency =
              new BootstrapModuleDependency(coreAppModule, foundModuleType, ac, impls);
          dependencies.add(dependency);
          log.warn(
              "\t\t\t- Found {} CORE services bootstrap module (it has a dependency on other core component {}): {}",
              foundModuleType,
              dependency.debugInfo());
        } else {
          log.warn(
              "\t\t\t- Found {} CORE services bootstrap module (no other bootstrap type dependency)",
              foundModuleType);
        }
      } // for bindingModules

      // [3] - put the core bootstrap modules in the output collection indexed by the
      // appCode/component
      outModuleTypes.put(coreAppModule, appModuleCoreBootstrapModuleTypes);
    } // for configuredBindingModules

    // Finally, make sure that the dependencies are satisfied
    if (CollectionUtils.hasData(dependencies)) {
      for (BootstrapModuleDependency dependency : dependencies) {
        Collection<Class<? extends ServicesCoreBootstrapGuiceModule>> otherCoreMods =
            outModuleTypes.get(dependency.getOtherAppAndComponent());

        for (ServicesImpl depImpl : dependency.getDependencies()) {
          boolean isLoaded = false;
          if (CollectionUtils.hasData(otherCoreMods)) {
            for (Class<? extends ServicesCoreBootstrapGuiceModule> otherCoreMod : otherCoreMods) {
              if (ServicesImpl.fromBindingModule(otherCoreMod) == depImpl) {
                isLoaded = true;
                break;
              }
            }
          }
          if (!isLoaded)
            throw new IllegalStateException(
                Strings.customized(
                    "{} (see @{})."
                        + "BUT this module could NOT be loaded."
                        + "Please ensure that a {} annotated type with impl={} attribute is accesible in the run-time classpath (maybe de dependent project is NOT deployed and available at the classpath)",
                    dependency.debugInfo(),
                    ServicesCore.class.getSimpleName(),
                    ServicesCoreBootstrapGuiceModule.class,
                    depImpl));
        }
      }
    }

    // Return
    return outModuleTypes;
  }