package com.thinkbiganalytics.nifi.rest.model.flow;
/*-
* #%L
* thinkbig-nifi-flow-visitor-model
* %%
* Copyright (C) 2017 ThinkBig Analytics
* %%
* 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.
* #L%
*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* JSON doesnt like circular dependencies. NifiFlowProcessor has a graph of objects that point up and down the tree. All attempts to deserialize the object with Jackson annotations on the
* NifiFlowProcessor failed For Example (@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")) Reference https://github.com/FasterXML/jackson-databind/issues/687 To
* get around this ids are stored instead of the entire object in the graph. This class will reattach the real objects back so you can then traverse the graph.
*/
public class NifiFlowDeserializer {
private static final Logger log = LoggerFactory.getLogger(NifiFlowDeserializer.class);
/**
* Construct the graph by reattaching the source/dest by looking at the ids
*
* @param group the graph of the flow to deserialize and connect and convert the id references to objects
*/
public static void constructGraph(NifiFlowProcessGroup group) {
if (group != null) {
log.info("constructing graph for {} ({})", group.getName(), group.getId());
//reattach the ids back to the graph of objects
Map<String, NifiFlowProcessor> processorMap = group.getProcessorMap();
processorMap.values().forEach(processor -> {
Set<NifiFlowProcessor> sources = processor.getSourceIds().stream().map(sourceId -> processorMap.get(sourceId)).collect(Collectors.toSet());
Set<NifiFlowProcessor> destinations = processor.getDestinationIds().stream().map(destId -> processorMap.get(destId)).collect(Collectors.toSet());
processor.setSources(sources);
processor.setDestinations(destinations);
processor.setProcessGroup(group);
});
//reattach to the group
group.setStartingProcessors(group.getStartingProcessors().stream().map(processor -> processorMap.get(processor.getId())).collect(Collectors.toSet()));
group.setEndingProcessors(
group.getEndingProcessors().values().stream().map(processor -> processorMap.get(processor.getId())).collect(Collectors.toMap(processor -> processor.getId(), processor -> processor)));
}
}
/**
* Remove any circular graph dependencies and replace it with id references
* These can be reconstructed later via the {@link this#constructGraph(NifiFlowProcessGroup)}
*
* @param group the graph of the flow to serialize
*/
public static void prepareForSerialization(NifiFlowProcessGroup group) {
//ensure the objects are cleared of references
Map<String, NifiFlowProcessor> processorMap = group.getProcessorMap();
processorMap.values().forEach(processor -> {
processor.setSources(null);
processor.setDestinations(null);
processor.setProcessGroup(null);
});
}
}