@Override
    protected void addCompletions(
        @NotNull CompletionParameters completionParameters,
        ProcessingContext processingContext,
        @NotNull CompletionResultSet completionResultSet) {

      PsiElement position = completionParameters.getPosition();
      if (!Symfony2ProjectComponent.isEnabled(position)) {
        return;
      }

      YAMLCompoundValue yamlCompoundValue =
          PsiTreeUtil.getParentOfType(position, YAMLCompoundValue.class);
      if (yamlCompoundValue == null) {
        return;
      }

      String className =
          YamlHelper.getYamlKeyValueAsString(yamlCompoundValue, "targetEntity", false);
      if (className == null) {
        return;
      }

      PhpClass phpClass = PhpElementsUtil.getClass(position.getProject(), className);
      if (phpClass == null) {
        return;
      }

      for (DoctrineModelField field : EntityHelper.getModelFields(phpClass)) {
        if (field.getRelation() != null) {
          completionResultSet.addElement(new DoctrineModelFieldLookupElement(field));
        }
      }
    }
  private void buildPropertyMap(QueryBuilderScopeContext qb) {

    if (!collectProperties) {
      return;
    }

    for (QueryBuilderJoin join : qb.getJoinMap().values()) {
      String className = join.getResolvedClass();
      if (className != null) {
        PhpClass phpClass = PhpElementsUtil.getClassInterface(project, className);
        if (phpClass != null) {
          qb.addPropertyAlias(
              join.getAlias(),
              new QueryBuilderPropertyAlias(
                  join.getAlias(),
                  null,
                  new DoctrineModelField(join.getAlias())
                      .addTarget(phpClass)
                      .setTypeName(phpClass.getPresentableFQN())));

          // add entity properties
          for (DoctrineModelField field : EntityHelper.getModelFields(phpClass)) {
            qb.addPropertyAlias(
                join.getAlias() + "." + field.getName(),
                new QueryBuilderPropertyAlias(join.getAlias(), field.getName(), field));
          }
        }
      }
    }
  }
  public static List<QueryBuilderRelation> attachRelationFields(PhpClass phpClass) {

    List<QueryBuilderRelation> relations = new ArrayList<QueryBuilderRelation>();

    for (DoctrineModelField field : EntityHelper.getModelFields(phpClass)) {
      if (field.getRelation() != null && field.getRelationType() != null) {
        relations.add(new QueryBuilderRelation(field.getName(), field.getRelation()));
      }
    }

    return relations;
  }
    @Override
    protected void addCompletions(
        @NotNull CompletionParameters completionParameters,
        ProcessingContext processingContext,
        @NotNull CompletionResultSet completionResultSet) {

      PsiElement position = completionParameters.getPosition();
      if (!Symfony2ProjectComponent.isEnabled(position)) {
        return;
      }

      PsiElement psiElement =
          PsiTreeUtil.findFirstParent(
              position,
              new Condition<PsiElement>() {
                @Override
                public boolean value(PsiElement psiElement) {

                  if (psiElement instanceof YAMLKeyValue) {
                    String s = ((YAMLKeyValue) psiElement).getKeyText().toLowerCase();
                    if ("joinTable".equalsIgnoreCase(s)) {
                      return true;
                    }
                  }

                  return false;
                }
              });

      if (psiElement == null) {
        return;
      }

      PsiElement yamlCompoundValue = psiElement.getParent();
      if (!(yamlCompoundValue instanceof YAMLCompoundValue)) {
        return;
      }

      String className =
          YamlHelper.getYamlKeyValueAsString(
              (YAMLCompoundValue) yamlCompoundValue, "targetEntity", false);
      if (className == null) {
        return;
      }

      PhpClass phpClass =
          ServiceUtil.getResolvedClassDefinition(psiElement.getProject(), className);
      if (phpClass == null) {
        return;
      }

      for (DoctrineModelField field : EntityHelper.getModelFields(phpClass)) {
        if (field.getRelation() == null) {
          String columnName = field.getColumn();
          if (columnName == null) {
            completionResultSet.addElement(
                LookupElementBuilder.create(field.getName()).withIcon(Symfony2Icons.DOCTRINE));
          } else {
            completionResultSet.addElement(
                LookupElementBuilder.create(columnName)
                    .withTypeText(field.getName(), false)
                    .withIcon(Symfony2Icons.DOCTRINE));
          }
        }
      }
    }
  public QueryBuilderScopeContext collect() {
    QueryBuilderScopeContext qb = new QueryBuilderScopeContext();

    // doctrine needs valid root with an alias, try to find one in method references or scope
    Map<String, String> map = this.findRootDefinition(methodReferences);
    if (map.size() > 0) {
      Map.Entry<String, String> entry = map.entrySet().iterator().next();
      qb.addTable(entry.getKey(), entry.getValue());
    }

    for (MethodReference methodReference : methodReferences) {

      String name = methodReference.getName();
      if (name != null) {
        collectParameter(qb, methodReference, name);
        collectJoins(qb, methodReference, name);
        collectSelects(qb, methodReference, name);
        collectSelectInForm(qb, methodReference, name);
      }
    }

    // first tableMap entry is root, we add several initial data
    if (qb.getTableMap().size() > 0) {
      Map.Entry<String, String> entry = qb.getTableMap().entrySet().iterator().next();
      String className = entry.getKey();
      PhpClass phpClass = PhpElementsUtil.getClassInterface(project, className);

      // add root select fields
      if (phpClass != null) {

        qb.addPropertyAlias(
            entry.getValue(),
            new QueryBuilderPropertyAlias(
                entry.getValue(),
                null,
                new DoctrineModelField(entry.getValue())
                    .addTarget(phpClass)
                    .setTypeName(phpClass.getPresentableFQN())));

        List<QueryBuilderRelation> relationList = new ArrayList<QueryBuilderRelation>();

        // qb.addRelation(entry.getValue(), attachRelationFields(phpClass));
        for (DoctrineModelField field : EntityHelper.getModelFields(phpClass)) {
          qb.addPropertyAlias(
              entry.getValue() + "." + field.getName(),
              new QueryBuilderPropertyAlias(entry.getValue(), field.getName(), field));
          if (field.getRelation() != null && field.getRelationType() != null) {
            relationList.add(new QueryBuilderRelation(field.getName(), field.getRelation()));
          }
        }

        qb.addRelation(entry.getValue(), relationList);
      }

      QueryBuilderRelationClassResolver resolver =
          new QueryBuilderRelationClassResolver(
              project, entry.getValue(), entry.getKey(), qb.getRelationMap(), qb.getJoinMap());
      resolver.collect();
    }

    // we have a querybuilder which complete known elements now
    // se we can builder a property (field) map table from it
    this.buildPropertyMap(qb);

    return qb;
  }
  private Map<String, String> findRootDefinition(Collection<MethodReference> methodReferences) {

    Map<String, String> roots = new HashMap<String, String>();

    if (methodReferences.size() == 0) {
      return roots;
    }

    String rootAlias = null;
    String repository = null;

    for (MethodReference methodReference : methodReferences) {
      String methodReferenceName = methodReference.getName();

      // get alias
      // ->createQueryBuilder('test');
      if ("createQueryBuilder".equals(methodReferenceName)) {
        String possibleAlias =
            PhpElementsUtil.getStringValue(
                PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 0));
        if (possibleAlias != null) {
          rootAlias = possibleAlias;
        }
      }

      // find repository class
      // getRepository('Foo')->createQueryBuilder('test');
      if ("getRepository".equals(methodReferenceName)) {
        String possibleRepository =
            PhpElementsUtil.getStringValue(
                PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 0));
        if (possibleRepository != null) {
          repository = possibleRepository;
          PhpClass phpClass = EntityHelper.resolveShortcutName(project, repository);
          if (phpClass != null) {
            repository = phpClass.getPresentableFQN();
          }
        }
      }

      // $qb->from('Foo\Class', 'article')
      if ("from".equals(methodReferenceName)) {
        String table =
            PhpElementsUtil.getStringValue(
                PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 0));
        String alias =
            PhpElementsUtil.getStringValue(
                PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 1));
        if (table != null && alias != null) {
          PhpClass phpClass = EntityHelper.resolveShortcutName(project, table);
          if (phpClass != null) {
            table = phpClass.getPresentableFQN();
          }

          roots.put(table, alias);
        }
      }
    }

    // we have a valid root so add it
    if (rootAlias != null && repository != null) {
      roots.put(repository, rootAlias);
    }

    // we found a alias but not a repository name, so try a scope search if we are inside repository
    // class
    // class implements \Doctrine\Common\Persistence\ObjectRepository, so search for model name of
    // "repositoryClass"
    if (rootAlias != null && repository == null) {
      MethodReference methodReference = methodReferences.iterator().next();
      PhpClass phpClass = PsiTreeUtil.getParentOfType(methodReference, PhpClass.class);
      if (new Symfony2InterfacesUtil()
          .isInstanceOf(phpClass, "\\Doctrine\\Common\\Persistence\\ObjectRepository")) {
        for (DoctrineModel model : EntityHelper.getModelClasses(project)) {
          String className = model.getPhpClass().getPresentableFQN();
          if (className != null) {
            PhpClass resolvedRepoName = EntityHelper.getEntityRepositoryClass(project, className);
            if (PhpElementsUtil.isEqualClassName(resolvedRepoName, phpClass.getPresentableFQN())) {
              roots.put(className, rootAlias);
              return roots;
            }
          }
        }
      }
    }

    // search on PhpTypeProvider
    // $er->createQueryBuilder()
    if (rootAlias != null && repository == null) {
      for (MethodReference methodReference : methodReferences) {
        if ("createQueryBuilder".equals(methodReference.getName())) {
          String signature = methodReference.getSignature();
          int endIndex = signature.lastIndexOf(ObjectRepositoryTypeProvider.TRIM_KEY);
          if (endIndex != -1) {
            String parameter = signature.substring(endIndex + 1);
            int point = parameter.indexOf(".");
            if (point > -1) {
              parameter = parameter.substring(0, point);
              parameter =
                  PhpTypeProviderUtil.getResolvedParameter(
                      PhpIndex.getInstance(project), parameter);
              if (parameter != null) {
                PhpClass phpClass = EntityHelper.resolveShortcutName(project, parameter);
                if (phpClass != null && phpClass.getPresentableFQN() != null) {
                  roots.put(phpClass.getPresentableFQN(), rootAlias);
                  return roots;
                }
              }
            }
          }
        }
      }
    }

    return roots;
  }