14d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com/**
24d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * Copyright (C) 2009 Google Inc.
34d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com *
44d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * Licensed under the Apache License, Version 2.0 (the "License");
54d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * you may not use this file except in compliance with the License.
64d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * You may obtain a copy of the License at
74d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com *
84d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * http://www.apache.org/licenses/LICENSE-2.0
94d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com *
104d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * Unless required by applicable law or agreed to in writing, software
114d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * distributed under the License is distributed on an "AS IS" BASIS,
124d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * See the License for the specific language governing permissions and
144d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com * limitations under the License.
154d93ce63450f6e58c44b0a8ef2143593fc08df86sberlin@gmail.com */
16ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
17ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.compackage com.google.inject.throwingproviders;
18ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
19ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.AbstractModule;
20ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.BindingAnnotation;
21ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.Exposed;
22ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.Guice;
23ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.Injector;
24ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.Key;
25ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.PrivateModule;
26ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.Provides;
27ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.TypeLiteral;
28ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.name.Named;
29ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport com.google.inject.name.Names;
30ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
31ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport junit.framework.TestCase;
32ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
33ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport java.lang.annotation.Retention;
34ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport java.lang.annotation.RetentionPolicy;
35ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport java.net.BindException;
36ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.comimport java.rmi.RemoteException;
37ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
38ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com/**
39ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com * Test methods for {@link CheckedProviderMethodsModule}.
40ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com */
41ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.compublic class CheckedProviderMethodsModuleTest extends TestCase {
42ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
43ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  private final TypeLiteral<RpcProvider<String>> rpcProviderOfString
44ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      = new TypeLiteral<RpcProvider<String>>() { };
45ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  private final TypeLiteral<RpcProvider<Integer>> rpcProviderOfInteger
46ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      = new TypeLiteral<RpcProvider<Integer>>() { };
47ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  private final TypeLiteral<RpcProvider<Long>> rpcProviderOfLong
48ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      = new TypeLiteral<RpcProvider<Long>>() { };
49ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  private final TypeLiteral<RpcProvider<Float>> rpcProviderOfFloat
50ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      = new TypeLiteral<RpcProvider<Float>>() { };
51ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  private final TypeLiteral<RpcProvider<Pair<Double, String>>> rpcProviderOfPair
52ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      = new TypeLiteral<RpcProvider<Pair<Double, String>>>() { };
53ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
54ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  private final TestScope testScope = new TestScope();
55ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
56ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  interface RpcProvider<T> extends CheckedProvider<T> {
57ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    T get() throws RemoteException, BindException;
58ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
59ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
60ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  @Retention(RetentionPolicy.RUNTIME)
61ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  @BindingAnnotation
62ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  @interface TestAnnotation {
63ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
64ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
65ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  class TestModule extends AbstractModule {
66ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
67ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    private int nextIntToReturn = 100;
68ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
69ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    @Override
70ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    protected void configure() {
71ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      bindScope(TestScope.Scoped.class, testScope);
72ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      install(ThrowingProviderBinder.forModule(this));
73ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      install(new TestPrivateModule());
74ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
75ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
76ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    @CheckedProvides(RpcProvider.class)
77ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    String getSomeStringFromServer() {
78ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      return "Works";
79ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
80ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
81ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    @CheckedProvides(RpcProvider.class) @TestScope.Scoped
82ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    int getSomeIntegerFromServer() {
83ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      return nextIntToReturn;
84ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
85ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
86ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    @CheckedProvides(RpcProvider.class) @TestAnnotation
87ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    long getSomeLongFromServer() {
88ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      return 0xffL;
89ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
90ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
91ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    @Provides
92ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    double getSomeDouble() {
93ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      return 2.0d;
94ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
95ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
96ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    @CheckedProvides(RpcProvider.class)
97ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    Pair<Double, String> getSomePair(Double input) {
98ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      return new Pair<Double, String>(input * 2, "foo");
99ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
100ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
101ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    @CheckedProvides(RpcProvider.class)
102ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    float getFloat() throws BindException {
103ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      throw new BindException("foo");
104ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
105ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
106ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    void setNextIntToReturn(int next) {
107ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      nextIntToReturn = next;
108ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
109ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
110ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
111ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  class TestPrivateModule extends PrivateModule {
112ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
113ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    @Override
114ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    protected void configure() {
115ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      install(ThrowingProviderBinder.forModule(this));
116ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
117ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
118ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    @CheckedProvides(RpcProvider.class) @Named("fruit") @Exposed
119ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    String provideApples() {
120ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      return "apple";
121ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
122ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
123ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
124ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
125ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  public void testNoAnnotationNoScope() throws BindException, RemoteException {
126ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    Injector injector = Guice.createInjector(new TestModule());
127ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    RpcProvider<String> provider = injector
128ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com        .getInstance(Key.get(rpcProviderOfString));
129ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    assertEquals("Works", provider.get());
130ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
131ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
132ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  public void testWithScope() throws BindException, RemoteException {
133ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    TestModule testModule = new TestModule();
134ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    Injector injector = Guice.createInjector(testModule);
135ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    RpcProvider<Integer> provider = injector
136ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com        .getInstance(Key.get(rpcProviderOfInteger));
137ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
138ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    assertEquals((Integer)100, provider.get());
139ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    testModule.setNextIntToReturn(120);
140ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    assertEquals((Integer)100, provider.get());
141ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    testScope.beginNewScope();
142ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    assertEquals((Integer)120, provider.get());
143ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
144ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
145ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  public void testWithAnnotation() throws BindException, RemoteException {
146ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    TestModule testModule = new TestModule();
147ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    Injector injector = Guice.createInjector(testModule);
148ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    RpcProvider<Long> provider = injector
149ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com        .getInstance(Key.get(rpcProviderOfLong, TestAnnotation.class));
150ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    assertEquals((Long)0xffL, provider.get());
151ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
152ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
153ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  public void testWithInjectedParameters() throws BindException, RemoteException {
154ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    TestModule testModule = new TestModule();
155ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    Injector injector = Guice.createInjector(testModule);
156ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    RpcProvider<Pair<Double, String>> provider = injector
157ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com        .getInstance(Key.get(rpcProviderOfPair));
158ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    Pair<Double, String> pair = provider.get();
159ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    assertEquals(pair.first, 4.0d);
160ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
161ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
162ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  public void testWithThrownException() {
163ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    TestModule testModule = new TestModule();
164ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    Injector injector = Guice.createInjector(testModule);
165ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    RpcProvider<Float> provider = injector
166ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com        .getInstance(Key.get(rpcProviderOfFloat));
167ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    try {
168ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      provider.get();
169ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      fail();
170ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    } catch (RemoteException e) {
171ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      fail();
172ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    } catch (BindException e) {
173ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com      // good
174ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    }
175ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
176ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
177ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  public void testExposedMethod() throws BindException, RemoteException {
178ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    TestModule testModule = new TestModule();
179ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    Injector injector = Guice.createInjector(testModule);
180ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    RpcProvider<String> provider = injector
181ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com        .getInstance(Key.get(rpcProviderOfString, Names.named("fruit")));
182ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com    assertEquals("apple", provider.get());
183ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
184ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
185ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com
186ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  private static class Pair<A, B> {
187b7a02b02d81c830d148355c90bc309bcd66fb592sberlin    A first;
188b7a02b02d81c830d148355c90bc309bcd66fb592sberlin    B second;
189b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
190b7a02b02d81c830d148355c90bc309bcd66fb592sberlin    Pair(A a, B b) {
191b7a02b02d81c830d148355c90bc309bcd66fb592sberlin      this.first= a;
192b7a02b02d81c830d148355c90bc309bcd66fb592sberlin      this.second = b;
193b7a02b02d81c830d148355c90bc309bcd66fb592sberlin    }
194ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com  }
195ba8a4cdebee559cd1b6ad4af2ef9f7f0d82d085dsberlin@gmail.com}