/******************************************************************************* * Copyright 2017 Capital One Services, LLC and Bitwise, Inc. * 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 hydrograph.engine.schemapropagation; import hydrograph.engine.core.component.entity.elements.SchemaField; import hydrograph.engine.core.utilities.SocketUtilities; import hydrograph.engine.jaxb.commontypes.TypeBaseComponent; import hydrograph.engine.jaxb.commontypes.TypeBaseInSocket; import hydrograph.engine.jaxb.commontypes.TypeBaseOutSocket; import hydrograph.engine.jaxb.commontypes.TypeInputComponent; import hydrograph.engine.jaxb.commontypes.TypeOperationsComponent; import hydrograph.engine.jaxb.commontypes.TypeOutputComponent; import hydrograph.engine.jaxb.commontypes.TypeStraightPullComponent; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; public class SchemaFieldHandler { private List<TypeBaseComponent> jaxbGraph; private Map<String, TypeBaseComponent> componentMap; private Map<String, Set<SchemaField>> schemaFields; public SchemaFieldHandler(List<TypeBaseComponent> jaxbGraphlist) { jaxbGraph = jaxbGraphlist; componentMap = new HashMap<String, TypeBaseComponent>(); schemaFields = new LinkedHashMap<String, Set<SchemaField>>(); generateSchemaFields(); } public Map<String, Set<SchemaField>> getSchemaFieldMap() { return schemaFields; } private void generateSchemaFields() { for (String componentId : getOrderedComponentsList(jaxbGraph)) { TypeBaseComponent baseComponent = componentMap.get(componentId); OperationHandler operationHandler = new OperationHandler(baseComponent, schemaFields); if (baseComponent instanceof TypeInputComponent) { schemaFields.putAll(operationHandler.getInputFields()); } else if (baseComponent instanceof TypeOutputComponent) { schemaFields.putAll(operationHandler.getOutputFields()); } else if (baseComponent instanceof TypeStraightPullComponent) { schemaFields.putAll(operationHandler.getStraightPullSchemaFields()); } else if (baseComponent instanceof TypeOperationsComponent) { schemaFields.putAll(operationHandler.getOperation()); } /*else if (baseComponent instanceof TypeCommandComponent) { // no need of schema fields }*/ } } private List<String> getOrderedComponentsList(List<TypeBaseComponent> jaxbGraph) { HashMap<String, Integer> componentDependencies = new HashMap<String, Integer>(); ArrayList<String> orderedComponents = new ArrayList<String>(); Queue<String> resolvedComponents = new LinkedList<String>(); for (TypeBaseComponent component : jaxbGraph) { int intitialDependency; intitialDependency = SocketUtilities.getInSocketList(component).size(); if (intitialDependency == 0) { resolvedComponents.add(component.getId()); } else { componentDependencies.put(component.getId(), intitialDependency); } componentMap.put(component.getId(), component); } if (resolvedComponents.isEmpty() && !componentDependencies.isEmpty()) { throw new RuntimeException("Unable to find any source component in graph " + jaxbGraph); } while (!resolvedComponents.isEmpty()) { // get resolved component String component = resolvedComponents.remove(); // add to ordered list orderedComponents.add(component); // reduce the dependency of the components which are dependent on // this component List<? extends TypeBaseOutSocket> outSocketList = SocketUtilities .getOutSocketList(componentMap.get(component)); for (TypeBaseOutSocket link : outSocketList) { // get the dependent component String targetComponent = getDependentComponent(link.getId(), component); if (targetComponent == null) throw new RuntimeException("Unable to find Depenedent components in traversal for " + component + ". This may be due to circular dependecies or unlinked components. "); // decrease the dependency by one Integer dependency = componentDependencies.get(targetComponent); dependency = dependency - 1; // if dependency is resolved then add it to resolved queue if (dependency == 0) { resolvedComponents.add(targetComponent); // also remove it from dependency pool componentDependencies.remove(targetComponent); } else { // else just update the dependency componentDependencies.put(targetComponent, dependency); } } } if (!componentDependencies.isEmpty()) { String components = ""; for (String componentID : componentDependencies.keySet()) { components = components + ", " + componentID; } throw new RuntimeException("Unable to include following components in traversal" + components + ". This may be due to circular dependecies or unlinked components. Please inspect and remove circular dependencies."); } return orderedComponents; } private String getDependentComponent(String socketId, String componentID) { for (TypeBaseComponent component : jaxbGraph) { List<? extends TypeBaseInSocket> inSocketList = SocketUtilities.getInSocketList(component); for (TypeBaseInSocket inSocket : inSocketList) { if (inSocket.getFromComponentId().equals(componentID) && inSocket.getFromSocketId().equals(socketId)) return component.getId(); } } throw new RuntimeException("Dependent component not found for component with id '" + componentID + "' and socket id '" + socketId + "'"); } }