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
17package com.android.statementservice.retriever;
18
19import android.annotation.NonNull;
20
21/**
22 * An immutable value type representing a statement, consisting of a source, target, and relation.
23 * This reflects an assertion that the relation holds for the source, target pair. For example, if a
24 * web site has the following in its assetlinks.json file:
25 *
26 * <pre>
27 * {
28 * "relation": ["delegate_permission/common.handle_all_urls"],
29 * "target"  : {"namespace": "android_app", "package_name": "com.example.app",
30 *              "sha256_cert_fingerprints": ["00:11:22:33"] }
31 * }
32 * </pre>
33 *
34 * Then invoking {@link AbstractStatementRetriever#retrieveStatements(AbstractAsset)} will return a
35 * {@link Statement} with {@link #getSource} equal to the input parameter, {@link #getRelation}
36 * equal to
37 *
38 * <pre>Relation.create("delegate_permission", "common.get_login_creds");</pre>
39 *
40 * and with {@link #getTarget} equal to
41 *
42 * <pre>AbstractAsset.create("{\"namespace\" : \"android_app\","
43 *                           + "\"package_name\": \"com.example.app\"}"
44 *                           + "\"sha256_cert_fingerprints\": \"[\"00:11:22:33\"]\"}");
45 * </pre>
46 */
47public final class Statement {
48
49    private final AbstractAsset mTarget;
50    private final Relation mRelation;
51    private final AbstractAsset mSource;
52
53    private Statement(AbstractAsset source, AbstractAsset target, Relation relation) {
54        mSource = source;
55        mTarget = target;
56        mRelation = relation;
57    }
58
59    /**
60     * Returns the source asset of the statement.
61     */
62    @NonNull
63    public AbstractAsset getSource() {
64        return mSource;
65    }
66
67    /**
68     * Returns the target asset of the statement.
69     */
70    @NonNull
71    public AbstractAsset getTarget() {
72        return mTarget;
73    }
74
75    /**
76     * Returns the relation of the statement.
77     */
78    @NonNull
79    public Relation getRelation() {
80        return mRelation;
81    }
82
83    /**
84     * Creates a new Statement object for the specified target asset and relation. For example:
85     * <pre>
86     *   Asset asset = Asset.Factory.create(
87     *       "{\"namespace\" : \"web\",\"site\": \"https://www.test.com\"}");
88     *   Relation relation = Relation.create("delegate_permission", "common.get_login_creds");
89     *   Statement statement = Statement.create(asset, relation);
90     * </pre>
91     */
92    public static Statement create(@NonNull AbstractAsset source, @NonNull AbstractAsset target,
93                                   @NonNull Relation relation) {
94        return new Statement(source, target, relation);
95    }
96
97    @Override
98    public boolean equals(Object o) {
99        if (this == o) {
100            return true;
101        }
102        if (o == null || getClass() != o.getClass()) {
103            return false;
104        }
105
106        Statement statement = (Statement) o;
107
108        if (!mRelation.equals(statement.mRelation)) {
109            return false;
110        }
111        if (!mTarget.equals(statement.mTarget)) {
112            return false;
113        }
114        if (!mSource.equals(statement.mSource)) {
115            return false;
116        }
117
118        return true;
119    }
120
121    @Override
122    public int hashCode() {
123        int result = mTarget.hashCode();
124        result = 31 * result + mRelation.hashCode();
125        result = 31 * result + mSource.hashCode();
126        return result;
127    }
128
129    @Override
130    public String toString() {
131        StringBuilder statement = new StringBuilder();
132        statement.append("Statement: ");
133        statement.append(mSource);
134        statement.append(", ");
135        statement.append(mTarget);
136        statement.append(", ");
137        statement.append(mRelation);
138        return statement.toString();
139    }
140}
141