All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.inferred.freebuilder.processor.Metadata Maven / Gradle / Ivy

There is a newer version: 2.8.0
Show newest version
/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.inferred.freebuilder.processor;

import static com.google.common.base.Preconditions.checkState;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Ordering;

import org.inferred.freebuilder.processor.util.Excerpt;
import org.inferred.freebuilder.processor.util.ParameterizedType;
import org.inferred.freebuilder.processor.util.QualifiedName;
import org.inferred.freebuilder.processor.util.SourceBuilder;

import javax.annotation.Nullable;
import javax.lang.model.type.TypeMirror;

/**
 * Metadata about a @{@link org.inferred.freebuilder.FreeBuilder FreeBuilder} type.
 */
public abstract class Metadata {

  /** Standard Java methods that may be underridden. */
  public enum StandardMethod {
    TO_STRING, HASH_CODE, EQUALS
  }

  /** How compulsory the underride is. */
  public enum UnderrideLevel {
    /** There is no underride. */
    ABSENT,
    /** The underride can be overridden (viz. to respect Partials). */
    OVERRIDEABLE,
    /** The underride is declared final. */
    FINAL;
  }

  public enum Visibility implements Excerpt {
    PUBLIC("public "), PROTECTED("protected "), PACKAGE(""), PRIVATE("private ");

    private final String excerpt;

    private Visibility(String excerpt) {
      this.excerpt = excerpt;
    }

    public static Visibility mostVisible(Visibility a, Visibility b) {
      return Ordering.natural().min(a, b);
    }

    @Override
    public void addTo(SourceBuilder code) {
      code.add(excerpt);
    }
  }

  /** Returns the type itself. */
  public abstract ParameterizedType getType();

  /** Returns true if the type is an interface. */
  public abstract boolean isInterfaceType();

  abstract Optional getOptionalBuilder();

  /**
   * Returns true if there is a user-visible Builder subclass defined.
   */
  public boolean hasBuilder() {
    return getOptionalBuilder().isPresent();
  }

  /**
   * Returns the builder type that users will see.
   *
   * @throws IllegalStateException if {@link #hasBuilder} returns false.
   */
  public ParameterizedType getBuilder() {
    return getOptionalBuilder().get();
  }

  /** Returns the builder factory mechanism the user has exposed, if any. */
  public abstract Optional getBuilderFactory();

  /** Returns the builder class that should be generated. */
  public abstract ParameterizedType getGeneratedBuilder();

  /** Returns the value class that should be generated. */
  public abstract ParameterizedType getValueType();

  /** Returns the partial value class that should be generated. */
  public abstract ParameterizedType getPartialType();

  /**
   * Returns a set of nested types that will be visible in the generated class, either because they
   * will be generated, or because they are present in a superclass.
   */
  public abstract ImmutableSet getVisibleNestedTypes();

  /** Returns the Property enum that may be generated. */
  public abstract ParameterizedType getPropertyEnum();

  /** Returns metadata about the properties of the type. */
  public abstract ImmutableList getProperties();

  public UnderrideLevel standardMethodUnderride(StandardMethod standardMethod) {
    UnderrideLevel underrideLevel = getStandardMethodUnderrides().get(standardMethod);
    return (underrideLevel == null) ? UnderrideLevel.ABSENT : underrideLevel;
  }

  public abstract ImmutableMap getStandardMethodUnderrides();

  /** Returns whether the builder type should be serializable. */
  public abstract boolean isBuilderSerializable();

  /** Returns a list of annotations that should be applied to the generated builder class. */
  public abstract ImmutableList getGeneratedBuilderAnnotations();

  /** Returns a list of annotations that should be applied to the generated value class. */
  public abstract ImmutableList getValueTypeAnnotations();

  /** Returns the visibility of the generated value class. */
  public abstract Visibility getValueTypeVisibility();

  /** Returns a list of nested classes that should be added to the generated builder class. */
  public abstract ImmutableList> getNestedClasses();

  /** Metadata about a property of a {@link Metadata}. */
  public interface Property {

    /** Returns the type of the property. */
    TypeMirror getType();

    /** Returns the boxed form of {@link #getType()}, or null if type is not primitive. */
    @Nullable TypeMirror getBoxedType();

    /** Returns the name of the property, e.g. myProperty. */
    String getName();

    /** Returns the capitalized name of the property, e.g. MyProperty. */
    String getCapitalizedName();

    /** Returns the name of the property in all-caps with underscores, e.g. MY_PROPERTY. */
    String getAllCapsName();

    /** Returns the name of the getter for the property, e.g. getMyProperty, or isSomethingTrue. */
    String getGetterName();

    /**
     * Returns the code generator to use for this property, or null if no generator has been picked
     * (i.e. when passed to {@link PropertyCodeGenerator.Factory#create}.
     */
    @Nullable PropertyCodeGenerator getCodeGenerator();

    /**
     * Returns true if a cast to this property type is guaranteed to be fully checked at runtime.
     * This is true for any type that is non-generic, raw, or parameterized with unbounded
     * wildcards, such as {@code Integer}, {@code List} or {@code Map}.
     */
    boolean isFullyCheckedCast();

    /**
     * Returns a list of annotations that should be applied to the accessor methods of this
     * property; that is, the getter method, and a single setter method that will accept the result
     * of the getter method as its argument. For a list, for example, that would be getX() and
     * addAllX().
     */
    ImmutableList getAccessorAnnotations();

    /** Builder for {@link Property}. */
    class Builder extends Metadata_Property_Builder {}
  }

  public static final Function GET_CODE_GENERATOR =
      new Function() {
        @Override
        public PropertyCodeGenerator apply(Property input) {
          return input.getCodeGenerator();
        }
      };

  /** Builder for {@link Metadata}. */
  public static class Builder extends Metadata_Builder {

    public Builder() {
      super.setValueTypeVisibility(Visibility.PRIVATE);
    }

  /**
   * Sets the value to be returned by {@link Metadata#getValueTypeVisibility()} to the most visible
   * of the current value and {@code visibility}. Will not decrease visibility.
   *
   * @return this {@code Builder} object
   * @throws NullPointerException if {@code visibility} is null
   */
    @Override
    public Builder setValueTypeVisibility(Visibility visibility) {
      return super.setValueTypeVisibility(
          Visibility.mostVisible(getValueTypeVisibility(), visibility));
    }

    /** Sets the builder class that users will see, if any. */
    public Builder setBuilder(Optional builder) {
      return setOptionalBuilder(builder);
    }

    /** Sets the builder class that users will see. */
    public Builder setBuilder(ParameterizedType builder) {
      return setOptionalBuilder(builder);
    }

    /**
     * Returns a newly-built {@link Metadata} based on the content of the {@code Builder}.
     */
    @Override
    public Metadata build() {
      Metadata metadata = super.build();
      QualifiedName generatedBuilder = metadata.getGeneratedBuilder().getQualifiedName();
      checkState(metadata.getValueType().getQualifiedName().getEnclosingType()
              .equals(generatedBuilder),
          "%s not a nested class of %s", metadata.getValueType(), generatedBuilder);
      checkState(metadata.getPartialType().getQualifiedName().getEnclosingType()
              .equals(generatedBuilder),
          "%s not a nested class of %s", metadata.getPartialType(), generatedBuilder);
      checkState(metadata.getPropertyEnum().getQualifiedName().getEnclosingType()
              .equals(generatedBuilder),
          "%s not a nested class of %s", metadata.getPropertyEnum(), generatedBuilder);
      return metadata;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy