Java tutorial
/******************************************************************************* * Copyright (c) 2013 Guillaume Hillairet. * 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: * Guillaume Hillairet - initial API and implementation *******************************************************************************/ package org.eclipselabs.emfjson.gwt.map; import static org.eclipselabs.emfjson.gwt.common.Constants.EJS_REF_KEYWORD; import static org.eclipselabs.emfjson.gwt.common.ModelUtil.getEReference; import static org.eclipselabs.emfjson.gwt.common.ModelUtil.isMapEntry; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.emf.common.util.Callback; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.resource.Resource; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONValue; class EReferenceDeserializer { private Deserializer deserializer; private MapDeserializer mapDeserializer; EReferenceDeserializer(Deserializer deserializer) { this.deserializer = deserializer; this.mapDeserializer = new MapDeserializer(); } void deSerialize(EObject eObject, JSONObject node, Resource resource) { if (node == null) return; EClass eClass = eObject.eClass(); for (String key : node.keySet()) { JSONValue value = node.get(key); EReference reference = getEReference(eClass, key); if (isCandidate(reference)) { if (isMapEntry(reference.getEType()) && value.isObject() != null) { mapDeserializer.deSerializeMapEntry(eObject, reference, value.isObject()); } else { deSerializeContainment(eObject, reference, node, value, resource); } } } } void deSerialize(EObject eObject, JSONObject node, Resource resource, Callback<EObject> callback) { if (node == null) return; Map<EReference, JSONValue> pairs = new HashMap<EReference, JSONValue>(); EClass eClass = eObject.eClass(); for (String key : node.keySet()) { JSONValue value = node.get(key); EReference reference = getEReference(eClass, key); if (isCandidate(reference)) pairs.put(reference, value); } Iterator<EReference> it = pairs.keySet().iterator(); deSerializeEach(eObject, resource, pairs, it, callback); } void deSerializeEach(final EObject eObject, final Resource resource, final Map<EReference, JSONValue> pairs, final Iterator<EReference> it, final Callback<EObject> callback) { if (it.hasNext()) { EReference reference = it.next(); JSONValue value = pairs.get(reference); // if (isMapEntry(reference.getEType()) && value.isObject() != null) { // } else { deSerializeContainment(eObject, reference, value, resource, new Callback<EObject>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); } @Override public void onSuccess(EObject result) { deSerializeEach(eObject, resource, pairs, it, callback); } }); } else { callback.onSuccess(eObject); } } void deSerializeContainment(EObject eObject, EReference reference, JSONObject root, JSONValue value, Resource resource) { JSONArray array = value.isArray(); if (array != null) { if (reference.isMany()) { @SuppressWarnings("unchecked") EList<EObject> values = (EList<EObject>) eObject.eGet(reference); for (int i = 0; i < array.size(); i++) { JSONValue current = array.get(i); EObject contained = createContainedObject(reference, current.isObject(), resource); if (contained != null) values.add(contained); } } } JSONObject object = value.isObject(); if (object != null) { EObject contained = createContainedObject(reference, value.isObject(), resource); if (contained != null) eObject.eSet(reference, contained); } } void deSerializeContainment(final EObject eObject, final EReference reference, JSONValue value, final Resource resource, final Callback<EObject> callback) { JSONArray array = value.isArray(); if (array != null && reference.isMany()) { createContainedObjectEach(eObject, reference, resource, array, 0, new Callback<EObject>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); } @Override public void onSuccess(EObject result) { callback.onSuccess(result); } }); } JSONObject object = value.isObject(); if (object != null && !reference.isMany()) { createContainedObject(reference, object, resource, new Callback<EObject>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); } @Override public void onSuccess(EObject result) { if (result != null) { eObject.eSet(reference, result); } callback.onSuccess(result); } }); } } void createContainedObjectEach(final EObject eObject, final EReference reference, final Resource resource, final JSONArray array, int idx, final Callback<EObject> callback) { if (idx < array.size()) { final JSONValue current = array.get(idx); final int i = ++idx; createContainedObject(reference, current.isObject(), resource, new Callback<EObject>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); } @Override public void onSuccess(EObject result) { @SuppressWarnings("unchecked") EList<EObject> values = (EList<EObject>) eObject.eGet(reference); values.add(result); createContainedObjectEach(eObject, reference, resource, array, i, callback); } }); } else { callback.onSuccess(eObject); } } EObject createContainedObject(EReference reference, JSONObject node, Resource resource) { EObject obj = null; if (node != null) { EClass eClass = JSUtil.findEClass(reference.getEReferenceType(), node, resource, deserializer.getNamespaces()); if (isRefNode(node)) { obj = deserializer.getProxyFactory().createProxy(resource, eClass, node); } else if (node.isObject() != null) { obj = deserializer.from(node.isObject(), eClass, resource); } } return obj; } void createContainedObject(EReference reference, final JSONObject node, final Resource resource, final Callback<EObject> callback) { if (node != null) { JSUtil.findEClass(reference.getEReferenceType(), node, resource, deserializer.getNamespaces(), new Callback<EClass>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); } @Override public void onSuccess(EClass eClass) { if (isRefNode(node)) { deserializer.getProxyFactory().createProxy(resource, eClass, node); } else if (node.isObject() != null) { // EObject result = EcoreUtil.create(eClass); // callback.onSuccess(result); deserializer.from(node.isObject(), eClass, resource, false, new Callback<EObject>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); } @Override public void onSuccess(EObject result) { callback.onSuccess(result); } }); } } }); } } boolean isCandidate(EReference reference) { return reference != null && reference.isContainment() && !reference.isTransient(); } boolean isRefNode(JSONValue node) { return node.isObject() != null && node.isObject().containsKey(EJS_REF_KEYWORD); } }