package org.oliot.epcis.service.query.mongodb;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.bson.BsonArray;
import org.bson.BsonBoolean;
import org.bson.BsonDateTime;
import org.bson.BsonDocument;
import org.bson.BsonDouble;
import org.bson.BsonInt32;
import org.bson.BsonInt64;
import org.bson.BsonRegularExpression;
import org.bson.BsonString;
import org.bson.BsonValue;
import org.oliot.epcis.configuration.Configuration;
import com.mongodb.client.MongoCollection;
/**
* Copyright (C) 2014-2016 Jaewook Byun
*
* This project is part of Oliot open source (http://oliot.org). Oliot EPCIS
* v1.2.x is Java Web Service complying with Electronic Product Code Information
* Service (EPCIS) v1.2.
*
* @author Jaewook Byun, Ph.D student
*
* Korea Advanced Institute of Science and Technology (KAIST)
*
* Real-time Embedded System Laboratory(RESL)
*
* bjw0829@kaist.ac.kr, bjw0829@gmail.com
*/
public class MongoQueryUtil {
static BsonDocument getNearQueryObject(String key, String paramValues) {
try {
// Prepare Query Values
String[] paramValueArr = paramValues.split(",");
if (paramValueArr.length < 2)
return null;
Double lon = Double.parseDouble(paramValueArr[0]);
Double lat = Double.parseDouble(paramValueArr[1]);
Integer min = null;
if (paramValueArr.length > 2)
min = Integer.parseInt(paramValueArr[2]);
Integer max = null;
if (paramValueArr.length > 3)
max = Integer.parseInt(paramValueArr[3]);
BsonDocument near = new BsonDocument();
BsonDocument geometry = new BsonDocument("type", new BsonString("Point"));
BsonArray coordinates = new BsonArray();
coordinates.add(new BsonDouble(lon));
coordinates.add(new BsonDouble(lat));
geometry.put("coordinates", coordinates);
near.put("$geometry", geometry);
if (min != null)
near.put("$minDistance", new BsonInt32(min));
if (max != null)
near.put("$maxDistance", new BsonInt32(max));
return new BsonDocument("any." + key, new BsonDocument("$near", near));
} catch (NumberFormatException e) {
e.printStackTrace();
return null;
}
}
static BsonDocument getFamilyQueryObject(String type, String[] fieldArr, String csv) {
BsonArray orQueries = new BsonArray();
for (String field : fieldArr) {
String[] paramValueArr = csv.split("\\|");
BsonArray subObjectList = new BsonArray();
for (int i = 0; i < paramValueArr.length; i++) {
String val = paramValueArr[i].trim();
BsonDocument dbo = new BsonDocument();
dbo.put(type, new BsonString(val));
subObjectList.add(dbo);
}
if (subObjectList.isEmpty() == false) {
BsonDocument query = new BsonDocument();
query.put(field, new BsonDocument("$in", subObjectList));
orQueries.add(query);
}
}
if (orQueries.size() != 0) {
BsonDocument queryObject = new BsonDocument();
queryObject.put("$or", orQueries);
return queryObject;
} else {
return null;
}
}
static BsonArray getWDParamBsonArray(String csv) {
BsonArray paramArray = new BsonArray();
String[] paramValueArr = csv.split("\\|");
for (String paramValue : paramValueArr) {
String param = paramValue.trim();
if (param.split("\\|").length == 1 && param.split("\\^").length == 2
&& param.split("\\^")[1].trim().equals("regex")) {
String regex = param.split("\\^")[0].trim();
BsonRegularExpression regexValue = new BsonRegularExpression("^" + regex + "$");
paramArray.add(regexValue);
} else {
paramArray.add(new BsonString(param));
}
}
MongoCollection<BsonDocument> collection = Configuration.mongoDatabase.getCollection("MasterData",
BsonDocument.class);
Iterator<BsonValue> paramIterator = paramArray.iterator();
Set<BsonValue> childParamSet = new HashSet<BsonValue>();
while (paramIterator.hasNext()) {
BsonValue param = paramIterator.next();
BsonDocument vocObject = null;
if (param instanceof BsonRegularExpression) {
BsonRegularExpression regexParam = param.asRegularExpression();
vocObject = collection.find(new BsonDocument("id", regexParam)).first();
} else {
BsonString stringParam = param.asString();
vocObject = collection.find(new BsonDocument("id", stringParam)).first();
}
if (vocObject != null) {
BsonArray childObject = vocObject.get("children").asArray();
Iterator<BsonValue> childIterator = childObject.iterator();
while (childIterator.hasNext()) {
BsonString child = childIterator.next().asString();
childParamSet.add(child);
}
}
}
Iterator<BsonValue> childParamIterator = childParamSet.iterator();
while (childParamIterator.hasNext()) {
paramArray.add(childParamIterator.next().asString());
}
return paramArray;
}
static BsonArray getParamBsonArray(String csv) {
BsonArray paramArray = new BsonArray();
String[] paramValueArr = csv.split("\\|");
for (String paramValue : paramValueArr) {
String param = paramValue.trim();
paramArray.add(converseType(param));
}
return paramArray;
}
static BsonValue converseType(String value) {
String[] valArr = value.split("\\^");
if (valArr.length != 2) {
return new BsonString(value);
}
try {
String type = valArr[1].trim();
if (type.equals("int")) {
return new BsonInt32(Integer.parseInt(valArr[0]));
} else if (type.equals("long")) {
return new BsonInt64(Long.parseLong(valArr[0]));
} else if (type.equals("double")) {
return new BsonDouble(Double.parseDouble(valArr[0]));
} else if (type.equals("boolean")) {
return new BsonBoolean(Boolean.parseBoolean(valArr[0]));
} else if (type.equals("regex")) {
return new BsonRegularExpression("^" + valArr[0] + "$");
} else if (type.equals("float")) {
return new BsonDouble(Double.parseDouble(valArr[0]));
} else if (type.equals("dateTime")) {
BsonDateTime time = MongoQueryService.getTimeMillis(valArr[0]);
if (time != null)
return time;
return new BsonString(value);
} else {
return new BsonString(value);
}
} catch (NumberFormatException e) {
return new BsonString(value);
}
}
static BsonDocument getMatchQueryObject(String[] fieldArr, BsonArray paramArray) {
BsonArray orQueries = new BsonArray();
for (String field : fieldArr) {
Iterator<BsonValue> paramIterator = paramArray.iterator();
// BsonArray pureStringParamArray = new BsonArray();
while (paramIterator.hasNext()) {
BsonValue param = paramIterator.next();
if (param instanceof BsonRegularExpression) {
BsonDocument regexQuery = new BsonDocument(field, new BsonDocument("$regex", param));
orQueries.add(regexQuery);
} else {
String value = param.asString().getValue();
value = value.replace(".", "[.]");
value = value.replace("*", "(.)*");
BsonRegularExpression expr = new BsonRegularExpression(value);
BsonDocument regexQuery = new BsonDocument(field, new BsonDocument("$regex", expr));
orQueries.add(regexQuery);
}
}
/*
* if (pureStringParamArray.size() != 0) { BsonDocument
* stringInQueries = new BsonDocument(field, new BsonDocument("$in",
* pureStringParamArray)); orQueries.add(stringInQueries); }
*/
}
if (orQueries.size() != 0) {
BsonDocument queryObject = new BsonDocument();
queryObject.put("$or", orQueries);
return queryObject;
} else {
return null;
}
}
static BsonDocument getQueryObject(String[] fieldArr, BsonArray paramArray) {
BsonArray orQueries = new BsonArray();
for (String field : fieldArr) {
Iterator<BsonValue> paramIterator = paramArray.iterator();
BsonArray pureStringParamArray = new BsonArray();
while (paramIterator.hasNext()) {
BsonValue param = paramIterator.next();
if (param instanceof BsonRegularExpression) {
BsonDocument regexQuery = new BsonDocument(field, new BsonDocument("$regex", param));
orQueries.add(regexQuery);
} else {
pureStringParamArray.add(param);
}
}
if (pureStringParamArray.size() != 0) {
BsonDocument stringInQueries = new BsonDocument(field, new BsonDocument("$in", pureStringParamArray));
orQueries.add(stringInQueries);
}
}
if (orQueries.size() != 0) {
BsonDocument queryObject = new BsonDocument();
queryObject.put("$or", orQueries);
return queryObject;
} else {
return null;
}
}
static BsonDocument getCompExtensionQueryObject(String type, String[] fields, String value, String comp) {
if (comp.equals("GT")) {
BsonArray subList = new BsonArray();
for (int i = 0; i < fields.length; i++) {
BsonDocument sub = new BsonDocument();
sub.put(fields[i], new BsonDocument("$gt", converseType(value)));
subList.add(sub);
}
BsonDocument subBase = new BsonDocument();
subBase.put("$or", subList);
return subBase;
} else if (comp.equals("GE")) {
BsonArray subList = new BsonArray();
for (int i = 0; i < fields.length; i++) {
BsonDocument sub = new BsonDocument();
sub.put(fields[i], new BsonDocument("$gte", converseType(value)));
subList.add(sub);
}
BsonDocument subBase = new BsonDocument();
subBase.put("$or", subList);
return subBase;
} else if (comp.equals("LT")) {
BsonArray subList = new BsonArray();
for (int i = 0; i < fields.length; i++) {
BsonDocument sub = new BsonDocument();
sub.put(fields[i], new BsonDocument("$lt", converseType(value)));
subList.add(sub);
}
BsonDocument subBase = new BsonDocument();
subBase.put("$or", subList);
return subBase;
} else if (comp.equals("LE")) {
BsonArray subList = new BsonArray();
for (int i = 0; i < fields.length; i++) {
BsonDocument sub = new BsonDocument();
sub.put(fields[i], new BsonDocument("$lte", converseType(value)));
subList.add(sub);
}
BsonDocument subBase = new BsonDocument();
subBase.put("$or", subList);
return subBase;
}
return null;
}
static BsonDocument getExistsQueryObject(String field, String str, BsonBoolean isExist) {
BsonDocument query = new BsonDocument();
if (str != null) {
str = encodeMongoObjectKey(str);
query.put(field + "." + str, new BsonDocument("$exists", isExist));
} else {
query.put(field, new BsonDocument("$exists", isExist));
}
return query;
}
static BsonDocument getExistsQueryObject(String[] fieldArr, String str, BsonBoolean isExist) {
BsonArray conjQueries = new BsonArray();
for (String field : fieldArr) {
BsonDocument query = new BsonDocument();
if (str != null) {
str = encodeMongoObjectKey(str);
query.put(field + "." + str, new BsonDocument("$exists", isExist));
} else {
query.put(field, new BsonDocument("$exists", isExist));
}
conjQueries.add(query);
}
if (conjQueries.size() != 0) {
BsonDocument queryObject = new BsonDocument();
if (isExist.equals(BsonBoolean.TRUE))
queryObject.put("$or", conjQueries);
else {
queryObject.put("$and", conjQueries);
}
return queryObject;
} else {
return null;
}
}
static String encodeMongoObjectKey(String key) {
key = key.replace(".", "\uff0e");
return key;
}
static String decodeMongoObjectKey(String key) {
key = key.replace("\uff0e", ".");
return key;
}
}