package org.easysoa.discovery.mock; import java.io.IOException; import java.io.OutputStream; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.DeserializationConfig.Feature; import org.codehaus.jackson.map.ObjectMapper; import org.easysoa.discovery.rest.model.Deliverable; import org.easysoa.discovery.rest.model.DeployedDeliverable; import org.easysoa.discovery.rest.model.Endpoint; import org.easysoa.discovery.rest.model.Environment; import org.easysoa.discovery.rest.model.Service; import org.easysoa.discovery.rest.model.ServiceImpl; import org.easysoa.discovery.rest.model.SoaNode; import org.easysoa.discovery.rest.model.SoaNodeType; import org.easysoa.discovery.rest.model.SoaSystem; import org.easysoa.discovery.rest.model.Software; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.uci.ics.jung.graph.DirectedSparseGraph; import edu.uci.ics.jung.graph.Graph; import edu.uci.ics.jung.graph.util.EdgeType; public class MockRepository extends OutputStream { private static final Logger logger = LoggerFactory.getLogger(MockRepository.class); private StringBuffer requestBuffer = new StringBuffer(); private Graph<String, String> graph = new DirectedSparseGraph<String, String>(); private Map<String, SoaNode> nodes = new HashMap<String, SoaNode>(); public OutputStream getOutputStream() { return this; } @Override public void write(int c) throws IOException { requestBuffer.append((char) c); } @Override public void close() throws IOException { super.close(); // Build request string String requestString = requestBuffer.toString(); requestBuffer = new StringBuffer(); // Handle request if (!requestString.isEmpty()) { try { ObjectMapper mapper = new ObjectMapper(); mapper.configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); JsonNode readTree = mapper.readTree(requestString); Iterator<JsonNode> discoveryIt = readTree.getElements(); // Handle each discovery while (discoveryIt.hasNext()) { JsonNode discovery = discoveryIt.next(); // Trace JSON message logger.info(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(discovery)); // Parse JSON to POJO SoaNodeType soaNodeType = SoaNodeType.valueOf(discovery.get("soaNodeType").getTextValue()); SoaNode newNode = null; switch (soaNodeType) { case SoaSystem: newNode = mapper.readValue(discovery, SoaSystem.class); break; case Software: newNode = mapper.readValue(discovery, Software.class); break; case Service: newNode = mapper.readValue(discovery, Service.class); break; case Deliverable: newNode = mapper.readValue(discovery, Deliverable.class); break; case ServiceImpl: newNode = mapper.readValue(discovery, ServiceImpl.class); break; case Environment: newNode = mapper.readValue(discovery, Environment.class); break; case DeployedDeliverable: newNode = mapper.readValue(discovery, DeployedDeliverable.class); break; case Endpoint: newNode = mapper.readValue(discovery, Endpoint.class); break; } // Add graph vertex if (!graph.containsVertex(newNode.getId())) { graph.addVertex(newNode.getId()); } // Add graph edges for (Entry<String, SoaNodeType> relation : newNode.getRelations().entrySet()) { addEdge(newNode.getId(), newNode.getSoaNodeType(), relation.getKey(), relation.getValue()); } // Store/merge node contents (XXX only the name/version/relations are merged) SoaNode prevNode = nodes.get(newNode.getId()); if (prevNode != null) { if (newNode.getName() == null) { newNode.setName(prevNode.getName()); } if (newNode.getVersion() == null) { newNode.setVersion(prevNode.getVersion()); } Map<String, SoaNodeType> relations = prevNode.getRelations(); relations.putAll(newNode.getRelations()); newNode.setRelations(relations); } nodes.put(newNode.getId(), newNode); // XXX Overriden instead of merged } } catch (Exception e) { logger.error("Failed to parse JSON discovery", e); } } } public void traceRepository() { logger.info("Repository contents"); logger.info("-------------------"); Collection<String> vertices = graph.getVertices(); for (String vertice : vertices) { if (graph.getPredecessors(vertice).isEmpty()) { traceRepository(vertice, 0); } } logger.info("-------------------"); logger.info(""); } private void traceRepository(String currentId, int depth) { if (depth < 10) { SoaNode soaNode = nodes.get(currentId); if (soaNode != null) { logger.info(spacing(depth) + soaNode.toString()); Collection<String> successors = graph.getSuccessors(currentId); for (String successor : successors) { traceRepository(successor, depth + 1); } } else { logger.info(spacing(depth) + "???"); } } else { logger.info(spacing(depth) + "..."); } } private String spacing(int depth) { StringBuilder spaces = new StringBuilder(); for (int i = 0; i < depth; i++) { spaces.append(" "); } return spaces.toString(); } private void addEdge(String nodeId1, SoaNodeType nodeType1, String nodeId2, SoaNodeType nodeType2) { if (!isValidEdgeDirection(nodeType1, nodeType2)) { String buffer = nodeId1; nodeId1 = nodeId2; nodeId2 = buffer; } graph.addEdge(nodeId1 + " > " + nodeId2, nodeId1, nodeId2, EdgeType.DIRECTED); } private boolean isValidEdgeDirection(SoaNodeType from, SoaNodeType to) { return getTypeLevel(from) - getTypeLevel(to) > 0; } private int getTypeLevel(SoaNodeType soaNodeType) { switch (soaNodeType) { case SoaSystem: return 10; case Service: return 9; case Software: return 8; case Deliverable: return 7; case ServiceImpl: return 5; case Environment: return 4; case DeployedDeliverable: return 3; case Endpoint: return 2; default: return 0; } } }