AvailableOutputsImpl implements AvailableOutputs { @Override public synchronized Set<OutputName> getAvailableOutputs(Class<?> inputType) { if (_allOutputsByInputType.containsKey(inputType)) { return _allOutputsByInputType.get(inputType); } Set<Class<?>> supertypes = EngineUtils.getSupertypes(inputType); Set<OutputName> outputs = Sets.newTreeSet(); for (Class<?> supertype : supertypes) { if (_outputsByInputType.containsKey(supertype)) { outputs.addAll(_outputsByInputType.get(supertype)); } } _allOutputsByInputType.put(inputType, outputs); return Collections.unmodifiableSet(outputs); } AvailableOutputsImpl();  AvailableOutputsImpl(Class<?>... inputTypes);  AvailableOutputsImpl(Set<Class<?>> inputTypes); @Override Set<Class<?>> getInputTypes(OutputName outputName); @Override synchronized Set<Class<?>> getInputTypes(); @Override synchronized Set<OutputName> getAvailableOutputs(Class<?> inputType); @Override Set<OutputName> getAvailableOutputs(); @Override synchronized FunctionMetadata getOutputFunction(OutputName outputName, Class<?> inputType); @Override synchronized FunctionMetadata getOutputFunction(OutputName outputName); @Override synchronized void register(Class<?>... functionInterfaces);  }
@Test public void getAvailableOutputs() { AvailableOutputs outputs = new AvailableOutputsImpl(s_inputTypes); outputs.register(F1.class, F2.class); assertEquals(ImmutableSortedSet.of(O1_NAME, O2_NAME), outputs.getAvailableOutputs(Target3.class)); assertEquals(ImmutableSortedSet.of(O1_NAME, O2_NAME), outputs.getAvailableOutputs(Target2.class)); assertEquals(ImmutableSortedSet.of(O1_NAME), outputs.getAvailableOutputs(Target1.class)); assertEquals(Collections.<String>emptySet(), outputs.getAvailableOutputs(Object.class)); }