@Nonnull
  public ConstructorCallInfo findConstructorCallInfoForField(
      @Nonnull String simpleName, @Nonnull TypeMirror type) throws IllegalArgumentException {
    ConstructorDeclaration constructorDeclaration = TypeUtils.findBestConstructor(classDeclaration);

    int index = 0;

    for (ParameterDeclaration parameterDeclaration : constructorDeclaration.getParameters()) {
      if (parameterDeclaration.getSimpleName().equals(simpleName)) {
        // Found a fitting type
        if (TypeUtils.mightBeConstructorCallFor(parameterDeclaration.getType(), type)) {
          return new ConstructorCallInfo(constructorDeclaration, index, parameterDeclaration);
        } else {
          throw new IllegalArgumentException(
              "Type mismatch for <"
                  + simpleName
                  + ">. Was <"
                  + parameterDeclaration.getType()
                  + "> but expected <"
                  + type
                  + ">");
        }
      }
      index++;
    }

    throw new IllegalArgumentException("No parameter found that fits <" + simpleName + ">");
  }
  @Nonnull
  public DomainObjectDescriptor create() {
    DomainObjectDescriptor domainObjectDescriptor = new DomainObjectDescriptor(classDeclaration);

    Collection<FieldDeclaration> fields =
        TypeUtils.findFieldsIncludingSuperClasses(classDeclaration);
    for (FieldDeclaration fieldDeclaration : fields) {
      if (TypeUtils.isStatic(fieldDeclaration)) {
        continue;
      }
      FieldWithInitializationInfo info = getFieldWithInitializationInfo(fieldDeclaration);
      domainObjectDescriptor.addField(info);
    }

    return domainObjectDescriptor;
  }
 @Nonnull
 public FieldInitializedInConstructorInfo findFieldInitializedInConstructor(
     @Nonnull String simpleName) {
   FieldDeclaration fieldDeclaration =
       TypeUtils.findFieldDeclaration(classDeclaration, simpleName);
   return getFieldInitializeInConstructorInfo(fieldDeclaration);
 }
 @Nonnull
 public FieldInitializedInConstructorInfo getFieldInitializeInConstructorInfo(
     @Nonnull FieldDeclaration fieldDeclaration) {
   ConstructorCallInfo constructorCallInfo = findConstructorCallInfoForField(fieldDeclaration);
   MethodDeclaration getterDeclaration =
       TypeUtils.findGetterForField(classDeclaration, fieldDeclaration);
   return new FieldInitializedInConstructorInfo(
       fieldDeclaration, getterDeclaration, constructorCallInfo);
 }
  @Nonnull
  public FieldWithInitializationInfo getFieldWithInitializationInfo(
      @Nonnull FieldDeclaration fieldDeclaration) {
    MethodDeclaration getterDeclaration =
        TypeUtils.findGetterForField(classDeclaration, fieldDeclaration);

    // At first look for fields that are initialized within the constructor
    try {
      ConstructorCallInfo constructorCallInfo = findConstructorCallInfoForField(fieldDeclaration);
      return new FieldInitializedInConstructorInfo(
          fieldDeclaration, getterDeclaration, constructorCallInfo);
    } catch (IllegalArgumentException ignore) {
    }

    // Now look for fields that have a setter
    try {
      MethodDeclaration setter = TypeUtils.findSetter(classDeclaration, fieldDeclaration);
      return new FieldInitializedInSetterInfo(fieldDeclaration, getterDeclaration, setter);
    } catch (IllegalArgumentException ignore) {
    }

    // Ok, return a read only field descriptor
    return new FieldNotInitializationInfo(fieldDeclaration, getterDeclaration);
  }