• 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 android.databinding.tool.expr;
18 
19 import android.databinding.tool.reflection.ModelAnalyzer;
20 import android.databinding.tool.reflection.ModelClass;
21 import android.databinding.tool.writer.KCode;
22 
23 import java.util.List;
24 
25 public class BracketExpr extends Expr {
26 
27     public enum BracketAccessor {
28         ARRAY,
29         LIST,
30         MAP,
31     }
32 
33     private BracketAccessor mAccessor;
34 
BracketExpr(Expr target, Expr arg)35     BracketExpr(Expr target, Expr arg) {
36         super(target, arg);
37     }
38 
39     @Override
resolveType(ModelAnalyzer modelAnalyzer)40     protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
41         ModelClass targetType = getTarget().getResolvedType();
42         if (targetType.isArray()) {
43             mAccessor = BracketAccessor.ARRAY;
44         } else if (targetType.isList()) {
45             mAccessor = BracketAccessor.LIST;
46         } else if (targetType.isMap()) {
47             mAccessor = BracketAccessor.MAP;
48         } else {
49             throw new IllegalArgumentException("Cannot determine variable type used in [] " +
50                     "expression. Cast the value to List, Map, " +
51                     "or array. Type detected: " + targetType.toJavaCode());
52         }
53         return targetType.getComponentType();
54     }
55 
56     @Override
constructDependencies()57     protected List<Dependency> constructDependencies() {
58         final List<Dependency> dependencies = constructDynamicChildrenDependencies();
59         for (Dependency dependency : dependencies) {
60             if (dependency.getOther() == getTarget()) {
61                 dependency.setMandatory(true);
62             }
63         }
64         return dependencies;
65     }
66 
computeUniqueKey()67     protected String computeUniqueKey() {
68         final String targetKey = getTarget().computeUniqueKey();
69         return addTwoWay(join(targetKey, "$", getArg().computeUniqueKey(), "$"));
70     }
71 
72     @Override
getInvertibleError()73     public String getInvertibleError() {
74         return null;
75     }
76 
getTarget()77     public Expr getTarget() {
78         return getChildren().get(0);
79     }
80 
getArg()81     public Expr getArg() {
82         return getChildren().get(1);
83     }
84 
getAccessor()85     public BracketAccessor getAccessor() {
86         return mAccessor;
87     }
88 
argCastsInteger()89     public boolean argCastsInteger() {
90         return mAccessor != BracketAccessor.MAP && getArg().getResolvedType().isObject();
91     }
92 
93     @Override
generateCode(boolean expand)94     protected KCode generateCode(boolean expand) {
95         String cast = argCastsInteger() ? "(Integer) " : "";
96         switch (getAccessor()) {
97             case ARRAY: {
98                 return new KCode().
99                         app("getFromArray(", getTarget().toCode()).
100                         app(", ").
101                         app(cast, getArg().toCode()).app(")");
102             }
103             case LIST: {
104                 ModelClass listType = ModelAnalyzer.getInstance().findClass(java.util.List.class).
105                         erasure();
106                 ModelClass targetType = getTarget().getResolvedType().erasure();
107                 if (listType.isAssignableFrom(targetType)) {
108                     return new KCode().
109                             app("getFromList(", getTarget().toCode()).
110                             app(", ").
111                             app(cast, getArg().toCode()).
112                             app(")");
113                 } else {
114                     return new KCode().
115                             app("", getTarget().toCode()).
116                             app(".get(").
117                             app(cast, getArg().toCode()).
118                             app(")");
119                 }
120             }
121             case MAP:
122                 return new KCode().
123                         app("", getTarget().toCode()).
124                         app(".get(", getArg().toCode()).
125                         app(")");
126         }
127         throw new IllegalStateException("Invalid BracketAccessor type");
128     }
129 
130     @Override
toInverseCode(KCode value)131     public KCode toInverseCode(KCode value) {
132         String cast = argCastsInteger() ? "(Integer) " : "";
133         return new KCode().
134                 app("setTo(", getTarget().toCode(true)).
135                 app(", ").
136                 app(cast, getArg().toCode(true)).
137                 app(", ", value).app(");");
138     }
139 }
140