text: /*******************************************************************************
   *  Copyright © 2012-2015 eBay Software Foundation
   *  This program is dual licensed under the MIT and Apache 2.0 licenses.
   *  Please see LICENSE for more information.
   *******************************************************************************/
  package com.ebay.jetstream.application.dataflows;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.URL;
  import java.net.URLConnection;
  import java.nio.ByteBuffer;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Map.Entry;
  import java.util.Set;
  
  import org.apache.commons.httpclient.HttpClient;
  import org.apache.commons.httpclient.NameValuePair;
  import org.apache.commons.httpclient.methods.PostMethod;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.InitializingBean;
  import org.springframework.beans.factory.support.DefaultListableBeanFactory;
  import org.springframework.jmx.export.annotation.ManagedResource;
  
  import com.ebay.jetstream.config.AbstractNamedBean;
  import com.ebay.jetstream.config.RootConfiguration;
  import com.ebay.jetstream.management.Management;
  import com.ebay.jetstream.util.CommonUtils;
  import com.ebay.jetstream.xmlser.Hidden;
  import com.ebay.jetstream.xmlser.XSerializable;
  
  /**
   * Visualizes the Jetstream pipeline using yuml.me
   * 
   * @author varavindan
   * 
   */
  @ManagedResource(objectName = "Event/DataFlows", description = "data flow visualization")
  public class VisualDataFlow extends AbstractNamedBean implements XSerializable,
  		InitializingBean {
  
  	private Map<String, Set<String>> graph;
  	private DefaultListableBeanFactory beanFactory;
  	private static final String yumlUrl = "http://yuml.me/";
  	private static final String yumlActivityUrl = "http://yuml.me/diagram/scruffy/activity";
  	private static final int BUF = 512;
  	private final Map<String, URL> graphYuml = new HashMap<String, URL>();
  	private static Logger logger = LoggerFactory.getLogger(VisualDataFlow.class); 
  
  	public Map<String, URL> getGraphYuml() {
  		return graphYuml;
  	}
  
  	public VisualDataFlow() {
  	}
  
  	private URL getYumlPic(String yumlData) {
  		try {
  			if (!graphYuml.containsKey(yumlData)) {
  				HttpClient httpclient = new HttpClient();
  				PostMethod post = new PostMethod(yumlActivityUrl);
  				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
  				post.addParameter(new NameValuePair("dsl_text", yumlData));
  				httpclient.executeMethod(post);
  				URL url = new URL(yumlUrl + post.getResponseBodyAsString());
  				graphYuml.put(yumlData, url);
  				return url;
  			} else {
  				return graphYuml.get(yumlData);
  			}
  		} catch (Exception e) {
  			logger.error(" Exception while rendering pipeline ", e);
  			return null;
  		}
  	}
  
  	public ByteBuffer getAsByteArray(URL url) throws IOException {
  		URLConnection connection = url.openConnection();
  		InputStream in = connection.getInputStream();
  		int contentLength = connection.getContentLength();
  		ByteArrayOutputStream tmpOut;
  
  		if (contentLength != -1) {
  			tmpOut = new ByteArrayOutputStream(contentLength);
  		} else {
  			tmpOut = new ByteArrayOutputStream(16384);
  		}
  
  		byte[] buf = new byte[BUF];
  		while (true) {
  			int len = in.read(buf);
  			if (len == -1) {
  				break;
  			}
  			tmpOut.write(buf, 0, len);
  		}
  		in.close();
  		tmpOut.close();
  		byte[] array = tmpOut.toByteArray();
  		return ByteBuffer.wrap(array);
  	}
  
  	@Hidden
  	public ByteBuffer getVisual() {
  		try {
  			String yumlData = "";
  			DataFlows dFlow = (DataFlows) RootConfiguration.get("DataFlows");
  			Map<String, Set<String>> graph = dFlow.getGraph();
  			int edges = graph.size();
  			for (Entry<String, Set<String>> edge : graph.entrySet()) {
  				if (!CommonUtils.isEmpty(edge.getValue())) {
  					for (String v : edge.getValue()) {
  						yumlData += "(" + edge.getKey() + ")" + "->" + "(" + v
  								+ ")";
  						yumlData += ",";
  					}
  				} else {
  					yumlData += "(" + edge.getKey() + ")";
  					yumlData += ",";
  				}
  			}
  			yumlData = yumlData.replaceAll(",$", "");
  			return getAsByteArray(getYumlPic(yumlData));
  		} catch (Throwable e) {
  			logger.error(" Exception while construting pipeline data ", e);
  			return null;
  		}
  	}
  
  	public void setGraph(Map<String, Set<String>> graph) {
  		this.graph = graph;
  	}
  
  	@Override
  	public void afterPropertiesSet() throws Exception {
  		Management.addBean(getBeanName(), this);
  	}
  
  }
  