Package com.getperka.flatpack.ext

Source Code of com.getperka.flatpack.ext.Property$Builder

/*
* #%L
* FlatPack serialization code
* %%
* Copyright (C) 2012 Perka Inc.
* %%
* 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.
* #L%
*/
package com.getperka.flatpack.ext;

import static com.getperka.flatpack.util.FlatPackTypes.hasAnnotationWithSimpleName;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;

import javax.inject.Inject;

import com.getperka.flatpack.BaseHasUuid;
import com.getperka.flatpack.HasUuid;
import com.getperka.flatpack.JsonProperty;
import com.getperka.flatpack.SuppressDefaultValue;
import com.getperka.flatpack.security.GroupPermissions;
import com.getperka.flatpack.security.SecurityGroups;
import com.getperka.flatpack.util.UuidDigest;

/**
* An immutable view of a property that should be serialized.
*/
public class Property extends BaseHasUuid {

  /**
   * Constructs {@link Property} instances.
   */
  static class Builder {
    @Inject
    private Property prop;
    @Inject
    SecurityGroups security;
    @Inject
    private TypeContext typeContext;

    Builder() {}

    public Property build() {
      Property toReturn = prop;
      prop = null;

      Method getter = toReturn.getGetter();
      Method setter = toReturn.getSetter();

      if (getter != null) {
        java.lang.reflect.Type returnType = getter.getGenericReturnType();
        toReturn.codex = typeContext.getCodex(returnType);
        analyzeAnnotations(toReturn, getter);
      } else if (setter != null) {
        java.lang.reflect.Type paramType = setter.getGenericParameterTypes()[0];
        toReturn.codex = typeContext.getCodex(paramType);
        analyzeAnnotations(toReturn, setter);
      } else {
        throw new IllegalStateException("No getter or setter");
      }
      toReturn.type = toReturn.codex.describe();

      return toReturn;
    }

    /**
     * Returns the Property object under construction.
     */
    public Property peek() {
      return prop;
    }

    public Builder withDeepTraversalOnly(boolean only) {
      prop.deepTraversalOnly = only;
      return this;
    }

    public Builder withGetter(Method getter) {
      getter.setAccessible(true);
      prop.getter = getter;

      if (prop.enclosingType == null) {
        Class<? extends HasUuid> enclosingType =
            getter.getDeclaringClass().asSubclass(HasUuid.class);
        prop.enclosingType = typeContext.describe(enclosingType);
      }

      return this;
    }

    public Builder withImpliedProperty(Property implied) {
      prop.implied = implied;
      return this;
    }

    public Builder withName(String name) {
      prop.name = name;
      return this;
    }

    public Builder withSetter(Method setter) {
      setter.setAccessible(true);
      prop.setter = setter;

      if (prop.enclosingType == null) {
        Class<? extends HasUuid> enclosingType =
            setter.getDeclaringClass().asSubclass(HasUuid.class);
        prop.enclosingType = typeContext.describe(enclosingType);
      }
      return this;
    }

    private void analyzeAnnotations(Property toReturn, AnnotatedElement method) {
      toReturn.embedded = hasAnnotationWithSimpleName(method, "Embedded");
      toReturn.suppressDefaultValue = method.isAnnotationPresent(SuppressDefaultValue.class);
    }
  }

  /**
   * Sorts Property objects by {@link #getName()}.
   */
  public static final Comparator<Property> PROPERTY_NAME_COMPARATOR = new Comparator<Property>() {
    @Override
    public int compare(Property o1, Property o2) {
      return o1.getName().compareTo(o2.getName());
    }
  };

  private Codex<?> codex;
  private boolean deepTraversalOnly;
  /**
   * This property exists for exposing annotations to callers.
   */
  private List<Annotation> docAnnotations;
  /**
   * This property is mutable by external callers. It's kind of a hack to allow the describe
   * endpoint to lazily add the doc strings.
   */
  private String docString;
  private EntityDescription enclosingType;
  private boolean embedded;
  private Method getter;
  private GroupPermissions groupPermissions;
  private Property implied;
  private String name;
  private Method setter;
  private boolean suppressDefaultValue;
  private Type type;

  @Inject
  private Property() {}

  @NoPack
  public Codex<?> getCodex() {
    return codex;
  }

  /**
   * Annotations that provide additional information about the entity. This could include
   * deprecation or JSR-303 validation constraints.
   * <p>
   * The value of this property will not influence any runtime behavior in the Flatpack
   * serialization code.
   */
  public List<Annotation> getDocAnnotations() {
    return docAnnotations;
  }

  public String getDocString() {
    return docString;
  }

  /**
   * The {@link EntityDescription} that defines the property.
   */
  public EntityDescription getEnclosingType() {
    return enclosingType;
  }

  /**
   * Returns the getter method for this Property. The returned method will have a non-{@code void}
   * return type and no parameters.
   */
  @NoPack
  public Method getGetter() {
    return getter;
  }

  /**
   * Returns the security permissions that govern access to the property.
   */
  public GroupPermissions getGroupPermissions() {
    return groupPermissions;
  }

  /**
   * When a new value is assigned to the current property in some instance, the implied property of
   * the new value should also be updated with the current instance.
   */
  public Property getImpliedProperty() {
    return implied;
  }

  /**
   * Returns the json payload name of the Property, which may differ from the bean name if a
   * {@link JsonProperty} annotation has been applied to the getter.
   */
  public String getName() {
    return name;
  }

  /**
   * Returns the optional setter for the property. The returned method will have a single parameter
   * and a {@code void} return type.
   */
  @NoPack
  public Method getSetter() {
    return setter;
  }

  /**
   * A simplified description of the property's type.
   */
  public Type getType() {
    return type;
  }

  /**
   * Returns {@code true} if the Property should be included only during a deep traversal.
   */
  public boolean isDeepTraversalOnly() {
    return deepTraversalOnly;
  }

  /**
   * Returns {@code true} if an entity Property's properties should be emitted into the owning
   * entity's properties.
   */
  public boolean isEmbedded() {
    return embedded;
  }

  /**
   * If {@code true}, non-null properties that contain the property type's default value will not be
   * serialized. For example, integer properties whose values are {@code 0} will not be serialized.
   */
  public boolean isSuppressDefaultValue() {
    return suppressDefaultValue;
  }

  public void setDocAnnotations(List<Annotation> docAnnotations) {
    this.docAnnotations = docAnnotations;
  }

  public void setDocString(String docString) {
    this.docString = docString;
  }

  public void setGroupPermissions(GroupPermissions groupPermissions) {
    this.groupPermissions = groupPermissions;
  }

  /**
   * For debugging use only.
   */
  @Override
  public String toString() {
    return getEnclosingType().getTypeName() + "." + getName() + " ::= " + getType();
  }

  @Override
  protected UUID defaultUuid() {
    if (getEnclosingType() == null || getName() == null) {
      throw new IllegalStateException();
    }
    return new UuidDigest(getClass()).add(getEnclosingType()).add(name).digest();
  }

  void setDeepTraversalOnly(boolean deepTraversalOnly) {
    this.deepTraversalOnly = deepTraversalOnly;
  }

  void setEmbedded(boolean embedded) {
    this.embedded = embedded;
  }

  void setEnclosingType(EntityDescription enclosingType) {
    this.enclosingType = enclosingType;
  }

  void setImplied(Property implied) {
    this.implied = implied;
  }

  /**
   * Use for late fixups of implied properties when the OneToMany property is examined after the
   * ManyToOne relationship.
   */
  void setImpliedProperty(Property implied) {
    this.implied = implied;
  }

  void setName(String name) {
    this.name = name;
  }

  void setSuppressDefaultValue(boolean suppressDefaultValue) {
    this.suppressDefaultValue = suppressDefaultValue;
  }

  void setType(Type type) {
    this.type = type;
  }
}
TOP

Related Classes of com.getperka.flatpack.ext.Property$Builder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.