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

org.bimserver.database.queries.om.JsonQueryObjectModelConverter Maven / Gradle / Ivy

Go to download

Shared libraries, common parent for both BIMserver and BimServerClientLib

There is a newer version: 2.0.0
Show newest version
package org.bimserver.database.queries.om;

/******************************************************************************
 * Copyright (C) 2009-2016  BIMserver.org
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see {@literal}.
 *****************************************************************************/

import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.bimserver.emf.PackageMetaData;
import org.bimserver.shared.QueryException;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EReference;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class JsonQueryObjectModelConverter {
	private PackageMetaData packageMetaData;

	public JsonQueryObjectModelConverter(PackageMetaData packageMetaData) {
		this.packageMetaData = packageMetaData;
	}
	
	public ObjectNode toJson(Query query) {
		ObjectMapper objectMapper = new ObjectMapper();
		ObjectNode queryNode = objectMapper.createObjectNode();
		Map defines = query.getDefines();
		ObjectNode definesNode = objectMapper.createObjectNode();
		queryNode.set("defines", definesNode);
		for (String key : defines.keySet()) {
			ObjectNode includeNode = objectMapper.createObjectNode();
			Include include = defines.get(key);
			ArrayNode fieldsNode = objectMapper.createArrayNode();
			for (EReference eReference : include.getFields()) {
				fieldsNode.add(eReference.getName());
			}
			definesNode.set(key, includeNode);
		}
		ArrayNode queryPartsNode = objectMapper.createArrayNode();
		queryNode.set("queries", queryPartsNode);
		for (QueryPart queryPart : query.getQueryParts()) {
			ObjectNode queryPartNode = objectMapper.createObjectNode();
			if (queryPart.hasTypes()) {
				ArrayNode typesNode = objectMapper.createArrayNode();
				queryPartNode.set("types", typesNode);
				for (EClass type : queryPart.getTypes()) {
					typesNode.add(type.getName());
				}
			}
			if (queryPart.hasOids()) {
				ArrayNode oidsNode = objectMapper.createArrayNode();
				queryPartNode.set("oids", oidsNode);
				for (long oid : queryPart.getOids()) {
					oidsNode.add(oid);
				}
			}
			queryPartsNode.add(queryPartNode);
		}
		return queryNode;
	}
	
	public Query parseJson(String queryName, ObjectNode fullQuery) throws QueryException {
		Query query = new Query(queryName, packageMetaData);
		if (fullQuery.has("defines")) {
			JsonNode defines = fullQuery.get("defines");
			if (defines instanceof ObjectNode) {
				parseDefines(query, (ObjectNode)fullQuery.get("defines"));
			} else {
				throw new QueryException("\"defines\" must be of type object");
			}
		}
		if (fullQuery.has("queries")) {
			JsonNode queriesNode = fullQuery.get("queries");
			if (queriesNode instanceof ArrayNode) {
				ArrayNode queries = (ArrayNode) fullQuery.get("queries");
				if (queries.size() == 0) {
					throw new QueryException("\"queries\" must contain at least one query");
				}
				for (int i=0; i fieldNames = jsonNode.fieldNames();
		int i=0;
		// First pass, get all the name and create stub includes, using two passing to allow the usage of includes defined later in the structure
		while (fieldNames.hasNext()) {
			String fieldName = fieldNames.next();
			JsonNode defineNode = jsonNode.get(fieldName);
			if (defineNode instanceof ObjectNode) {
				Include include = new Include(packageMetaData);
				query.addDefine(fieldName, include);
			} else {
				throw new QueryException("\"defines\"[" + i + "] must be of type object");
			}
			i++;
		}
		// Second pass, actually construct the includes
		fieldNames = jsonNode.fieldNames();
		while (fieldNames.hasNext()) {
			String fieldName = fieldNames.next();
			JsonNode defineNode = jsonNode.get(fieldName);
			ObjectNode define = (ObjectNode)defineNode;
			parseInclude(query, define, query.getDefine(fieldName));
		}
	}
	
	private Include parseInclude(Query query, ObjectNode jsonNode, Include include) throws QueryException {
		if (include == null) {
			include = new Include(packageMetaData);
		}
		if (!jsonNode.has("type") && !jsonNode.has("types")) {
			throw new QueryException("includes require a \"type\" or \"types\" field " + jsonNode);
		}
		if (jsonNode.has("type")) {
			JsonNode typeNode = jsonNode.get("type");
			if (typeNode.isTextual()) {
				EClass eClass = packageMetaData.getEClassIncludingDependencies(typeNode.asText());
				if (eClass == null) {
					throw new QueryException("Cannot find type \"" + typeNode.asText() + "\"");
				}
				include.addType(eClass, false);
			} else {
				throw new QueryException("\"type\" field mst be of type string");
			}
		}
		if (jsonNode.has("types")) {
			JsonNode typesNode = jsonNode.get("types");
			if (typesNode instanceof ArrayNode) {
				ArrayNode types = (ArrayNode)typesNode;
				if (types.size() == 0) {
					throw new QueryException("\"types\" must have a least one element");
				}
				for (int i=0; i> fields = properties.fields();
				while (fields.hasNext()) {
					Entry entry = fields.next();
					JsonNode value = entry.getValue();
					if (value.isValueNode()) {
						queryPart.addProperty(entry.getKey(), value.asBoolean());
					} else {
						throw new QueryException("property \"" + entry.getKey() + "\" type not supported");
					}
				}
			} else {
				throw new QueryException("\"properties\" must be of type object");
			}
		}
		if (objectNode.has("inBoundingBox")) {
			JsonNode boundingBoxNode = objectNode.get("inBoundingBox");
			if (boundingBoxNode instanceof ObjectNode) {
				ObjectNode boundingBox = (ObjectNode) boundingBoxNode;
				double x = checkFloat(boundingBox, "x");
				double y = checkFloat(boundingBox, "y");
				double z = checkFloat(boundingBox, "z");
				double width = checkFloat(boundingBox, "width");
				double height = checkFloat(boundingBox, "height");
				double depth = checkFloat(boundingBox, "depth");
				queryPart.setInBoundingBox(new InBoundingBox(x, y, z, width, height, depth));
			} else {
				throw new QueryException("\"inBoundingBox\" should be of type object");
			}
		}

		if (objectNode.has("include")) {
			JsonNode includeNode = objectNode.get("include");
			processSubInclude(query, queryPart, includeNode);
		}
		if (objectNode.has("includes")) {
			JsonNode includesNode = objectNode.get("includes");
			if (includesNode instanceof ArrayNode) {
				ArrayNode includes = (ArrayNode)includesNode;
				for (int i=0; i fieldNames = objectNode.fieldNames();
		while (fieldNames.hasNext()) {
			String fieldName = fieldNames.next();
			if (fieldName.equals("includeAllFields") || fieldName.equals("type") || fieldName.equals("types") || fieldName.equals("oid") || fieldName.equals("oids") || fieldName.equals("guid") || fieldName.equals("guids") || fieldName.equals("properties") || fieldName.equals("inBoundingBox") || fieldName.equals("include") || fieldName.equals("includes") || fieldName.equals("includeAllSubtypes")) {
				// fine
			} else {
				throw new QueryException("Unknown field: \"" + fieldName + "\"");
			}
		}
		
		query.addQueryPart(queryPart);
	}
	
	private double checkFloat(ObjectNode node, String key) throws QueryException {
		if (!node.has(key)) {
			throw new QueryException("\"" + key + "\" not found on \"inBoundingBox\"");
		}
		JsonNode jsonNode = node.get(key);
		if (jsonNode.isNumber()) {
			return jsonNode.asDouble();
		} else {
			throw new QueryException("\"" + key + "\" should be of type number");
		}
	}

	private void addType(ObjectNode objectNode, QueryPart queryPart, String type) throws QueryException {
		if (type.equals("Object")) {
			// no type filter
			return;
		}
		EClass eClass = packageMetaData.getEClassIncludingDependencies(type);
		if (eClass == null) {
			throw new QueryException("Type \"" + type + "\" not found");
		}
		queryPart.addType(eClass, objectNode.has("includeAllSubtypes") && objectNode.get("includeAllSubtypes").asBoolean());
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy