/*

 * Delivered to the U.S. Government in Accordance with Contract FA8650-10-C-7080.

 *

 * EXPORT CONTROLLED

 * ECCN#   EAR99

 * Warning: This document contains technical data which is controlled under the

 * Bureau of Industry & Security's Export Administration Regulations and may not be

 * exported or re-exported without authorization by the Bureau of Industry & Security.

 * Diversion contrary to US law is prohibited.

 *

 * (c) 2011 United Technologies Corp.

 * Developed with the sponsorship of the Defense Advanced Research Projects Agency (DARPA).

 *

 * Permission is hereby granted, free of charge, to any person obtaining a copy of this data,

 * including any software or models in source or binary form, as well as any drawings, 

 * specifications, and documentation (collectively "the Data"), to deal in the Data without 

 * restriction, including without limitation the rights to use, copy, modify, merge, publish,

 * distribute, sublicense, and/or sell copies of the Data, and to permit persons to whom the Data

 * is furnished to do so, subject to the following conditions:

 * 

 * The above copyright notice and this permission notice shall be included in all copies or

 * substantial portions of the Data.

 *

 * THE DATA IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING

 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND

 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS, SPONSORS, DEVELOPERS, CONTRIBUTORS, OR

 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION

 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE DATA OR THE

 * USE OR OTHER DEALINGS IN THE DATA.

*/

package meta.util;



import java.io.FileOutputStream;

import java.io.IOException;

import java.util.List;

import java.util.UUID;



import org.jdom.Attribute;

import org.jdom.Document;

import org.jdom.Element;

import org.jdom.Namespace;

import org.jdom.output.XMLOutputter;



import meta.model.Architecture;

import meta.model.Device;

import meta.model.Link;



public class Export {

	private Namespace xmi;

	private Namespace uml;

    private int count;

	public Export() {

		xmi = Namespace.getNamespace("xmi",

				"http://schema.omg.org/spec/XMI/2.1");

		uml = Namespace.getNamespace("uml",

				"http://schema.omg.org/spec/UML/2.1.1");

		count = 0;

	}



	private String getGUID() {

		return String.format("GUID+%s", UUID.randomUUID());

	}

	private Element buildOwnedEnd(String guid, String guidLink, Device device) {

		Element oe = new Element("OwnedEnd");

		String sname = String.format("its%s", device.getName());

		Attribute xmitype = new Attribute("type", "uml:Property", xmi);

		Attribute id = new Attribute("id", guid, xmi);

		Attribute name = new Attribute("name", sname);

		Attribute vis = new Attribute("visibility", "public");

		Attribute type = new Attribute("type", device.getGUID());

		Attribute oa = new Attribute("owningAssociation", guidLink);

		Attribute a = new Attribute("association", guidLink);

		oe.setAttribute(xmitype);

		oe.setAttribute(id);

		oe.setAttribute(name);

		oe.setAttribute(vis);

		oe.setAttribute(type);

		oe.setAttribute(oa);

		oe.setAttribute(a);

		return oe;

	}

	private Element buildUMLAssociationClass(Link link) {

		String name = String.format("f%d", count);

		Element pe = new Element("packagedElement");

		Attribute type = new Attribute("type", "uml:AssociationClass", xmi);

		String guid = link.getGUID();

		Attribute id = new Attribute("id", guid, xmi);

		String guidOwnEnd1 = getGUID();

		String guidOwnEnd2 = getGUID();

		String smemberEnd = String.format("%s %s", guidOwnEnd1,guidOwnEnd2);

		Attribute memberEnd = new Attribute("memberEnd",smemberEnd);

		Attribute navigableOwnedEnd = new Attribute("navigableOwnedEnd",guidOwnEnd2);

		pe.setAttribute(type);

		pe.setAttribute(id);

		pe.setAttribute("name", name); count++;

		pe.setAttribute(memberEnd);

		pe.setAttribute(navigableOwnedEnd);

		Element ownEnd1 = buildOwnedEnd(guidOwnEnd1, guid ,link.getSource());

		Element ownEnd2 = buildOwnedEnd(guidOwnEnd2, guid ,link.getSink());

		pe.addContent(ownEnd1);

		pe.addContent(ownEnd2);

		return pe;

	}

    /**

     * Build a UML class for a device

     * @param device

     */

	private Element buildUMLclass(Device device) {

		Element e = new Element("packagedElement");

		Attribute type = new Attribute("type", "uml:Class", xmi);

		String name = device.getName();

		String guid = device.getGUID();

		Attribute id = new Attribute("id", guid, xmi);

		e.setAttribute(type);

		e.setAttribute(id);

		e.setAttribute("name", name);

		return e;

	}



	/**

	 * Export the architecture in XMI format 

	 */

	public void toXMI(Architecture arch) {



		Element root = new Element("XMI", xmi);

		root.addNamespaceDeclaration(uml);

		Attribute ver = new Attribute("version", "2.1", xmi);

		root.setAttribute(ver);

		Document doc = new Document(root);

		Element packagee = new Element("Package", uml);

		String id = getGUID();

		packagee.setAttribute("id", id, xmi);

		packagee.setAttribute("name", "meta");



		// create a UML class for each device

		List<Device> dlist = arch.getDevices();

		for (Device d : dlist) {

			Element devElem = buildUMLclass(d);

			packagee.addContent(devElem);

		}

		// creae a UML association class for each link

		List<Link> link1 = arch.getLinkTable();

	    for ( Link l : link1) {

	         Element linkElem = buildUMLAssociationClass(l);

	         packagee.addContent(linkElem);

	    }

		root.addContent(packagee);

		try {

			String tmp = System.getProperty("java.io.tmpdir");

			String name = arch.getName();

			String file = String.format("%s\\%s.xmi", tmp, name);

			FileOutputStream out = new FileOutputStream(file);

			XMLOutputter serializer = new XMLOutputter();

			serializer.output(doc, out);

			out.flush();

			out.close();

		} catch (IOException e) {



		}



	}

}

