BracketExpr.java revision bb4a033fcd5cd20e5be46ef8ead442dc7db2454d
15cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount/* 25cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * Copyright (C) 2015 The Android Open Source Project 35cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * 45cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * Licensed under the Apache License, Version 2.0 (the "License"); 55cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * you may not use this file except in compliance with the License. 65cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * You may obtain a copy of the License at 75cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * 85cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * http://www.apache.org/licenses/LICENSE-2.0 95cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * 105cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * Unless required by applicable law or agreed to in writing, software 115cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * distributed under the License is distributed on an "AS IS" BASIS, 125cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * See the License for the specific language governing permissions and 145cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * limitations under the License. 155cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount */ 165cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.expr; 185cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer; 20fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass; 216047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.solver.ExecutionPath; 22e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mountimport android.databinding.tool.writer.KCode; 235cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 24bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mountimport com.google.common.collect.Lists; 25bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 266047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport java.util.ArrayList; 275cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mountimport java.util.List; 285cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 295cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mountpublic class BracketExpr extends Expr { 305cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 31af146d6a8c0efcf5682d14047c06866a5548f78fYigit Boyar public enum BracketAccessor { 325cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount ARRAY, 335cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount LIST, 345cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount MAP, 355cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 365cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 375cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount private BracketAccessor mAccessor; 385cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 395cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount BracketExpr(Expr target, Expr arg) { 405cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount super(target, arg); 415cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 425cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 435cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount @Override 4479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) { 45731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar ModelClass targetType = getTarget().getResolvedType(); 465cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount if (targetType.isArray()) { 475cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount mAccessor = BracketAccessor.ARRAY; 48e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount } else if (targetType.isList()) { 495cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount mAccessor = BracketAccessor.LIST; 50e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount } else if (targetType.isMap()) { 515cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount mAccessor = BracketAccessor.MAP; 525cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } else { 535cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount throw new IllegalArgumentException("Cannot determine variable type used in [] " + 548e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount "expression. Cast the value to List, Map, " + 558e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount "or array. Type detected: " + targetType.toJavaCode()); 565cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 57e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount return targetType.getComponentType(); 585cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 595cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 605cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount @Override 616047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) { 626047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final List<ExecutionPath> targetPaths = getTarget().toExecutionPath(paths); 636047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // after this, we need a null check. 646047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar List<ExecutionPath> result = new ArrayList<ExecutionPath>(); 656047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (getTarget() instanceof StaticIdentifierExpr) { 666047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar result.addAll(toExecutionPathInOrder(paths, getTarget())); 676047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } else { 686047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar for (ExecutionPath path : targetPaths) { 696047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Expr cmp = getModel().comparison("!=", getTarget(), 706047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar getModel().symbol("null", Object.class)); 716047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar path.addPath(cmp); 726047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final ExecutionPath subPath = path.addBranch(cmp, true); 736047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (subPath != null) { 746047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final List<ExecutionPath> argPath = getArg().toExecutionPath(subPath); 756047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar result.addAll(addJustMeToExecutionPath(argPath)); 766047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 776047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 786047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 796047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return result; 806047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 816047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 826047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 835cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount protected List<Dependency> constructDependencies() { 84e0d5ed7613cb72192430cd2ed8e4159618ca308eGeorge Mount final List<Dependency> dependencies = constructDynamicChildrenDependencies(); 85e0d5ed7613cb72192430cd2ed8e4159618ca308eGeorge Mount for (Dependency dependency : dependencies) { 86e0d5ed7613cb72192430cd2ed8e4159618ca308eGeorge Mount if (dependency.getOther() == getTarget()) { 87e0d5ed7613cb72192430cd2ed8e4159618ca308eGeorge Mount dependency.setMandatory(true); 88e0d5ed7613cb72192430cd2ed8e4159618ca308eGeorge Mount } 89e0d5ed7613cb72192430cd2ed8e4159618ca308eGeorge Mount } 90e0d5ed7613cb72192430cd2ed8e4159618ca308eGeorge Mount return dependencies; 915cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 925cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 935cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount protected String computeUniqueKey() { 94d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount final String targetKey = getTarget().computeUniqueKey(); 95bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return join(targetKey, "$", getArg().computeUniqueKey(), "$"); 96d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 97d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 98d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount @Override 99d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public String getInvertibleError() { 100d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return null; 1015cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 1025cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 1035cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount public Expr getTarget() { 1047920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount return getChildren().get(0); 1055cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 1065cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 1075cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount public Expr getArg() { 1087920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount return getChildren().get(1); 1095cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 1105cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 1115cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount public BracketAccessor getAccessor() { 1125cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount return mAccessor; 1135cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 1145cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 1155cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount public boolean argCastsInteger() { 116d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mAccessor != BracketAccessor.MAP && getArg().getResolvedType().isObject(); 1175cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 118e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount 119e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount @Override 120bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount protected KCode generateCode() { 12176b791f78542a2feb191482a2204de95eaf8ee72George Mount String cast = argCastsInteger() ? "(Integer) " : ""; 122e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount switch (getAccessor()) { 12376b791f78542a2feb191482a2204de95eaf8ee72George Mount case ARRAY: { 12476b791f78542a2feb191482a2204de95eaf8ee72George Mount return new KCode(). 12576b791f78542a2feb191482a2204de95eaf8ee72George Mount app("getFromArray(", getTarget().toCode()). 12676b791f78542a2feb191482a2204de95eaf8ee72George Mount app(", "). 12776b791f78542a2feb191482a2204de95eaf8ee72George Mount app(cast, getArg().toCode()).app(")"); 12876b791f78542a2feb191482a2204de95eaf8ee72George Mount } 12976b791f78542a2feb191482a2204de95eaf8ee72George Mount case LIST: { 13076b791f78542a2feb191482a2204de95eaf8ee72George Mount ModelClass listType = ModelAnalyzer.getInstance().findClass(java.util.List.class). 13176b791f78542a2feb191482a2204de95eaf8ee72George Mount erasure(); 13276b791f78542a2feb191482a2204de95eaf8ee72George Mount ModelClass targetType = getTarget().getResolvedType().erasure(); 13376b791f78542a2feb191482a2204de95eaf8ee72George Mount if (listType.isAssignableFrom(targetType)) { 13476b791f78542a2feb191482a2204de95eaf8ee72George Mount return new KCode(). 13576b791f78542a2feb191482a2204de95eaf8ee72George Mount app("getFromList(", getTarget().toCode()). 13676b791f78542a2feb191482a2204de95eaf8ee72George Mount app(", "). 13776b791f78542a2feb191482a2204de95eaf8ee72George Mount app(cast, getArg().toCode()). 13876b791f78542a2feb191482a2204de95eaf8ee72George Mount app(")"); 13976b791f78542a2feb191482a2204de95eaf8ee72George Mount } else { 14076b791f78542a2feb191482a2204de95eaf8ee72George Mount return new KCode(). 14176b791f78542a2feb191482a2204de95eaf8ee72George Mount app("", getTarget().toCode()). 14276b791f78542a2feb191482a2204de95eaf8ee72George Mount app(".get("). 14376b791f78542a2feb191482a2204de95eaf8ee72George Mount app(cast, getArg().toCode()). 14476b791f78542a2feb191482a2204de95eaf8ee72George Mount app(")"); 145e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount } 14676b791f78542a2feb191482a2204de95eaf8ee72George Mount } 147e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount case MAP: 14876b791f78542a2feb191482a2204de95eaf8ee72George Mount return new KCode(). 14976b791f78542a2feb191482a2204de95eaf8ee72George Mount app("", getTarget().toCode()). 15076b791f78542a2feb191482a2204de95eaf8ee72George Mount app(".get(", getArg().toCode()). 15176b791f78542a2feb191482a2204de95eaf8ee72George Mount app(")"); 152e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount } 153e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount throw new IllegalStateException("Invalid BracketAccessor type"); 154e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount } 155d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 156d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount @Override 157bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) { 158bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount Expr arg = getArg().cloneToModel(model); 159bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount arg = argCastsInteger() 160bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount ? model.castExpr("int", model.castExpr("Integer", arg)) 161bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount : arg; 162bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount StaticIdentifierExpr viewDataBinding = 163bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount model.staticIdentifier(ModelAnalyzer.VIEW_DATA_BINDING); 164bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount viewDataBinding.setUserDefinedType(ModelAnalyzer.VIEW_DATA_BINDING); 165bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount ModelClass targetType = getTarget().getResolvedType(); 166bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount if ((targetType.isList() || targetType.isMap()) && 167bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount value.getResolvedType().isPrimitive()) { 168bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount ModelClass boxed = value.getResolvedType().box(); 169bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount value = model.castExpr(boxed.toJavaCode(), value); 170bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 171bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount List<Expr> args = Lists.newArrayList(getTarget().cloneToModel(model), arg, value); 172bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount MethodCallExpr setter = model.methodCall(viewDataBinding, "setTo", args); 173bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount setter.setAllowProtected(); 174bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return setter; 175bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 176bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 177bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount @Override 178bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public Expr cloneToModel(ExprModel model) { 179bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return model.bracketExpr(getTarget().cloneToModel(model), getArg().cloneToModel(model)); 180bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 181bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 182bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount @Override 183bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public String toString() { 184bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return getTarget().toString() + '[' + getArg() + ']'; 185d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 1865cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount} 187