/* * Copyright 2014, Simon Matić Langford * Copyright 2014, The Sporting Exchange Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.betfair.cougar.transport.impl; import com.betfair.cougar.api.DehydratedExecutionContext; import com.betfair.cougar.api.export.Protocol; import com.betfair.cougar.api.export.ProtocolParadigm; import com.betfair.cougar.api.export.ProtocolRegistry; import com.betfair.cougar.core.api.GateListener; import com.betfair.cougar.core.api.builder.DehydratedExecutionContextBuilder; import com.betfair.cougar.transport.api.DehydratedExecutionContextComponent; import com.betfair.cougar.transport.api.DehydratedExecutionContextResolution; import com.betfair.cougar.transport.api.DehydratedExecutionContextResolverFactory; import com.betfair.cougar.transport.api.DehydratedExecutionContextResolver; import java.util.*; /** */ public class DehydratedExecutionContextResolutionImpl implements GateListener, DehydratedExecutionContextResolution { private List<DehydratedExecutionContextResolverFactory> factories = new ArrayList<>(); private Map<Protocol, Set<DehydratedExecutionContextResolver>> protocolResolvers = new HashMap<>(); @Override public void registerFactory(DehydratedExecutionContextResolverFactory factory) { factories.add(factory); } @Override public int getPriority() { // we want to run after all the transports have been registered // they will want to be initialised early anyway so they're registered before // the services/executables get bound return Integer.MAX_VALUE; } @Override public void onCougarStart() { init(true); } public void init(boolean failIfNotComplete) { for (ProtocolParadigm paradigm : ProtocolParadigm.values()) { Set<Protocol> protocols = ProtocolRegistry.protocols(paradigm); for (Protocol p : protocols) { Set<DehydratedExecutionContextComponent> remainingComponents = new HashSet<>(Arrays.asList(DehydratedExecutionContextComponent.values())); Set<DehydratedExecutionContextResolver> componentResolvers = new HashSet<>(); List<DehydratedExecutionContextResolverFactory> reversedFactories = new ArrayList<>(factories); Collections.reverse(reversedFactories); for (DehydratedExecutionContextResolverFactory f : reversedFactories) { DehydratedExecutionContextResolver<?,?>[] resolvers = f.resolvers(p); if (resolvers != null) { for (DehydratedExecutionContextResolver<?,?> resolver : resolvers) { DehydratedExecutionContextComponent[] components = resolver.supportedComponents(); Set<DehydratedExecutionContextComponent> handling = new HashSet<>(); for (DehydratedExecutionContextComponent component : components) { if (remainingComponents.contains(component)) { componentResolvers.add(resolver); remainingComponents.remove(component); handling.add(component); } } // notify the resolver what they will be resolving resolver.resolving(Collections.unmodifiableSet(handling)); } } } //todo: #82: this needs to go back once all protocols have been built.. && failIfNotComplete // if (!remainingComponents.isEmpty()) { // throw new IllegalStateException("I have unhandled components: "+remainingComponents); // } protocolResolvers.put(p, componentResolvers); } } } @Override public String getName() { return "DehydratedExecutionContextResolution"; } @Override public <T,C> DehydratedExecutionContext resolveExecutionContext(Protocol protocol, T transport, C credentialsContainer) { DehydratedExecutionContextBuilder builder = new DehydratedExecutionContextBuilder(); Set<DehydratedExecutionContextResolver> resolvers = protocolResolvers.get(protocol); if (resolvers != null) { //noinspection unchecked for (DehydratedExecutionContextResolver<T,C> r : resolvers) { // todo: #82: the builder needs to verify that items are only set once r.resolve(transport, credentialsContainer, builder); } } // the builder checks that all needed components have been set return builder.build(); } }