[ 
https://issues.apache.org/jira/browse/JCLOUDS-750?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14166636#comment-14166636
 ] 

Andrea Turli commented on JCLOUDS-750:
--------------------------------------

Thanks [~adriancole] for this suggestion

I personally think our value classes are something that a tool can do certainly 
better than a human. In my experience, writing those it is the most time 
consuming and boring task to me.

I've revamped an old tool created by Adam Lowe to generate "jclouds-domain" 
objects which is able to generate the value class + the builder

i.e. from this incomplete class 

package com.example;

import java.util.List;

import org.jclouds.javax.annotation.Nullable;

import com.google.common.base.MoreObjects;
import com.google.gson.annotations.SerializedName;

public class Acl {

   @SerializedName("UserGroup")
   @Nullable
   private final String userGroup;
   @SerializedName("ResourceRole")
   private final String resourceRole;
   @SerializedName("Permissions")
   @Nullable
   private final List<String> permissions;

to 

package com.example;

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

import java.util.List;
import java.beans.ConstructorProperties;

import javax.inject.Named;

import org.jclouds.javax.annotation.Nullable;

import com.google.common.collect.ImmutableMap;
import com.google.gson.annotations.SerializedName;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.base.Objects.ToStringHelper;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
/**
 * Class Acl
*/
public class Acl {

   @SerializedName("UserGroup")
   private final String userGroup;
   @SerializedName("ResourceRole")
   private final String resourceRole;
   @SerializedName("Permissions")
   private final List<String> permissions;

   @ConstructorProperties({
      "UserGroup", "ResourceRole", "Permissions"
   })
   protected Acl(@Nullable String userGroup, String resourceRole, @Nullable 
List<String> permissions) {
      this.userGroup = userGroup;
      this.resourceRole = checkNotNull(resourceRole, "resourceRole");
      this.permissions = permissions == null ? ImmutableList.<String>of() : 
ImmutableList.copyOf(permissions);      
   }

   @Nullable
   public String getUserGroup() {
      return this.userGroup;
   }

   public String getResourceRole() {
      return this.resourceRole;
   }

   public List<String> getPermissions() {
      return this.permissions;
   }

   @Override
   public int hashCode() {
      return Objects.hashCode(userGroup, resourceRole, permissions);
   }

   @Override
   public boolean equals(Object obj) {
      if (this == obj) return true;
      if (obj == null || getClass() != obj.getClass()) return false;
      Acl that = Acl.class.cast(obj);
      return Objects.equal(this.userGroup, that.userGroup)
               && Objects.equal(this.resourceRole, that.resourceRole)
               && Objects.equal(this.permissions, that.permissions);
   }

   @Override
   public String toString() {
      return MoreObjects.toStringHelper(this)
                        .add("userGroup", userGroup)
                        .add("resourceRole", resourceRole)
                        .add("permissions", permissions)
                        .toString();
   }

   public static Builder builder() {
      return new Builder();
   }

   public Builder toBuilder() {
      return builder().fromAcl(this);
   }

   public static final class Builder {
      protected String userGroup;
      protected String resourceRole;
      protected List<String> permissions = ImmutableList.of();

      /**
      * @see Acl#getUserGroup()
      */
      public Builder userGroup(String userGroup) {
         this.userGroup = userGroup;
         return this;
      }

      /**
      * @see Acl#getResourceRole()
      */
      public Builder resourceRole(String resourceRole) {
         this.resourceRole = resourceRole;
         return this;
      }

      /**
      * @see Acl#getPermissions()
      */
      public Builder permissions(List<String> permissions) {
         this.permissions = ImmutableList.copyOf(checkNotNull(permissions, 
"permissions"));
         return this;
      }

      public Builder permissions(String... in) {
         return permissions(ImmutableList.copyOf(in));
      }

      public Acl build() {
         return new Acl(userGroup, resourceRole, permissions);
      }

      public Builder fromAcl(Acl in) {
         return this
         .userGroup(in.getUserGroup())
         .resourceRole(in.getResourceRole())
         .permissions(in.getPermissions());
      }
   }

}

Of course this needs to be used offline, but it could be a nice helper.
Thoughts?

> Replace hand-written domain classes with Auto-Value ones
> --------------------------------------------------------
>
>                 Key: JCLOUDS-750
>                 URL: https://issues.apache.org/jira/browse/JCLOUDS-750
>             Project: jclouds
>          Issue Type: New Feature
>            Reporter: Adrian Cole
>
> In doing maintenance and ports, I've noticed that we have drift related to 
> using guava to implement hashCode/equals on domain classes. Having an 
> opportunity for a guava incompatibility on something like this is not high 
> value, in my opinion. Moreover, we have a lot of other inconsistency in our 
> value classes, which have caused bugs, and extra review time on pull requests.
> Auto-Value generates concrete implementations and takes out the possibility 
> of inconsistency of field names, Nullability, etc. It is handled at compile 
> time, so doesn't introduce a dependency of note, nor a chance of guava 
> version conflict for our users.
> https://github.com/google/auto/tree/master/value
> While it may be the case that we need custom gson adapters (ex opposed to the 
> ConstructorAnnotation approach), or a revision to our approach, I believe 
> that this work is worthwhile.
> While it is the case that our Builders won't be generated, I still think this 
> is valuable. For example, in many cases, we shouldn't be making Builders 
> anyway (ex. they are read-only objects never instantiated, such as lists). 
> Even if we choose to still write Builders, the problem is isolated there.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to