1919import static com .google .common .base .Preconditions .checkArgument ;
2020import static com .google .common .base .Preconditions .checkNotNull ;
2121
22+ import com .google .common .base .Function ;
23+ import com .google .common .base .MoreObjects ;
2224import com .google .common .collect .ImmutableMap ;
2325import com .google .common .collect .ImmutableSet ;
26+ import com .google .common .collect .Lists ;
27+ import com .google .protobuf .ByteString ;
2428
2529import java .io .Serializable ;
30+ import java .util .ArrayList ;
2631import java .util .Arrays ;
2732import java .util .HashMap ;
2833import java .util .HashSet ;
2934import java .util .LinkedHashSet ;
35+ import java .util .LinkedList ;
36+ import java .util .List ;
3037import java .util .Map ;
3138import java .util .Objects ;
3239import java .util .Set ;
3744 * a set of identities to a role, where the identities can be user accounts, Google groups, Google
3845 * domains, and service accounts. A role is a named list of permissions defined by IAM.
3946 *
40- * @param <R> the data type of roles (should be serializable)
4147 * @see <a href="https://cloud.google.com/iam/reference/rest/v1/Policy">Policy</a>
4248 */
43- public abstract class IamPolicy < R > implements Serializable {
49+ public final class Policy implements Serializable {
4450
45- private static final long serialVersionUID = 1114489978726897720L ;
51+ private static final long serialVersionUID = - 3348914530232544290L ;
4652
47- private final Map <R , Set <Identity >> bindings ;
53+ private final Map <Role , Set <Identity >> bindings ;
4854 private final String etag ;
49- private final Integer version ;
55+ private final int version ;
56+
57+ public abstract static class Marshaller <T > {
58+
59+ protected static final Function <String , Identity > IDENTITY_VALUE_OF_FUNCTION =
60+ new Function <String , Identity >() {
61+ @ Override
62+ public Identity apply (String identityPb ) {
63+ return Identity .valueOf (identityPb );
64+ }
65+ };
66+ protected static final Function <Identity , String > IDENTITY_STR_VALUE_FUNCTION =
67+ new Function <Identity , String >() {
68+ @ Override
69+ public String apply (Identity identity ) {
70+ return identity .strValue ();
71+ }
72+ };
73+
74+ protected abstract Policy fromPb (T policyPb );
75+
76+ protected abstract T toPb (Policy policy );
77+ }
78+
79+ public static class DefaultMarshaller extends Marshaller <com .google .iam .v1 .Policy > {
80+
81+ @ Override
82+ protected Policy fromPb (com .google .iam .v1 .Policy policyPb ) {
83+ Map <Role , Set <Identity >> bindings = new HashMap <>();
84+ for (com .google .iam .v1 .Binding bindingPb : policyPb .getBindingsList ()) {
85+ bindings .put (Role .of (bindingPb .getRole ()),
86+ ImmutableSet .copyOf (
87+ Lists .transform (bindingPb .getMembersList (), IDENTITY_VALUE_OF_FUNCTION )));
88+ }
89+ return builder ()
90+ .bindings (bindings )
91+ .etag (policyPb .getEtag ().size () == 0 ? null : policyPb .getEtag ().toStringUtf8 ())
92+ .version (policyPb .getVersion ())
93+ .build ();
94+ }
95+
96+ @ Override
97+ protected com .google .iam .v1 .Policy toPb (Policy policy ) {
98+ com .google .iam .v1 .Policy .Builder policyBuilder = com .google .iam .v1 .Policy .newBuilder ();
99+ List <com .google .iam .v1 .Binding > bindingPbList = new LinkedList <>();
100+ for (Map .Entry <Role , Set <Identity >> binding : policy .bindings ().entrySet ()) {
101+ com .google .iam .v1 .Binding .Builder bindingBuilder = com .google .iam .v1 .Binding .newBuilder ();
102+ bindingBuilder .setRole (binding .getKey ().value ());
103+ bindingBuilder .addAllMembers (
104+ Lists .transform (new ArrayList <>(binding .getValue ()), IDENTITY_STR_VALUE_FUNCTION ));
105+ bindingPbList .add (bindingBuilder .build ());
106+ }
107+ policyBuilder .addAllBindings (bindingPbList );
108+ if (policy .etag != null ) {
109+ policyBuilder .setEtag (ByteString .copyFromUtf8 (policy .etag ));
110+ }
111+ policyBuilder .setVersion (policy .version );
112+ return policyBuilder .build ();
113+ }
114+ }
50115
51116 /**
52- * Builder for an IAM Policy.
53- *
54- * @param <R> the data type of roles
55- * @param <B> the subclass extending this abstract builder
117+ * A builder for {@code Policy} objects.
56118 */
57- public abstract static class Builder < R , B extends Builder < R , B >> {
119+ public static class Builder {
58120
59- private final Map <R , Set <Identity >> bindings = new HashMap <>();
121+ private final Map <Role , Set <Identity >> bindings = new HashMap <>();
60122 private String etag ;
61- private Integer version ;
123+ private int version ;
62124
63- /**
64- * Constructor for IAM Policy builder.
65- */
66125 protected Builder () {}
67126
127+ protected Builder (Policy policy ) {
128+ bindings (policy .bindings );
129+ etag (policy .etag );
130+ version (policy .version );
131+ }
132+
68133 /**
69134 * Replaces the builder's map of bindings with the given map of bindings.
70135 *
71136 * @throws NullPointerException if the given map is null or contains any null keys or values
72137 * @throws IllegalArgumentException if any identities in the given map are null
73138 */
74- public final B bindings (Map <R , Set <Identity >> bindings ) {
139+ public final Builder bindings (Map <Role , Set <Identity >> bindings ) {
75140 checkNotNull (bindings , "The provided map of bindings cannot be null." );
76- for (Map .Entry <R , Set <Identity >> binding : bindings .entrySet ()) {
141+ for (Map .Entry <Role , Set <Identity >> binding : bindings .entrySet ()) {
77142 checkNotNull (binding .getKey (), "The role cannot be null." );
78143 Set <Identity > identities = binding .getValue ();
79144 checkNotNull (identities , "A role cannot be assigned to a null set of identities." );
80145 checkArgument (!identities .contains (null ), "Null identities are not permitted." );
81146 }
82147 this .bindings .clear ();
83- for (Map .Entry <R , Set <Identity >> binding : bindings .entrySet ()) {
84- this .bindings .put (binding .getKey (), new HashSet <Identity >(binding .getValue ()));
148+ for (Map .Entry <Role , Set <Identity >> binding : bindings .entrySet ()) {
149+ this .bindings .put (binding .getKey (), new HashSet <>(binding .getValue ()));
85150 }
86- return self () ;
151+ return this ;
87152 }
88153
89154 /**
90155 * Removes the role (and all identities associated with that role) from the policy.
91156 */
92- public final B removeRole (R role ) {
157+ public final Builder removeRole (Role role ) {
93158 bindings .remove (role );
94- return self () ;
159+ return this ;
95160 }
96161
97162 /**
98163 * Adds one or more identities to the policy under the role specified.
99164 *
100165 * @throws NullPointerException if the role or any of the identities is null.
101166 */
102- public final B addIdentity (R role , Identity first , Identity ... others ) {
167+ public final Builder addIdentity (Role role , Identity first , Identity ... others ) {
103168 String nullIdentityMessage = "Null identities are not permitted." ;
104169 checkNotNull (first , nullIdentityMessage );
105170 checkNotNull (others , nullIdentityMessage );
@@ -111,18 +176,18 @@ public final B addIdentity(R role, Identity first, Identity... others) {
111176 toAdd .addAll (Arrays .asList (others ));
112177 Set <Identity > identities = bindings .get (checkNotNull (role , "The role cannot be null." ));
113178 if (identities == null ) {
114- identities = new HashSet <Identity >();
179+ identities = new HashSet <>();
115180 bindings .put (role , identities );
116181 }
117182 identities .addAll (toAdd );
118- return self () ;
183+ return this ;
119184 }
120185
121186 /**
122187 * Removes one or more identities from an existing binding. Does nothing if the binding
123188 * associated with the provided role doesn't exist.
124189 */
125- public final B removeIdentity (R role , Identity first , Identity ... others ) {
190+ public final Builder removeIdentity (Role role , Identity first , Identity ... others ) {
126191 Set <Identity > identities = bindings .get (role );
127192 if (identities != null ) {
128193 identities .remove (first );
@@ -131,7 +196,7 @@ public final B removeIdentity(R role, Identity first, Identity... others) {
131196 if (identities != null && identities .isEmpty ()) {
132197 bindings .remove (role );
133198 }
134- return self () ;
199+ return this ;
135200 }
136201
137202 /**
@@ -145,31 +210,31 @@ public final B removeIdentity(R role, Identity first, Identity... others) {
145210 * applied to the same version of the policy. If no etag is provided in the call to
146211 * setIamPolicy, then the existing policy is overwritten blindly.
147212 */
148- protected final B etag (String etag ) {
213+ protected final Builder etag (String etag ) {
149214 this .etag = etag ;
150- return self () ;
215+ return this ;
151216 }
152217
153218 /**
154219 * Sets the version of the policy. The default version is 0, meaning only the "owner", "editor",
155220 * and "viewer" roles are permitted. If the version is 1, you may also use other roles.
156221 */
157- protected final B version (Integer version ) {
222+ protected final Builder version (int version ) {
158223 this .version = version ;
159- return self () ;
224+ return this ;
160225 }
161226
162- @ SuppressWarnings ("unchecked" )
163- private B self () {
164- return (B ) this ;
227+ /**
228+ * Creates a {@code Policy} object.
229+ */
230+ public final Policy build () {
231+ return new Policy (this );
165232 }
166-
167- public abstract IamPolicy <R > build ();
168233 }
169234
170- protected IamPolicy (Builder < R , ? extends Builder < R , ?>> builder ) {
171- ImmutableMap .Builder <R , Set <Identity >> bindingsBuilder = ImmutableMap .builder ();
172- for (Map .Entry <R , Set <Identity >> binding : builder .bindings .entrySet ()) {
235+ private Policy (Builder builder ) {
236+ ImmutableMap .Builder <Role , Set <Identity >> bindingsBuilder = ImmutableMap .builder ();
237+ for (Map .Entry <Role , Set <Identity >> binding : builder .bindings .entrySet ()) {
173238 bindingsBuilder .put (binding .getKey (), ImmutableSet .copyOf (binding .getValue ()));
174239 }
175240 this .bindings = bindingsBuilder .build ();
@@ -180,12 +245,14 @@ protected IamPolicy(Builder<R, ? extends Builder<R, ?>> builder) {
180245 /**
181246 * Returns a builder containing the properties of this IAM Policy.
182247 */
183- public abstract Builder <R , ? extends Builder <R , ?>> toBuilder ();
248+ public Builder toBuilder () {
249+ return new Builder (this );
250+ }
184251
185252 /**
186253 * The map of bindings that comprises the policy.
187254 */
188- public Map <R , Set <Identity >> bindings () {
255+ public Map <Role , Set <Identity >> bindings () {
189256 return bindings ;
190257 }
191258
@@ -208,27 +275,42 @@ public String etag() {
208275 * Sets the version of the policy. The default version is 0, meaning only the "owner", "editor",
209276 * and "viewer" roles are permitted. If the version is 1, you may also use other roles.
210277 */
211- public Integer version () {
278+ public int version () {
212279 return version ;
213280 }
214281
215282 @ Override
216- public final int hashCode () {
283+ public String toString () {
284+ return MoreObjects .toStringHelper (this )
285+ .add ("bindings" , bindings )
286+ .add ("etag" , etag )
287+ .add ("version" , version )
288+ .toString ();
289+ }
290+
291+ @ Override
292+ public int hashCode () {
217293 return Objects .hash (getClass (), bindings , etag , version );
218294 }
219295
220296 @ Override
221- public final boolean equals (Object obj ) {
297+ public boolean equals (Object obj ) {
222298 if (obj == this ) {
223299 return true ;
224300 }
225- if (obj == null || ! obj . getClass (). equals ( getClass () )) {
301+ if (!( obj instanceof Policy )) {
226302 return false ;
227303 }
228- @ SuppressWarnings ("rawtypes" )
229- IamPolicy other = (IamPolicy ) obj ;
304+ Policy other = (Policy ) obj ;
230305 return Objects .equals (bindings , other .bindings ())
231306 && Objects .equals (etag , other .etag ())
232307 && Objects .equals (version , other .version ());
233308 }
309+
310+ /**
311+ * Returns a builder for {@code Policy} objects.
312+ */
313+ public static Builder builder () {
314+ return new Builder ();
315+ }
234316}
0 commit comments