• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.statementservice.retriever;
18 
19 import android.annotation.NonNull;
20 
21 import java.util.regex.Pattern;
22 
23 /**
24  * An immutable value type representing a statement relation with "kind" and "detail".
25  *
26  * <p> The set of kinds is enumerated by the API: <ul> <li> <b>delegate_permission</b>: The detail
27  * field specifies which permission to delegate. A statement involving this relation does not
28  * constitute a requirement to do the delegation, just a permission to do so. </ul>
29  *
30  * <p> We may add other kinds in the future.
31  *
32  * <p> The detail field is a lowercase alphanumeric string with underscores and periods allowed
33  * (matching the regex [a-z0-9_.]+), but otherwise unstructured.
34  */
35 public final class Relation {
36 
37     private static final Pattern KIND_PATTERN = Pattern.compile("^[a-z0-9_.]+$");
38     private static final Pattern DETAIL_PATTERN = Pattern.compile("^([a-z0-9_.]+)$");
39 
40     private final String mKind;
41     private final String mDetail;
42 
Relation(String kind, String detail)43     private Relation(String kind, String detail) {
44         mKind = kind;
45         mDetail = detail;
46     }
47 
48     /**
49      * Returns the relation's kind.
50      */
51     @NonNull
getKind()52     public String getKind() {
53         return mKind;
54     }
55 
56     /**
57      * Returns the relation's detail.
58      */
59     @NonNull
getDetail()60     public String getDetail() {
61         return mDetail;
62     }
63 
64     /**
65      * Creates a new Relation object for the specified {@code kind} and {@code detail}.
66      *
67      * @throws AssociationServiceException if {@code kind} or {@code detail} is not well formatted.
68      */
create(@onNull String kind, @NonNull String detail)69     public static Relation create(@NonNull String kind, @NonNull String detail)
70             throws AssociationServiceException {
71         if (!KIND_PATTERN.matcher(kind).matches() || !DETAIL_PATTERN.matcher(detail).matches()) {
72             throw new AssociationServiceException("Relation not well formatted.");
73         }
74         return new Relation(kind, detail);
75     }
76 
77     /**
78      * Creates a new Relation object from its string representation.
79      *
80      * @throws AssociationServiceException if the relation is not well formatted.
81      */
create(@onNull String relation)82     public static Relation create(@NonNull String relation) throws AssociationServiceException {
83         String[] r = relation.split("/", 2);
84         if (r.length != 2) {
85             throw new AssociationServiceException("Relation not well formatted.");
86         }
87         return create(r[0], r[1]);
88     }
89 
90     /**
91      * Returns true if {@code relation} has the same kind and detail.
92      */
matches(Relation relation)93     public boolean matches(Relation relation) {
94         return getKind().equals(relation.getKind()) && getDetail().equals(relation.getDetail());
95     }
96 
97     /**
98      * Returns a string representation of this relation.
99      */
100     @Override
toString()101     public String toString() {
102         StringBuilder relation = new StringBuilder();
103         relation.append(getKind());
104         relation.append("/");
105         relation.append(getDetail());
106         return relation.toString();
107     }
108 
109     // equals() and hashCode() are generated by Android Studio.
110     @Override
equals(Object o)111     public boolean equals(Object o) {
112         if (this == o) {
113             return true;
114         }
115         if (o == null || getClass() != o.getClass()) {
116             return false;
117         }
118 
119         Relation relation = (Relation) o;
120 
121         if (mDetail != null ? !mDetail.equals(relation.mDetail) : relation.mDetail != null) {
122             return false;
123         }
124         if (mKind != null ? !mKind.equals(relation.mKind) : relation.mKind != null) {
125             return false;
126         }
127 
128         return true;
129     }
130 
131     @Override
hashCode()132     public int hashCode() {
133         int result = mKind != null ? mKind.hashCode() : 0;
134         result = 31 * result + (mDetail != null ? mDetail.hashCode() : 0);
135         return result;
136     }
137 }
138