ExprModelTest.java revision ee7586713d68806b556a425cbebf007a56261ff3
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 android.databinding.tool.expr; 18 19import com.google.common.base.Predicate; 20import com.google.common.collect.Iterables; 21 22import org.apache.commons.lang3.ArrayUtils; 23import org.apache.commons.lang3.NotImplementedException; 24import org.junit.Before; 25import org.junit.Rule; 26import org.junit.Test; 27import org.junit.rules.TestWatcher; 28import org.junit.runner.Description; 29 30import android.databinding.tool.LayoutBinder; 31import android.databinding.tool.MockLayoutBinder; 32import android.databinding.tool.reflection.ModelAnalyzer; 33import android.databinding.tool.reflection.ModelClass; 34import android.databinding.tool.reflection.java.JavaAnalyzer; 35import android.databinding.tool.util.L; 36 37import java.util.ArrayList; 38import java.util.Arrays; 39import java.util.BitSet; 40import java.util.List; 41 42import static org.junit.Assert.assertEquals; 43import static org.junit.Assert.assertFalse; 44import static org.junit.Assert.assertNotNull; 45import static org.junit.Assert.assertNull; 46import static org.junit.Assert.assertSame; 47import static org.junit.Assert.assertTrue; 48 49public class ExprModelTest { 50 51 private static class DummyExpr extends Expr { 52 53 String mKey; 54 55 public DummyExpr(String key, DummyExpr... children) { 56 super(children); 57 mKey = key; 58 } 59 60 @Override 61 protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) { 62 return modelAnalyzer.findClass(Integer.class); 63 } 64 65 @Override 66 protected List<Dependency> constructDependencies() { 67 return constructDynamicChildrenDependencies(); 68 } 69 70 @Override 71 protected String computeUniqueKey() { 72 return mKey + super.computeUniqueKey(); 73 } 74 } 75 76 ExprModel mExprModel; 77 78 @Rule 79 public TestWatcher mTestWatcher = new TestWatcher() { 80 @Override 81 protected void failed(Throwable e, Description description) { 82 if (mExprModel != null && mExprModel.getFlagMapping() != null) { 83 final String[] mapping = mExprModel.getFlagMapping(); 84 for (int i = 0; i < mapping.length; i++) { 85 L.d("flag %d: %s", i, mapping[i]); 86 } 87 } 88 } 89 }; 90 91 @Before 92 public void setUp() throws Exception { 93 JavaAnalyzer.initForTests(); 94 mExprModel = new ExprModel(); 95 } 96 97 @Test 98 public void testAddNormal() { 99 final DummyExpr d = new DummyExpr("a"); 100 assertSame(d, mExprModel.register(d)); 101 assertSame(d, mExprModel.register(d)); 102 assertEquals(1, mExprModel.mExprMap.size()); 103 } 104 105 @Test 106 public void testAddDupe1() { 107 final DummyExpr d = new DummyExpr("a"); 108 assertSame(d, mExprModel.register(d)); 109 assertSame(d, mExprModel.register(new DummyExpr("a"))); 110 assertEquals(1, mExprModel.mExprMap.size()); 111 } 112 113 @Test 114 public void testAddMultiple() { 115 mExprModel.register(new DummyExpr("a")); 116 mExprModel.register(new DummyExpr("b")); 117 assertEquals(2, mExprModel.mExprMap.size()); 118 } 119 120 121 @Test 122 public void testAddWithChildren() { 123 DummyExpr a = new DummyExpr("a"); 124 DummyExpr b = new DummyExpr("b"); 125 DummyExpr c = new DummyExpr("c", a, b); 126 mExprModel.register(c); 127 DummyExpr a2 = new DummyExpr("a"); 128 DummyExpr b2 = new DummyExpr("b"); 129 DummyExpr c2 = new DummyExpr("c", a, b); 130 assertEquals(c, mExprModel.register(c2)); 131 } 132 133 @Test 134 public void testShouldRead() { 135 LayoutBinder lb = new MockLayoutBinder(); 136 mExprModel = lb.getModel(); 137 IdentifierExpr a = lb.addVariable("a", "java.lang.String"); 138 IdentifierExpr b = lb.addVariable("b", "java.lang.String"); 139 IdentifierExpr c = lb.addVariable("c", "java.lang.String"); 140 lb.parse("a == null ? b : c"); 141 mExprModel.comparison("==", a, mExprModel.symbol("null", Object.class)); 142 lb.getModel().seal(); 143 Iterable<Expr> shouldRead = getShouldRead(); 144 // a and a == null 145 assertEquals(2, Iterables.size(shouldRead)); 146 final Iterable<Expr> readFirst = getReadFirst(shouldRead, null); 147 assertEquals(1, Iterables.size(readFirst)); 148 final Expr first = Iterables.getFirst(readFirst, null); 149 assertSame(a, first); 150 // now , assume we've read this 151 final BitSet shouldReadFlags = first.getShouldReadFlags(); 152 assertNotNull(shouldReadFlags); 153 } 154 155 @Test 156 public void testTernaryWithPlus() { 157 LayoutBinder lb = new MockLayoutBinder(); 158 mExprModel = lb.getModel(); 159 IdentifierExpr user = lb 160 .addVariable("user", "android.databinding.tool.expr.ExprModelTest.User"); 161 MathExpr parsed = parse(lb, "user.name + \" \" + (user.lastName ?? \"\")", MathExpr.class); 162 mExprModel.seal(); 163 Iterable<Expr> toRead = getShouldRead(); 164 Iterable<Expr> readNow = getReadFirst(toRead); 165 assertEquals(1, Iterables.size(readNow)); 166 assertSame(user, Iterables.getFirst(readNow, null)); 167 List<Expr> justRead = new ArrayList<Expr>(); 168 justRead.add(user); 169 readNow = filterOut(getReadFirst(toRead, justRead), justRead); 170 assertEquals(2, Iterables.size(readNow)); //user.name && user.lastName 171 Iterables.addAll(justRead, readNow); 172 // user.lastname (T, F), user.name + " " 173 readNow = filterOut(getReadFirst(toRead, justRead), justRead); 174 assertEquals(2, Iterables.size(readNow)); //user.name && user.lastName 175 Iterables.addAll(justRead, readNow); 176 readNow = filterOut(getReadFirst(toRead, justRead), justRead); 177 assertEquals(0, Iterables.size(readNow)); 178 mExprModel.markBitsRead(); 179 180 toRead = getShouldRead(); 181 assertEquals(2, Iterables.size(toRead)); 182 justRead.clear(); 183 readNow = filterOut(getReadFirst(toRead, justRead), justRead); 184 assertEquals(1, Iterables.size(readNow)); 185 assertSame(parsed.getRight(), Iterables.getFirst(readNow, null)); 186 Iterables.addAll(justRead, readNow); 187 188 readNow = filterOut(getReadFirst(toRead, justRead), justRead); 189 assertEquals(1, Iterables.size(readNow)); 190 assertSame(parsed, Iterables.getFirst(readNow, null)); 191 Iterables.addAll(justRead, readNow); 192 193 readNow = filterOut(getReadFirst(toRead, justRead), justRead); 194 assertEquals(0, Iterables.size(readNow)); 195 mExprModel.markBitsRead(); 196 assertEquals(0, Iterables.size(getShouldRead())); 197 } 198 199 private List<Expr> filterOut(Iterable itr, final Iterable exclude) { 200 return Arrays.asList(Iterables.toArray(Iterables.filter(itr, new Predicate() { 201 @Override 202 public boolean apply(Object input) { 203 return !Iterables.contains(exclude, input); 204 } 205 }), Expr.class)); 206 } 207 208 @Test 209 public void testTernaryInsideTernary() { 210 LayoutBinder lb = new MockLayoutBinder(); 211 mExprModel = lb.getModel(); 212 IdentifierExpr cond1 = lb.addVariable("cond1", "boolean"); 213 IdentifierExpr cond2 = lb.addVariable("cond2", "boolean"); 214 215 IdentifierExpr a = lb.addVariable("a", "boolean"); 216 IdentifierExpr b = lb.addVariable("b", "boolean"); 217 IdentifierExpr c = lb.addVariable("c", "boolean"); 218 219 final TernaryExpr ternaryExpr = parse(lb, "cond1 ? cond2 ? a : b : c", TernaryExpr.class); 220 final TernaryExpr innerTernary = (TernaryExpr) ternaryExpr.getIfTrue(); 221 mExprModel.seal(); 222 223 Iterable<Expr> toRead = getShouldRead(); 224 assertEquals(1, Iterables.size(toRead)); 225 assertEquals(ternaryExpr.getPred(), Iterables.getFirst(toRead, null)); 226 227 Iterable<Expr> readNow = getReadFirst(toRead); 228 assertEquals(1, Iterables.size(readNow)); 229 assertEquals(ternaryExpr.getPred(), Iterables.getFirst(readNow, null)); 230 int cond1True = ternaryExpr.getRequirementFlagIndex(true); 231 int cond1False = ternaryExpr.getRequirementFlagIndex(false); 232 // ok, it is read now. 233 mExprModel.markBitsRead(); 234 235 // now it should read cond2 or c, depending on the flag from first 236 toRead = getShouldRead(); 237 assertEquals(2, Iterables.size(toRead)); 238 assertExactMatch(toRead, ternaryExpr.getIfFalse(), innerTernary.getPred()); 239 assertFlags(ternaryExpr.getIfFalse(), cond1False); 240 assertFlags(ternaryExpr.getIfTrue(), cond1True); 241 242 mExprModel.markBitsRead(); 243 244 // now it should read a or b, innerTernary, outerTernary 245 toRead = getShouldRead(); 246 assertExactMatch(toRead, innerTernary.getIfTrue(), innerTernary.getIfFalse(), ternaryExpr, 247 innerTernary); 248 assertFlags(innerTernary.getIfTrue(), innerTernary.getRequirementFlagIndex(true)); 249 assertFlags(innerTernary.getIfFalse(), innerTernary.getRequirementFlagIndex(false)); 250 assertFalse(mExprModel.markBitsRead()); 251 } 252 253 @Test 254 public void testRequirementFlags() { 255 LayoutBinder lb = new MockLayoutBinder(); 256 mExprModel = lb.getModel(); 257 IdentifierExpr a = lb.addVariable("a", "java.lang.String"); 258 IdentifierExpr b = lb.addVariable("b", "java.lang.String"); 259 IdentifierExpr c = lb.addVariable("c", "java.lang.String"); 260 IdentifierExpr d = lb.addVariable("d", "java.lang.String"); 261 IdentifierExpr e = lb.addVariable("e", "java.lang.String"); 262 final Expr aTernary = lb.parse("a == null ? b == null ? c : d : e"); 263 assertTrue(aTernary instanceof TernaryExpr); 264 final Expr bTernary = ((TernaryExpr) aTernary).getIfTrue(); 265 assertTrue(bTernary instanceof TernaryExpr); 266 final Expr aIsNull = mExprModel 267 .comparison("==", a, mExprModel.symbol("null", Object.class)); 268 final Expr bIsNull = mExprModel 269 .comparison("==", b, mExprModel.symbol("null", Object.class)); 270 lb.getModel().seal(); 271 Iterable<Expr> shouldRead = getShouldRead(); 272 // a and a == null 273 assertEquals(2, Iterables.size(shouldRead)); 274 assertFalse(a.getShouldReadFlags().isEmpty()); 275 assertTrue(a.getShouldReadFlags().get(a.getId())); 276 assertTrue(b.getShouldReadFlags().isEmpty()); 277 assertTrue(c.getShouldReadFlags().isEmpty()); 278 assertTrue(d.getShouldReadFlags().isEmpty()); 279 assertTrue(e.getShouldReadFlags().isEmpty()); 280 281 Iterable<Expr> readFirst = getReadFirst(shouldRead, null); 282 assertEquals(1, Iterables.size(readFirst)); 283 final Expr first = Iterables.getFirst(readFirst, null); 284 assertSame(a, first); 285 assertTrue(mExprModel.markBitsRead()); 286 for (Expr expr : mExprModel.getPendingExpressions()) { 287 assertNull(expr.mShouldReadFlags); 288 } 289 shouldRead = getShouldRead(); 290 assertExactMatch(shouldRead, e, b, bIsNull); 291 292 assertFlags(e, aTernary.getRequirementFlagIndex(false)); 293 294 assertFlags(b, aTernary.getRequirementFlagIndex(true)); 295 assertFlags(bIsNull, aTernary.getRequirementFlagIndex(true)); 296 assertTrue(mExprModel.markBitsRead()); 297 shouldRead = getShouldRead(); 298 assertEquals(4, Iterables.size(shouldRead)); 299 assertTrue(Iterables.contains(shouldRead, c)); 300 assertTrue(Iterables.contains(shouldRead, d)); 301 assertTrue(Iterables.contains(shouldRead, aTernary)); 302 assertTrue(Iterables.contains(shouldRead, bTernary)); 303 304 assertTrue(c.getShouldReadFlags().get(bTernary.getRequirementFlagIndex(true))); 305 assertEquals(1, c.getShouldReadFlags().cardinality()); 306 307 assertTrue(d.getShouldReadFlags().get(bTernary.getRequirementFlagIndex(false))); 308 assertEquals(1, d.getShouldReadFlags().cardinality()); 309 310 assertTrue(bTernary.getShouldReadFlags().get(aTernary.getRequirementFlagIndex(true))); 311 assertEquals(1, bTernary.getShouldReadFlags().cardinality()); 312 313 assertEquals(5, aTernary.getShouldReadFlags().cardinality()); 314 for (Expr expr : new Expr[]{a, b, c, d, e}) { 315 assertTrue(aTernary.getShouldReadFlags().get(expr.getId())); 316 } 317 318 readFirst = getReadFirst(shouldRead); 319 assertEquals(2, Iterables.size(readFirst)); 320 assertTrue(Iterables.contains(readFirst, c)); 321 assertTrue(Iterables.contains(readFirst, d)); 322 assertFalse(mExprModel.markBitsRead()); 323 } 324 325 @Test 326 public void testPostConditionalDependencies() { 327 LayoutBinder lb = new MockLayoutBinder(); 328 mExprModel = lb.getModel(); 329 330 IdentifierExpr u1 = lb.addVariable("u1", User.class.getCanonicalName()); 331 IdentifierExpr u2 = lb.addVariable("u2", User.class.getCanonicalName()); 332 IdentifierExpr a = lb.addVariable("a", int.class.getCanonicalName()); 333 IdentifierExpr b = lb.addVariable("b", int.class.getCanonicalName()); 334 IdentifierExpr c = lb.addVariable("c", int.class.getCanonicalName()); 335 IdentifierExpr d = lb.addVariable("d", int.class.getCanonicalName()); 336 IdentifierExpr e = lb.addVariable("e", int.class.getCanonicalName()); 337 TernaryExpr abTernary = parse(lb, "a > b ? u1.name : u2.name", TernaryExpr.class); 338 TernaryExpr bcTernary = parse(lb, "b > c ? u1.getCond(d) ? u1.lastName : u2.lastName : `xx`" 339 + " + u2.getCond(e) ", TernaryExpr.class); 340 Expr abCmp = abTernary.getPred(); 341 Expr bcCmp = bcTernary.getPred(); 342 Expr u1GetCondD = ((TernaryExpr) bcTernary.getIfTrue()).getPred(); 343 final MathExpr xxPlusU2getCondE = (MathExpr) bcTernary.getIfFalse(); 344 Expr u2GetCondE = xxPlusU2getCondE.getRight(); 345 Expr u1Name = abTernary.getIfTrue(); 346 Expr u2Name = abTernary.getIfFalse(); 347 Expr u1LastName = ((TernaryExpr) bcTernary.getIfTrue()).getIfTrue(); 348 Expr u2LastName = ((TernaryExpr) bcTernary.getIfTrue()).getIfFalse(); 349 350 mExprModel.seal(); 351 Iterable<Expr> shouldRead = getShouldRead(); 352 353 assertExactMatch(shouldRead, a, b, c, abCmp, bcCmp); 354 355 Iterable<Expr> firstRead = getReadFirst(shouldRead); 356 357 assertExactMatch(firstRead, a, b, c); 358 359 assertFlags(a, a, b, u1, u2, u1Name, u2Name); 360 assertFlags(b, a, b, u1, u2, u1Name, u2Name, c, d, u1LastName, u2LastName, e); 361 assertFlags(c, b, c, u1, d, u1LastName, u2LastName, e); 362 assertFlags(abCmp, a, b, u1, u2, u1Name, u2Name); 363 assertFlags(bcCmp, b, c, u1, d, u1LastName, u2LastName, e); 364 365 assertTrue(mExprModel.markBitsRead()); 366 367 shouldRead = getShouldRead(); 368 Expr[] batch = {d, e, u1, u2, u1GetCondD, u2GetCondE, xxPlusU2getCondE, abTernary, 369 abTernary.getIfTrue(), abTernary.getIfFalse()}; 370 assertExactMatch(shouldRead, batch); 371 firstRead = getReadFirst(shouldRead); 372 assertExactMatch(firstRead, d, e, u1, u2); 373 374 assertFlags(d, bcTernary.getRequirementFlagIndex(true)); 375 assertFlags(e, bcTernary.getRequirementFlagIndex(false)); 376 assertFlags(u1, bcTernary.getRequirementFlagIndex(true), 377 abTernary.getRequirementFlagIndex(true)); 378 assertFlags(u2, bcTernary.getRequirementFlagIndex(false), 379 abTernary.getRequirementFlagIndex(false)); 380 381 assertFlags(u1GetCondD, bcTernary.getRequirementFlagIndex(true)); 382 assertFlags(u2GetCondE, bcTernary.getRequirementFlagIndex(false)); 383 assertFlags(xxPlusU2getCondE, bcTernary.getRequirementFlagIndex(false)); 384 assertFlags(abTernary, a, b, u1, u2, u1Name, u2Name); 385 assertFlags(abTernary.getIfTrue(), abTernary.getRequirementFlagIndex(true)); 386 assertFlags(abTernary.getIfFalse(), abTernary.getRequirementFlagIndex(false)); 387 388 assertTrue(mExprModel.markBitsRead()); 389 390 shouldRead = getShouldRead(); 391 // actually, there is no real case to read u1 anymore because if b>c was not true, 392 // u1.getCond(d) will never be set. Right now, we don't have mechanism to figure this out 393 // and also it does not affect correctness (just an unnecessary if stmt) 394 assertExactMatch(shouldRead, u2, u1LastName, u2LastName, bcTernary.getIfTrue(), bcTernary); 395 firstRead = getReadFirst(shouldRead); 396 assertExactMatch(firstRead, u1LastName, u2); 397 398 assertFlags(u1LastName, bcTernary.getIfTrue().getRequirementFlagIndex(true)); 399 assertFlags(u2LastName, bcTernary.getIfTrue().getRequirementFlagIndex(false)); 400 assertFlags(u2, bcTernary.getIfTrue().getRequirementFlagIndex(false)); 401 402 assertFlags(bcTernary.getIfTrue(), bcTernary.getRequirementFlagIndex(true)); 403 assertFlags(bcTernary, b, c, u1, u2, d, u1LastName, u2LastName, e); 404 } 405 406 @Test 407 public void testCircularDependency() { 408 LayoutBinder lb = new MockLayoutBinder(); 409 mExprModel = lb.getModel(); 410 IdentifierExpr a = lb.addVariable("a", int.class.getCanonicalName()); 411 IdentifierExpr b = lb.addVariable("b", int.class.getCanonicalName()); 412 final TernaryExpr abTernary = parse(lb, "a > 3 ? a : b", TernaryExpr.class); 413 mExprModel.seal(); 414 Iterable<Expr> shouldRead = getShouldRead(); 415 assertExactMatch(shouldRead, a, abTernary.getPred()); 416 assertTrue(mExprModel.markBitsRead()); 417 shouldRead = getShouldRead(); 418 assertExactMatch(shouldRead, b, abTernary); 419 assertFalse(mExprModel.markBitsRead()); 420 } 421 422 @Test 423 public void testNestedCircularDependency() { 424 LayoutBinder lb = new MockLayoutBinder(); 425 mExprModel = lb.getModel(); 426 IdentifierExpr a = lb.addVariable("a", int.class.getCanonicalName()); 427 IdentifierExpr b = lb.addVariable("b", int.class.getCanonicalName()); 428 IdentifierExpr c = lb.addVariable("c", int.class.getCanonicalName()); 429 final TernaryExpr a3Ternary = parse(lb, "a > 3 ? c > 4 ? a : b : c", TernaryExpr.class); 430 final TernaryExpr c4Ternary = (TernaryExpr) a3Ternary.getIfTrue(); 431 mExprModel.seal(); 432 Iterable<Expr> shouldRead = getShouldRead(); 433 assertExactMatch(shouldRead, a, a3Ternary.getPred()); 434 assertTrue(mExprModel.markBitsRead()); 435 shouldRead = getShouldRead(); 436 assertExactMatch(shouldRead, c, c4Ternary.getPred()); 437 assertFlags(c, a3Ternary.getRequirementFlagIndex(true), 438 a3Ternary.getRequirementFlagIndex(false)); 439 assertFlags(c4Ternary.getPred(), a3Ternary.getRequirementFlagIndex(true)); 440 } 441 442 @Test 443 public void testNoFlagsForNonBindingStatic() { 444 LayoutBinder lb = new MockLayoutBinder(); 445 mExprModel = lb.getModel(); 446 lb.addVariable("a", int.class.getCanonicalName()); 447 final MathExpr parsed = parse(lb, "a * (3 + 2)", MathExpr.class); 448 mExprModel.seal(); 449 assertTrue(parsed.getRight().getInvalidFlags().isEmpty()); 450 assertEquals(1, parsed.getLeft().getInvalidFlags().cardinality()); 451 assertEquals(1, mExprModel.getInvalidateableFieldLimit()); 452 } 453 454 @Test 455 public void testFlagsForBindingStatic() { 456 LayoutBinder lb = new MockLayoutBinder(); 457 mExprModel = lb.getModel(); 458 lb.addVariable("a", int.class.getCanonicalName()); 459 final Expr staticParsed = parse(lb, "3 + 2", MathExpr.class); 460 final MathExpr parsed = parse(lb, "a * (3 + 2)", MathExpr.class); 461 mExprModel.seal(); 462 assertTrue(staticParsed.isBindingExpression()); 463 assertEquals(1, staticParsed.getInvalidFlags().cardinality()); 464 assertEquals(parsed.getRight().getInvalidFlags(), staticParsed.getInvalidFlags()); 465 assertEquals(1, parsed.getLeft().getInvalidFlags().cardinality()); 466 assertEquals(2, mExprModel.getInvalidateableFieldLimit()); 467 } 468 469 private void assertFlags(Expr a, int... flags) { 470 BitSet bitset = new BitSet(); 471 for (int flag : flags) { 472 bitset.set(flag); 473 } 474 assertEquals("flag test for " + a.getUniqueKey(), bitset, a.getShouldReadFlags()); 475 } 476 477 private void assertFlags(Expr a, Expr... exprs) { 478 BitSet bitSet = a.getShouldReadFlags(); 479 for (Expr expr : exprs) { 480 BitSet clone = (BitSet) bitSet.clone(); 481 clone.and(expr.getInvalidFlags()); 482 assertEquals("should read flags of " + a.getUniqueKey() + " should include " + expr 483 .getUniqueKey(), expr.getInvalidFlags(), clone); 484 } 485 486 BitSet composite = new BitSet(); 487 for (Expr expr : exprs) { 488 composite.or(expr.getInvalidFlags()); 489 } 490 assertEquals("composite flags should match", composite, bitSet); 491 } 492 493 private void assertExactMatch(Iterable<Expr> iterable, Expr... exprs) { 494 int i = 0; 495 log("list", iterable); 496 for (Expr expr : exprs) { 497 assertTrue((i++) + ":must contain " + expr.getUniqueKey(), 498 Iterables.contains(iterable, expr)); 499 } 500 i = 0; 501 for (Expr expr : iterable) { 502 assertTrue((i++) + ":must be expected " + expr.getUniqueKey(), 503 ArrayUtils.contains(exprs, expr)); 504 } 505 } 506 507 private <T extends Expr> T parse(LayoutBinder binder, String input, Class<T> klass) { 508 final Expr parsed = binder.parse(input); 509 assertTrue(klass.isAssignableFrom(parsed.getClass())); 510 return (T) parsed; 511 } 512 513 private void log(String s, Iterable<Expr> iterable) { 514 L.d(s); 515 for (Expr e : iterable) { 516 L.d(": %s : %s allFlags: %s readSoFar: %s", e.getUniqueKey(), e.getShouldReadFlags(), 517 e.getShouldReadFlagsWithConditionals(), e.getReadSoFar()); 518 } 519 L.d("end of %s", s); 520 } 521 522 private Iterable<Expr> getReadFirst(Iterable<Expr> shouldRead) { 523 return getReadFirst(shouldRead, null); 524 } 525 526 private Iterable<Expr> getReadFirst(Iterable<Expr> shouldRead, final Iterable<Expr> justRead) { 527 return Iterables.filter(shouldRead, new Predicate<Expr>() { 528 @Override 529 public boolean apply(Expr input) { 530 return input.shouldReadNow(justRead); 531 } 532 }); 533 } 534 535 private Iterable<Expr> getShouldRead() { 536 return mExprModel.filterShouldRead(mExprModel.getPendingExpressions()); 537 } 538 539 public static class User { 540 541 String name; 542 543 String lastName; 544 545 public String getName() { 546 return name; 547 } 548 549 public String getLastName() { 550 return lastName; 551 } 552 553 public boolean getCond(int i) { 554 return true; 555 } 556 } 557} 558