All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.emfjson.gwt.map.JsonReader Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2015 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.emfjson.gwt.map;

import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import org.eclipse.emf.common.util.Callback;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.*;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;

import org.emfjson.common.Options;
import org.emfjson.common.resource.UuidResource;
import org.emfjson.gwt.common.AsyncCache;
import org.emfjson.gwt.common.AsyncIterator;
import org.emfjson.gwt.common.AsyncReferenceEntry;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.emfjson.common.EObjects.createEntry;
import static org.emfjson.common.EObjects.isMapEntry;

public class JsonReader {

	private final Resource resource;
	private final ResourceSet resourceSet;
	private final Options options;
	private final AsyncCache cache = new AsyncCache();
	private final ValueSerializer valueSerializer = new ValueSerializer();
	private final List entries = new ArrayList<>();

	public JsonReader(Resource resource, Options options) {
		this.resource = resource;
		this.options = options;
		this.resourceSet = resource.getResourceSet();
	}

	public void parse(JSONValue value, final Callback done) {
		final JSONObject object = value.isObject();
		if (object != null) {
			parseObject(object, null, new Callback() {
				@Override
				public void onFailure(Throwable caught) {
					done.onFailure(caught);
				}

				@Override
				public void onSuccess(EObject result) {
					resource.getContents().add(result);
					resolveEntries(new Callback() {
						@Override
						public void onFailure(Throwable caught) {
							done.onFailure(caught);
						}

						@Override
						public void onSuccess(Resource resource) {
							done.onSuccess(resource);
						}
					});
				}
			});
		}

		final JSONArray array = value.isArray();
		if (array != null) {
			parseArray(array, new Callback() {
				@Override
				public void onFailure(Throwable caught) {
					done.onFailure(caught);
				}

				@Override
				public void onSuccess(final Resource result) {
					resolveEntries(new Callback() {
						@Override
						public void onFailure(Throwable caught) {
							done.onFailure(caught);
						}

						@Override
						public void onSuccess(Resource resource) {
							done.onSuccess(result);
						}
					});
				}
			});
		}
	}

	void parseArray(JSONArray array, Callback done) {
		AsyncIterator.forEach(resource, 0, array, this, done);
	}

	public void parseObject(final JSONObject node, final EReference container, final Callback done) {
		create(node, container, new Callback() {
			@Override
			public void onSuccess(EObject result) {
				fillObject(node, result, new Callback() {
					@Override
					public void onFailure(Throwable caught) {
						done.onFailure(caught);
					}

					@Override
					public void onSuccess(EObject result) {
						done.onSuccess(result);
					}
				});
			}

			@Override
			public void onFailure(Throwable caught) {
				done.onFailure(caught);
			}
		});
	}

	private void fillObject(JSONObject node, EObject object, final Callback done) {
		if (node == null || object == null) return;

		final EClass eClass = object.eClass();
		final Map containments = new HashMap<>();

		for (final String key : node.keySet()) {
			final EStructuralFeature feature = cache.getEStructuralFeature(eClass, key);
			final JSONValue value = node.get(key);

			if (feature instanceof EAttribute) {

				readAttribute((EAttribute) feature, object, value);

			} else if (feature instanceof EReference) {
				EReference reference = (EReference) feature;

				if (reference.isContainment()) {

					if (isMapEntry(reference.getEReferenceType())) {

						parseEntry(object, reference, value);

					} else {

						containments.put(reference, value);

					}

				} else {
					addEntry(object, reference, value);
				}

			}
		}

		AsyncIterator.forEach(object, containments, new Callback() {
			@Override
			public void onFailure(Throwable caught) {
				done.onFailure(caught);
			}

			@Override
			public void onSuccess(EObject result) {
				done.onSuccess(result);
			}
		}, this);
	}

	private void parseEntry(EObject owner, EReference reference, JSONValue value) {
		final JSONObject entryObject = value.isObject();
		if (entryObject != null) {
			setEntryObject(entryObject, owner, reference);
		} else {
			final JSONArray array = value.isArray();
			if (array != null) {
				for (int i = 0; i < array.size(); i++) {
					JSONValue current = array.get(i);
					if (current.isObject() != null) {
						setEntryObject(current.isObject(), owner, reference);
					}
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	private void setEntryObject(JSONObject entryObject, EObject owner, EReference reference) {
		EList values = null;

		if (reference.isMany()) {
			values = (EList) owner.eGet(reference);
		}

		if (entryObject != null) {

			for (String key : entryObject.keySet()) {
				final JSONValue entryValue = entryObject.get(key);
				final JSONString stringValue = entryValue.isString();

				if (stringValue != null) {
					if (reference.isMany() && values != null) {
						values.add(createEntry(key, stringValue.stringValue()));
					} else {
						owner.eSet(reference, createEntry(key, stringValue.stringValue()));
					}
				}
			}

		}
	}

	private void addEntry(EObject object, EReference reference, JSONValue value) {
		JSONArray array = value.isArray();
		if (array != null) {
			for (int i = 0; i < array.size(); i++) {
				String ref = getRef(array.get(i));
				if (ref != null) {
					entries.add(new AsyncReferenceEntry(object, reference, ref));
				}
			}
		} else {
			String ref = getRef(value);
			if (ref != null) {
				entries.add(new AsyncReferenceEntry(object, reference, ref));
			}
		}
	}

	private String getRef(JSONValue value) {
		final JSONObject refObject = value.isObject();
		if (refObject != null) {
			final JSONValue refValue = refObject.get(options.refField);
			if (refValue != null) {
				final JSONString string = refValue.isString();
				if (string != null) {
					return string.stringValue();
				}
			}
		}
		return null;
	}

	private void create(final JSONObject node, final EReference container, final Callback callback) {
		if (container != null &&
			container.getEReferenceType() != null &&
			!container.getEReferenceType().isAbstract()) {

			callback.onSuccess(create(container.getEReferenceType(), node));

		} else if (container == null && options.rootElement != null) {

			callback.onSuccess(create(options.rootElement, node));

		} else {

			cache.getEClass(resourceSet, getType(node), new Callback() {
				@Override
				public void onSuccess(EClass result) {
					callback.onSuccess(create(result, node));
				}

				@Override
				public void onFailure(Throwable caught) {
					callback.onFailure(caught);
				}
			});

		}
	}

	private EObject create(EClass eClass, JSONObject node) {
		EObject object = EcoreUtil.create(eClass);

		if (node.containsKey(options.idField)) {
			JSONString stringValue = node.get(options.idField).isString();

			if (stringValue != null && object != null && resource instanceof UuidResource) {
				((UuidResource) resource).setID(object, stringValue.stringValue());
			}
		}

		return object;
	}

	private String getType(JSONObject node) {
		final JSONValue typeValue = node.get(options.typeField);
		if (typeValue != null) {
			final JSONString stringValue = typeValue.isString();
			if (stringValue != null) {
				return stringValue.stringValue();
			}
		}
		return null;
	}

	private void readAttribute(EAttribute attribute, EObject object, JSONValue value) {
		final JSONArray array = value.isArray();
		if (array != null) {
			for (int i = 0; i < array.size(); i++) {
				valueSerializer.setOrAdd(object, attribute, array.get(i));
			}
		} else {
			valueSerializer.setOrAdd(object, attribute, value);
		}
	}

	private void resolveEntries(Callback callback) {
		AsyncIterator.forEach(resource, entries.iterator(), callback);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy