/** @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;
  }
 /**
  * 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;
 }
  /////////////////////////////////////////////////////////////////////////////////////////
  //  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();
  }
  /**
   * 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);
    }
  }
 /**
  * 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();
 }
 /**
  * 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();
 }
  /**
   * 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;
  }
 /**
  * @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();
 }
  /** @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();
  }
  /**
   * 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();
  }
 /**
  * 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);
 }
  /**
   * 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;
  }