Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(895)

Side by Side Diff: plugins/org.chromium.debug.ui/src/org/chromium/debug/ui/DialogUtils.java

Issue 6312048: Redo normal expressions in dialog updater to be thread-safe (Closed) Base URL: https://chromedevtools.googlecode.com/svn/trunk
Patch Set: follow codereview Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | plugins/org.chromium.debug.ui/src/org/chromium/debug/ui/WizardUtils.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | plugins/org.chromium.debug.ui/src/org/chromium/debug/ui/WizardUtils.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698