/**
 *  Copyright (c) 2012, 2016 Sme.UP and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *
 * Contributors:
 *   Mattia Rocchi - Initial API and implementation
 */
package org.smeup.sys.dk.source.nio;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.impl.BasicEObjectImpl;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.smeup.sys.dk.source.QProject;
import org.smeup.sys.il.core.QObjectNameable;
import org.smeup.sys.rt.core.QApplication;

public class NIOObjectSerializer {

	private QApplication application;
	private ResourceSet resourceSet;

	public NIOObjectSerializer(QApplication application, ResourceSet resourceSet) {
		this.application = application;
		this.resourceSet = resourceSet;
	}

	public <T extends QObjectNameable> ByteArrayOutputStream serialize(QProject project, Class<T> klass, String name, T object) throws IOException {

		URI uri = buildURI(project, klass, name);

		synchronized (uri.toString().intern()) {
			NIOResourceImpl resource = (NIOResourceImpl) resourceSet.getResource(uri, false);
			if (resource == null)
				resource = (NIOResourceImpl) resourceSet.createResource(uri, "asup");
			else
				clearResource(resource);

			((BasicEObjectImpl) object).eSetResource(null, null);
			resource.getContents().add((EObject) object);

			ByteArrayOutputStream output = new ByteArrayOutputStream();
			resource.doSave(output, Collections.EMPTY_MAP);
			
			return output;
		}
	}

	@SuppressWarnings("unchecked")
	public <T extends QObjectNameable> T deserialize(QProject project, Class<T> klass, String name, InputStream inputStream) throws IOException {

		URI uri = buildURI(project, klass, name);

		synchronized (uri.toString().intern()) {
			NIOResourceImpl resource = (NIOResourceImpl) resourceSet.getResource(uri, false);
			if (resource == null)
				resource = (NIOResourceImpl) resourceSet.createResource(uri, "asup");
			else {
				clearResource(resource);
			}

			resource.doLoad(inputStream, resourceSet.getLoadOptions());
			if (resource.getContents().isEmpty())
				return null;

			EObject eObject = resource.getContents().get(0);
			
			return (T) eObject;
		}
	}

	private void clearResource(NIOResourceImpl resource) {
		BasicEObjectImpl oldObject = null;
		if (resource.isLoaded() && !resource.getContents().isEmpty()) {
			oldObject = (BasicEObjectImpl) resource.getContents().get(0);
			resource.getContents().clear();
			oldObject.eSetResource(resource, null);
		}
	}

	private <T extends QObjectNameable> URI buildURI(QProject project, Class<T> klass, String name) {

		String uri = "asup://" + application.getName() + "/" + project.getName() + "/" + klass.getSimpleName().toLowerCase().substring(1);
		URI eURI = URI.createURI(uri);
		
		// TODO remove me
		eURI = eURI.appendFragment(name);
		
		return eURI;
	}
}
@@ -1292,32 +1292,53 @@
  klass, name);%0A%0A
+%09%09// resource object%0A
 %09%09synchronized (
@@ -1385,32 +1385,107 @@
 eImpl resource =
+ null;%0A%09%09%09%0A%09%09%09// resourceSet%0A%09%09%09synchronized (resourceSet) %7B%0A%09%09%09%09resource =
  (NIOResourceImp
@@ -1516,32 +1516,33 @@
 ce(uri, false);%0A
+%09
 %09%09%09if (resource 
@@ -1546,32 +1546,33 @@
 ce == null)%0A%09%09%09%09
+%09
 resource = (NIOR
@@ -1621,24 +1621,25 @@
 i, %22asup%22);%0A
+%09
 %09%09%09else%0A%09%09%09%09
@@ -1634,24 +1634,25 @@
 %09%09%09else%0A%09%09%09%09
+%09
 clearResourc
@@ -1664,17 +1664,17 @@
 ource);%0A
-%0A
+%09
 %09%09%09((Bas
@@ -1721,24 +1721,25 @@
 , null);%0A%09%09%09
+%09
 resource.get
@@ -1771,16 +1771,21 @@
 object);
+%0A%09%09%09%7D
 %0A%0A%09%09%09Byt
@@ -1892,20 +1892,17 @@
 Y_MAP);%0A
-%09%09%09
 %0A
+
 %09%09%09retur
@@ -2586,20 +2586,17 @@
 get(0);%0A
-%09%09%09
 %0A
+
 %09%09%09retur
@@ -3194,19 +3194,17 @@
 I(uri);%0A
-%09%09
 %0A
+
 %09%09// TOD
@@ -3251,18 +3251,16 @@
 (name);%0A
-%09%09
 %0A%09%09retur

Patch concurrent modification