org.eclipselabs.emfjson.gwt.map.EReferenceDeserializer.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipselabs.emfjson.gwt.map.EReferenceDeserializer.java

Source

/*******************************************************************************
 * 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);
    }

}