/** finishView, buildView: $this->vars */
  public static Set<String> getFormViewVars(Project project, String... formTypeNames) {

    Set<String> stringSet = new HashSet<String>();

    ArrayList<PhpClass> phpClasses = new ArrayList<PhpClass>();

    // attach core form phpclass
    // @TODO: add formtype itself
    PhpClass coreForm = FormUtil.getFormTypeToClass(project, "form");
    if (coreForm != null) {
      phpClasses.add(coreForm);
    }

    // for extension can also provide vars
    for (Map.Entry<String, String> entry :
        FormOptionsUtil.getFormExtensionKeys(project, formTypeNames).entrySet()) {
      PhpClass phpClass = PhpElementsUtil.getClassInterface(project, entry.getValue());
      if (phpClass != null) {
        phpClasses.add(phpClass);
      }
    }

    for (PhpClass phpClass : phpClasses) {
      for (String stringMethod : new String[] {"finishView", "buildView"}) {
        Method method = PhpElementsUtil.getClassMethod(phpClass, stringMethod);
        if (method != null) {

          // self method
          getMethodVars(stringSet, method);

          // allow parent::
          // @TODO: provide global util method
          for (ClassReference classReference :
              PsiTreeUtil.collectElementsOfType(method, ClassReference.class)) {
            if ("parent".equals(classReference.getName())) {
              PsiElement methodReference = classReference.getContext();
              if (methodReference instanceof MethodReference) {
                PsiElement parentMethod = ((MethodReference) methodReference).resolve();
                if (parentMethod instanceof Method) {
                  getMethodVars(stringSet, (Method) parentMethod);
                }
              }
            }
          }
        }
      }
    }

    return stringSet;
  }
  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;
  }