Beispiel #1
0
  /**
   * Takes a list of entities and sorts them, according to relationships they have. The entities
   * that have uni-directional relationship with another entity, will be moved to the position
   * behind the entity they are related with. The bi-directional relationships are not sorted,
   * moreover if invalid bi-directional relationship is found, an exception is thrown.
   *
   * @param list Initial list of entities to sort
   * @return List of entities, sorted by relationship
   */
  public static List<Entity> sortByHasARelation(List<Entity> list) {
    List<Entity> sorted = new ArrayList<>(list);
    MultiValueMap<String, String> unresolvedRelations = new LinkedMultiValueMap<>();

    // we need to check if classes have 'has-a' relation
    // these classes should be later in list
    // we do that after all entities will be added to sorted list
    for (int i = 0; i < sorted.size(); ++i) {
      Entity entity = sorted.get(i);
      List<Field> fields =
          (List<Field>)
              CollectionUtils.select(
                  entity.getFields(),
                  new Predicate() {
                    @Override
                    public boolean evaluate(Object object) {
                      return object instanceof Field && ((Field) object).getType().isRelationship();
                    }
                  });

      if (CollectionUtils.isNotEmpty(fields)) {
        int max = i;

        for (Field field : fields) {
          final RelationshipHolder holder = new RelationshipHolder(field);

          // For each field we perform a validation to spot circular, unresolvable relations,
          // which means the data model is incorrect
          unresolvedRelations = validateRelationship(unresolvedRelations, field, holder);
          assertRelationshipIsHistoryCompatible(field, holder, list);

          Entity relation =
              (Entity)
                  CollectionUtils.find(
                      sorted,
                      new Predicate() {
                        @Override
                        public boolean evaluate(Object object) {
                          return object instanceof Entity
                              && ((Entity) object)
                                  .getClassName()
                                  .equalsIgnoreCase(holder.getRelatedClass());
                        }
                      });

          // In case the relation is bidirectional, we shouldn't move the class,
          // in order to avoid infinite loop
          boolean biDirectional = field.getMetadata(RELATED_FIELD) != null;
          max = Math.max(max, biDirectional ? -1 : sorted.indexOf(relation));
        }

        if (max != i) {
          sorted.remove(i);
          --i;

          if (max < sorted.size()) {
            sorted.add(max, entity);
          } else {
            sorted.add(entity);
          }
        }
      }
    }

    return sorted;
  }