OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.debug.ui; | 5 package org.chromium.debug.ui; |
6 | 6 |
| 7 import java.lang.annotation.ElementType; |
| 8 import java.lang.annotation.Retention; |
| 9 import java.lang.annotation.RetentionPolicy; |
| 10 import java.lang.annotation.Target; |
| 11 import java.lang.reflect.InvocationTargetException; |
| 12 import java.lang.reflect.Method; |
| 13 import java.lang.reflect.ParameterizedType; |
| 14 import java.lang.reflect.Type; |
| 15 import java.lang.reflect.WildcardType; |
7 import java.util.ArrayList; | 16 import java.util.ArrayList; |
8 import java.util.Arrays; | 17 import java.util.Arrays; |
9 import java.util.Collection; | 18 import java.util.Collection; |
10 import java.util.Collections; | 19 import java.util.Collections; |
11 import java.util.Comparator; | 20 import java.util.Comparator; |
12 import java.util.HashMap; | 21 import java.util.HashMap; |
13 import java.util.HashSet; | 22 import java.util.HashSet; |
14 import java.util.LinkedHashMap; | 23 import java.util.LinkedHashMap; |
15 import java.util.LinkedHashSet; | 24 import java.util.LinkedHashSet; |
16 import java.util.List; | 25 import java.util.List; |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 * <p>Scope roughly corresponds to a group of UI controls that may become disa
bled, | 312 * <p>Scope roughly corresponds to a group of UI controls that may become disa
bled, |
304 * and thus may not generate any data and need no inner updates. | 313 * and thus may not generate any data and need no inner updates. |
305 */ | 314 */ |
306 public interface Scope { | 315 public interface Scope { |
307 Scope getOuterScope(); | 316 Scope getOuterScope(); |
308 | 317 |
309 /** | 318 /** |
310 * Creates a switcher that is operated by optional expression. | 319 * Creates a switcher that is operated by optional expression. |
311 * @param <T> type of expression | 320 * @param <T> type of expression |
312 */ | 321 */ |
313 <T> OptionalSwitcher<T> addOptionalSwitch(Gettable<? extends Optional<T>> ex
pression); | 322 <T> OptionalSwitcher<T> addOptionalSwitch(Gettable<? extends Optional<? exte
nds T>> expression); |
314 | 323 |
315 /** | 324 /** |
316 * Creates a switcher that is operated by non-optional expression. | 325 * Creates a switcher that is operated by non-optional expression. |
317 * @param <T> type of expression | 326 * @param <T> type of expression |
318 */ | 327 */ |
319 <T> Switcher<T> addSwitch(Gettable<T> expression); | 328 <T> Switcher<T> addSwitch(Gettable<T> expression); |
320 } | 329 } |
321 | 330 |
322 /** | 331 /** |
323 * A callback that lets UI to reflect that some scope became enabled/disabled. | 332 * A callback that lets UI to reflect that some scope became enabled/disabled. |
(...skipping 27 matching lines...) Expand all Loading... |
351 | 360 |
352 /** | 361 /** |
353 * A switcher that is operated by optional expression. | 362 * A switcher that is operated by optional expression. |
354 */ | 363 */ |
355 public interface OptionalSwitcher<T> extends SwitchBase<T> { | 364 public interface OptionalSwitcher<T> extends SwitchBase<T> { |
356 /** | 365 /** |
357 * See javadoc for {@link Switcher#createMerge}; the difference of this meth
od is that | 366 * See javadoc for {@link Switcher#createMerge}; the difference of this meth
od is that |
358 * all sources have optional type and the merge source itself of optional ty
pe. The switcher | 367 * all sources have optional type and the merge source itself of optional ty
pe. The switcher |
359 * expression may have error value, in this case the merger also returns thi
s error value. | 368 * expression may have error value, in this case the merger also returns thi
s error value. |
360 */ | 369 */ |
361 <P> ValueSource<? extends Optional<P>> createOptionalMerge( | 370 <P> ValueSource<? extends Optional<? extends P>> createOptionalMerge( |
362 ValueSource<? extends Optional<P>> ... sources); | 371 ValueSource<? extends Optional<? extends P>> ... sources); |
363 } | 372 } |
364 | 373 |
365 public static <T> ValueSource<T> createConstant(final T constnant, Updater upd
ater) { | 374 public static <T> ValueSource<T> createConstant(final T constnant, Updater upd
ater) { |
366 ValueSource<T> source = new ValueSource<T>() { | 375 ValueSource<T> source = new ValueSource<T>() { |
367 public T getValue() { | 376 public T getValue() { |
368 return constnant; | 377 return constnant; |
369 } | 378 } |
370 }; | 379 }; |
371 updater.addSource(updater.rootScope(), source); | 380 updater.addSource(updater.rootScope(), source); |
372 return source; | 381 return source; |
(...skipping 23 matching lines...) Expand all Loading... |
396 return new Optional<V>() { | 405 return new Optional<V>() { |
397 public Set<Message> errorMessages() { | 406 public Set<Message> errorMessages() { |
398 return Collections.emptySet(); | 407 return Collections.emptySet(); |
399 } | 408 } |
400 public V getNormal() { | 409 public V getNormal() { |
401 return value; | 410 return value; |
402 } | 411 } |
403 public boolean isNormal() { | 412 public boolean isNormal() { |
404 return true; | 413 return true; |
405 } | 414 } |
| 415 @Override |
| 416 public boolean equals(Object obj) { |
| 417 if (obj == null) { |
| 418 return false; |
| 419 } |
| 420 if (obj == this) { |
| 421 return true; |
| 422 } |
| 423 if (!obj.getClass().equals(this.getClass())) { |
| 424 return false; |
| 425 } |
| 426 Optional<?> other = (Optional<?>) obj; |
| 427 if (value == null) { |
| 428 return other.getNormal() == null; |
| 429 } else { |
| 430 return value.equals(other.getNormal()); |
| 431 } |
| 432 } |
| 433 @Override |
| 434 public int hashCode() { |
| 435 return value == null ? 0 : value.hashCode(); |
| 436 } |
406 }; | 437 }; |
407 } | 438 } |
408 | 439 |
409 public static <V> Optional<V> createErrorOptional(Message message) { | 440 public static <V> Optional<V> createErrorOptional(Message message) { |
410 return createErrorOptional(Collections.singleton(message)); | 441 return createErrorOptional(Collections.singleton(message)); |
411 } | 442 } |
412 | 443 |
413 public static <V> Optional<V> createErrorOptional(final Set<? extends Message>
messages) { | 444 public static <V> Optional<V> createErrorOptional(final Set<? extends Message>
messages) { |
414 return new Optional<V>() { | 445 return new Optional<V>() { |
415 public Set<? extends Message> errorMessages() { | 446 public Set<? extends Message> errorMessages() { |
416 return messages; | 447 return messages; |
417 } | 448 } |
418 public V getNormal() { | 449 public V getNormal() { |
419 throw new UnsupportedOperationException(); | 450 throw new UnsupportedOperationException(); |
420 } | 451 } |
421 public boolean isNormal() { | 452 public boolean isNormal() { |
422 return false; | 453 return false; |
423 } | 454 } |
| 455 @Override |
| 456 public boolean equals(Object obj) { |
| 457 if (obj == null) { |
| 458 return false; |
| 459 } |
| 460 if (obj == this) { |
| 461 return true; |
| 462 } |
| 463 if (!obj.getClass().equals(this.getClass())) { |
| 464 return false; |
| 465 } |
| 466 Optional<?> other = (Optional<?>) obj; |
| 467 if (messages == null) { |
| 468 return other.errorMessages() == null; |
| 469 } else { |
| 470 return messages.equals(other.errorMessages()); |
| 471 } |
| 472 } |
| 473 @Override |
| 474 public int hashCode() { |
| 475 return messages.hashCode(); |
| 476 } |
424 }; | 477 }; |
425 } | 478 } |
426 | 479 |
427 /** | 480 /** |
428 * A user interface message for dialog window. It has text and priority that h
elps choosing | 481 * A user interface message for dialog window. It has text and priority that h
elps choosing |
429 * the most important message it there are many of them. | 482 * the most important message it there are many of them. |
430 */ | 483 */ |
431 public static class Message { | 484 public static class Message { |
432 private final String text; | 485 private final String text; |
433 private final MessagePriority priority; | 486 private final MessagePriority priority; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 Optional<T> result = calculateNewValue(); | 548 Optional<T> result = calculateNewValue(); |
496 Optional<T> oldValue = getValue(); | 549 Optional<T> oldValue = getValue(); |
497 setCurrentValue(result); | 550 setCurrentValue(result); |
498 if (!result.equals(oldValue)) { | 551 if (!result.equals(oldValue)) { |
499 updater.reportChanged(this); | 552 updater.reportChanged(this); |
500 } | 553 } |
501 } | 554 } |
502 } | 555 } |
503 | 556 |
504 /** | 557 /** |
505 * An interface similar to {@link Gettable}, but with a quite specific contrac
t: | 558 * An expression that gets calculated only when its dependencies are all non-e
rror. |
506 * it may depend on some optional values, but its calculate method should only
be called | 559 * The interface contains a "calculate" method and several methods that return
expression |
507 * when all of the values are normal (non-error). This way its implementations
becomes simpler. | 560 * dependencies. |
508 * It's up to someone who calls calculate method to check that contract is hel
d. | 561 * <p> |
| 562 * The one that is using this expression is responsible for reading all source
s, checking |
| 563 * whether the optional values are normal and calling "calculate" method passi
ng the |
| 564 * normal values as arguments. |
| 565 * <p> |
| 566 * The interface is reflection-oriented, as you cannot express type schema in
plain Java. |
| 567 * The client should check the interface for a type-consistency statically on
runtime and |
| 568 * throw exception if something is wrong. All user types are explicitly declar
ed in |
| 569 * signature of methods. This allows accurate type checking via reflection (in
cluding |
| 570 * generics parameters, which are otherwise erased on runtime). |
| 571 * <p> |
| 572 * The interface is reflection-based. It only contains annotation that method
should have. |
| 573 * |
| 574 * @param <T> type of value this expression returns |
509 */ | 575 */ |
510 public interface NormalExpression<RES> { | 576 public interface NormalExpression<T> { |
511 RES calculate(); | 577 /** |
| 578 * An annotation for a "calculate" method of the interface. There should be
only one such |
| 579 * a method in the object. Its return type should be "T" or "Optional<? exte
nds T>" (we are |
| 580 * flexible in this only place). It should have arguments one per its depend
ency |
| 581 * (in the same order). |
| 582 * <p>The method must be declared public for the reflection to work. |
| 583 */ |
| 584 @Retention(RetentionPolicy.RUNTIME) |
| 585 @Target(ElementType.METHOD) |
| 586 @interface Calculate { |
| 587 } |
| 588 |
| 589 /** |
| 590 * An annotation for a method that returns expression dependency. It should
have no arguments |
| 591 * and return IValueSource<? extends Optional<*T*>> type ("IValueSource" is
significant here). |
| 592 * The type *T* should correspond to the type of "calculate" method argument
(dependency |
| 593 * methods should go in the same order as "calculate" arguments go). |
| 594 * <p>The method must be declared public for the reflection to work. |
| 595 */ |
| 596 @Target(ElementType.METHOD) |
| 597 @Retention(RetentionPolicy.RUNTIME) |
| 598 @interface DependencyGetter { |
| 599 } |
512 } | 600 } |
513 | 601 |
| 602 |
514 /** | 603 /** |
515 * Creates a {@link ValueProcessor} that is backed by {@link NormalExpression}
. | 604 * Converts {@link NormalExpression} into {@link Gettable} and takes responsib
ility of checking |
516 * @param optionalSources list of inputs that are optional and thus have to be
checked for | 605 * that all dependencies have only normal values. Despite {@link NormalExpress
ion} being |
517 * {@link NormalExpression} contract. | 606 * reflection-based interface, this method should be completely type-safe for
a programmer and |
| 607 * accurately check (statically) that its signatures are consistent (including
generic types). |
518 */ | 608 */ |
519 public static <T> ValueProcessor<Optional<T>> createOptionalProcessor( | 609 public static <RES> Gettable<Optional<? extends RES>> handleErrors( |
520 final NormalExpression<T> expression, | 610 final NormalExpression<RES> expression) { |
521 ValueSource<? extends Optional<?>> ... optionalSources) { | 611 Class<?> expressionClass = expression.getClass(); |
522 final Gettable<Optional<T>> getter = handleErrors(expression, optionalSource
s); | 612 |
523 return createProcessor(getter); | 613 // All reflection is done in generic-aware API generation. |
524 } | 614 |
525 | 615 // Read generic NormalExpression type parameter of expression class. |
526 /** | 616 Type expressionType; |
527 * Implements the basic contract of {@link NormalExpression}. Wraps it as {@li
nk Gettable} and | 617 { |
528 * keeps all its optional sources that are checked before each calculation. | 618 ParameterizedType normalExpressionType = null; |
529 */ | 619 for (Type inter : expressionClass.getGenericInterfaces()) { |
530 public static <RES> Gettable<Optional<RES>> handleErrors(final NormalExpressio
n<RES> expression, | 620 if (inter instanceof ParameterizedType == false) { |
531 final ValueSource<? extends Optional<?>> ... optionalSources) { | 621 continue; |
532 NormalExpression<Optional<RES>> wrapper = new NormalExpression<Optional<RES>
>() { | 622 } |
533 public Optional<RES> calculate() { | 623 ParameterizedType parameterizedType = (ParameterizedType) inter; |
534 return createOptional(expression.calculate()); | 624 if (!parameterizedType.getRawType().equals(NormalExpression.class)) { |
| 625 continue; |
| 626 } |
| 627 normalExpressionType = parameterizedType; |
| 628 } |
| 629 if (normalExpressionType == null) { |
| 630 throw new IllegalArgumentException("Expression does not directly impleme
nt " + |
| 631 NormalExpression.class.getName()); |
| 632 } |
| 633 expressionType = normalExpressionType.getActualTypeArguments()[0]; |
| 634 } |
| 635 |
| 636 // Read all methods of expression class and choose annotated ones. |
| 637 Method calculateMethodVar = null; |
| 638 final List<Method> dependencyMethods = new ArrayList<Method>(2); |
| 639 for (Method m : expressionClass.getMethods()) { |
| 640 if (m.getAnnotation(NormalExpression.Calculate.class) != null) { |
| 641 if (calculateMethodVar != null) { |
| 642 throw new IllegalArgumentException("Class " + expressionClass.getName(
) + |
| 643 " has more than one method with " + |
| 644 NormalExpression.Calculate.class.getName() + " annotation"); |
| 645 } |
| 646 calculateMethodVar = m; |
| 647 } |
| 648 if (m.getAnnotation(NormalExpression.DependencyGetter.class) != null) { |
| 649 dependencyMethods.add(m); |
| 650 } |
| 651 } |
| 652 if (calculateMethodVar == null) { |
| 653 throw new IllegalArgumentException("Failed to found Class method with " + |
| 654 NormalExpression.Calculate.class.getName() + " annotation in " + |
| 655 expressionClass.getName()); |
| 656 } |
| 657 final Method calculateMethod = calculateMethodVar; |
| 658 Type methodReturnType = calculateMethod.getGenericReturnType(); |
| 659 |
| 660 // Method is typically in anonymous class. Making it accessible is required. |
| 661 calculateMethod.setAccessible(true); |
| 662 |
| 663 // Prepare handling method return value (it's either a plain value or an opt
ional wrapper). |
| 664 abstract class ReturnValueHandler { |
| 665 abstract Optional<? extends RES> castResult(Object resultObject); |
| 666 } |
| 667 |
| 668 final ReturnValueHandler returnValueHandler; |
| 669 |
| 670 if (methodReturnType.equals(expressionType)) { |
| 671 returnValueHandler = new ReturnValueHandler() { |
| 672 Optional<? extends RES> castResult(Object resultObject) { |
| 673 // Return type in interface is RES. |
| 674 // Type cast has been proven to be correct. |
| 675 return createOptional((RES) resultObject); |
| 676 } |
| 677 }; |
| 678 } else { |
| 679 tryUnwrapOptional: { |
| 680 if (methodReturnType instanceof ParameterizedType) { |
| 681 ParameterizedType parameterizedType = (ParameterizedType) methodReturn
Type; |
| 682 if (parameterizedType.getRawType() == Optional.class) { |
| 683 Type optionalParam = parameterizedType.getActualTypeArguments()[0]; |
| 684 boolean okToCast = false; |
| 685 if (optionalParam instanceof WildcardType) { |
| 686 WildcardType wildcardType = (WildcardType) optionalParam; |
| 687 if (wildcardType.getUpperBounds()[0].equals(expressionType)) { |
| 688 okToCast = true; |
| 689 } |
| 690 } else if (optionalParam.equals(expressionType)) { |
| 691 okToCast = true; |
| 692 } |
| 693 if (okToCast) { |
| 694 returnValueHandler = new ReturnValueHandler() { |
| 695 Optional<? extends RES> castResult(Object resultObject) { |
| 696 // Return type in interface is optional wrapper around RES. |
| 697 // Type cast has been proven to be correct. |
| 698 return (Optional<? extends RES>) resultObject; |
| 699 } |
| 700 }; |
| 701 break tryUnwrapOptional; |
| 702 } |
| 703 } |
| 704 } |
| 705 throw new IllegalArgumentException("Wrong return type " + methodReturnTy
pe + |
| 706 ", expected: " + expressionType); |
| 707 } |
| 708 } |
| 709 |
| 710 // Check that dependencies correspond to "calculate" method arguments. |
| 711 Type[] methodParamTypes = calculateMethod.getGenericParameterTypes(); |
| 712 if (methodParamTypes.length != dependencyMethods.size()) { |
| 713 throw new IllegalArgumentException("Wrong number of agruments in calculate
method " + |
| 714 calculateMethod); |
| 715 } |
| 716 // We depend on methods being ordered in Java reflection. |
| 717 for (int i = 0; i < methodParamTypes.length; i++) { |
| 718 Method depMethod = dependencyMethods.get(i); |
| 719 try { |
| 720 if (depMethod.getParameterTypes().length != 0) { |
| 721 throw new IllegalArgumentException("Dependency method should not have
arguments"); |
| 722 } |
| 723 Type depType = depMethod.getGenericReturnType(); |
| 724 if (depType instanceof ParameterizedType == false) { |
| 725 throw new IllegalArgumentException("Dependency has wrong return type:
" + depType); |
| 726 } |
| 727 ParameterizedType depParameterizedType = (ParameterizedType) depType; |
| 728 if (depParameterizedType.getRawType() != ValueSource.class) { |
| 729 throw new IllegalArgumentException("Dependency has wrong return type:
" + depType); |
| 730 } |
| 731 // Method is typically in anonymous class. Making it accessible is requi
red. |
| 732 depMethod.setAccessible(true); |
| 733 } catch (IllegalArgumentException e) { |
| 734 throw new IllegalArgumentException("Failed to process method " + depMeth
od, e); |
| 735 } |
| 736 } |
| 737 |
| 738 // Create implementation that will call methods via reflection. |
| 739 return new Gettable<Optional<? extends RES>>() { |
| 740 @Override |
| 741 public Optional<? extends RES> getValue() { |
| 742 Object[] params = new Object[dependencyMethods.size()]; |
| 743 Set<Message> errors = null; |
| 744 for (int i = 0; i < params.length; i++) { |
| 745 Object sourceObject; |
| 746 try { |
| 747 sourceObject = dependencyMethods.get(i).invoke(expression); |
| 748 } catch (IllegalAccessException e) { |
| 749 throw new RuntimeException(e); |
| 750 } catch (InvocationTargetException e) { |
| 751 throw new RuntimeException(e); |
| 752 } |
| 753 ValueSource<? extends Optional<?>> source = |
| 754 (ValueSource<? extends Optional<?>>) sourceObject; |
| 755 Optional<?> optionalValue = source.getValue(); |
| 756 if (optionalValue.isNormal()) { |
| 757 params[i] = optionalValue.getNormal(); |
| 758 } else { |
| 759 if (errors == null) { |
| 760 errors = new LinkedHashSet<Message>(0); |
| 761 } |
| 762 errors.addAll(optionalValue.errorMessages()); |
| 763 } |
| 764 } |
| 765 if (errors == null) { |
| 766 Object result; |
| 767 try { |
| 768 result = calculateMethod.invoke(expression, params); |
| 769 } catch (IllegalAccessException e) { |
| 770 throw new RuntimeException(e); |
| 771 } catch (InvocationTargetException e) { |
| 772 throw new RuntimeException(e); |
| 773 } |
| 774 return returnValueHandler.castResult(result); |
| 775 } else { |
| 776 return createErrorOptional(errors); |
| 777 } |
535 } | 778 } |
536 }; | 779 }; |
537 return handleErrorsAddNew(wrapper, optionalSources); | |
538 } | |
539 | |
540 /** | |
541 * Implements the basic contract of {@link NormalExpression}. Wraps it as {@li
nk Gettable} and | |
542 * keeps all its optional sources that are checked before each calculation. | |
543 * The expression may rely on all optionalSources being of normal values, but
it is allowed to | |
544 * return error value itself. | |
545 */ | |
546 public static <RES> Gettable<Optional<RES>> handleErrorsAddNew( | |
547 final NormalExpression<Optional<RES>> expression, | |
548 final ValueSource<? extends Optional<?>> ... optionalSources) { | |
549 return new Gettable<Optional<RES>>() { | |
550 public Optional<RES> getValue() { | |
551 boolean hasErrors = false; | |
552 for (ValueSource<? extends Optional<?>> source : optionalSources) { | |
553 if (!source.getValue().isNormal()) { | |
554 hasErrors = true; | |
555 break; | |
556 } | |
557 } | |
558 | |
559 if (hasErrors) { | |
560 Set<Message> errors = new LinkedHashSet<Message>(0); | |
561 for (ValueSource<? extends Optional<?>> source : optionalSources) { | |
562 if (!source.getValue().isNormal()) { | |
563 errors.addAll(source.getValue().errorMessages()); | |
564 } | |
565 } | |
566 return createErrorOptional(errors); | |
567 } else { | |
568 return expression.calculate(); | |
569 } | |
570 } | |
571 }; | |
572 } | 780 } |
573 | 781 |
574 public static ValueSource<? extends Optional<?>>[] dependencies( | 782 public static ValueSource<? extends Optional<?>>[] dependencies( |
575 ValueSource<? extends Optional<?>>... sources) { | 783 ValueSource<? extends Optional<?>>... sources) { |
576 return sources; | 784 return sources; |
577 } | 785 } |
578 | 786 |
579 | 787 |
580 /* | 788 /* |
581 * Part 3. Various utils. | 789 * Part 3. Various utils. |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 Optional<? extends T> control = expression.getValue(); | 1072 Optional<? extends T> control = expression.getValue(); |
865 if (control.isNormal()) { | 1073 if (control.isNormal()) { |
866 T tag = control.getNormal(); | 1074 T tag = control.getNormal(); |
867 newScope = getScopeForTag(tag); | 1075 newScope = getScopeForTag(tag); |
868 } else { | 1076 } else { |
869 newScope = null; | 1077 newScope = null; |
870 } | 1078 } |
871 setCurrentScope(newScope); | 1079 setCurrentScope(newScope); |
872 } | 1080 } |
873 | 1081 |
874 public <P> ValueSource<? extends Optional<P>> createOptionalMerge( | 1082 public <P> ValueSource<? extends Optional<? extends P>> createOptionalMerge( |
875 ValueSource<? extends Optional<P>>... sources) { | 1083 ValueSource<? extends Optional<? extends P>>... sources) { |
876 | 1084 |
877 final Map<T, ValueSource<? extends Optional<P>>> map = sortSources(Arrays.
asList(sources)); | 1085 final Map<T, ValueSource<? extends Optional<? extends P>>> map = |
| 1086 sortSources(Arrays.asList(sources)); |
878 | 1087 |
879 ValueProcessor<? extends Optional<P>> result = new ValueProcessor<Optional
<P>>() { | 1088 ValueProcessor<? extends Optional<? extends P>> result = |
| 1089 new ValueProcessor<Optional<? extends P>>() { |
880 public void update(Updater updater) { | 1090 public void update(Updater updater) { |
881 setCurrentValue(calculate()); | 1091 setCurrentValue(calculate()); |
882 updater.reportChanged(this); | 1092 updater.reportChanged(this); |
883 } | 1093 } |
884 | 1094 |
885 private Optional<P> calculate() { | 1095 private Optional<? extends P> calculate() { |
886 Optional<? extends T> control = sourceForMerge.getValue(); | 1096 Optional<? extends T> control = sourceForMerge.getValue(); |
887 if (control.isNormal()) { | 1097 if (control.isNormal()) { |
888 ValueSource<? extends Optional<P>> oneSource = map.get(control.getNo
rmal()); | 1098 ValueSource<? extends Optional<? extends P>> oneSource = map.get(con
trol.getNormal()); |
889 return oneSource.getValue(); | 1099 return oneSource.getValue(); |
890 } else { | 1100 } else { |
891 return createErrorOptional(control.errorMessages()); | 1101 return createErrorOptional(control.errorMessages()); |
892 } | 1102 } |
893 } | 1103 } |
894 }; | 1104 }; |
895 ScopeImpl outerScope = getOuterScope(); | 1105 ScopeImpl outerScope = getOuterScope(); |
896 Updater updater = outerScope.getUpdater(); | 1106 Updater updater = outerScope.getUpdater(); |
897 updater.addConsumer(outerScope, result); | 1107 updater.addConsumer(outerScope, result); |
898 updater.addDependency(result, getSourceForMerge()); | 1108 updater.addDependency(result, getSourceForMerge()); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 Updater getUpdater() { | 1155 Updater getUpdater() { |
946 return updater; | 1156 return updater; |
947 } | 1157 } |
948 | 1158 |
949 ScopeImpl(SwitcherBaseImpl<?> switcher, ScopeEnabler scopeEnabler, Updater u
pdater) { | 1159 ScopeImpl(SwitcherBaseImpl<?> switcher, ScopeEnabler scopeEnabler, Updater u
pdater) { |
950 this.switcher = switcher; | 1160 this.switcher = switcher; |
951 this.scopeEnabler = scopeEnabler; | 1161 this.scopeEnabler = scopeEnabler; |
952 this.updater = updater; | 1162 this.updater = updater; |
953 } | 1163 } |
954 | 1164 |
955 public <P> OptionalSwitcher<P> addOptionalSwitch(Gettable<? extends Optional
<P>> expression) { | 1165 public <P> OptionalSwitcher<P> addOptionalSwitch( |
| 1166 Gettable<? extends Optional<? extends P>> expression) { |
956 OptionalSwitcherImpl<P> switcher = new OptionalSwitcherImpl<P>(this, expre
ssion); | 1167 OptionalSwitcherImpl<P> switcher = new OptionalSwitcherImpl<P>(this, expre
ssion); |
957 updater.addConsumer(this, switcher.getValueConsumer()); | 1168 updater.addConsumer(this, switcher.getValueConsumer()); |
958 updater.addSource(this, switcher.getSourceForMerge()); | 1169 updater.addSource(this, switcher.getSourceForMerge()); |
959 updater.addDependency(switcher.getValueConsumer(), switcher.getSourceForMe
rge()); | 1170 updater.addDependency(switcher.getValueConsumer(), switcher.getSourceForMe
rge()); |
960 return switcher; | 1171 return switcher; |
961 } | 1172 } |
962 | 1173 |
963 public <P> Switcher<P> addSwitch(Gettable<P> expression) { | 1174 public <P> Switcher<P> addSwitch(Gettable<P> expression) { |
964 SwitcherImpl<P> switcher = new SwitcherImpl<P>(this, expression); | 1175 SwitcherImpl<P> switcher = new SwitcherImpl<P>(this, expression); |
965 updater.addConsumer(this, switcher.getValueConsumer()); | 1176 updater.addConsumer(this, switcher.getValueConsumer()); |
966 updater.addSource(this, switcher.getSourceForMerge()); | 1177 updater.addSource(this, switcher.getSourceForMerge()); |
967 updater.addDependency(switcher.getValueConsumer(), switcher.getSourceForMe
rge()); | 1178 updater.addDependency(switcher.getValueConsumer(), switcher.getSourceForMe
rge()); |
968 return switcher; | 1179 return switcher; |
969 } | 1180 } |
970 | 1181 |
971 public Scope getOuterScope() { | 1182 public Scope getOuterScope() { |
972 if (switcher == null) { | 1183 if (switcher == null) { |
973 return null; | 1184 return null; |
974 } | 1185 } |
975 return switcher.getOuterScope(); | 1186 return switcher.getOuterScope(); |
976 } | 1187 } |
977 } | 1188 } |
978 } | 1189 } |
OLD | NEW |