/*
* Copyright 2013, TopicQuests
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
*/
package org.topicquests.topicmap.json.model;
import java.util.*;
import net.minidev.json.JSONObject;
//import net.minidev.json.parser.JSONParser;
//import org.json.simple.JSONObject;
//import org.json.simple.parser.JSONParser;
import org.topicquests.common.ResultPojo;
import org.topicquests.common.api.IResult;
import org.topicquests.common.api.ITopicQuestsOntology;
import org.topicquests.model.Compare;
import org.topicquests.model.api.node.INode;
import org.topicquests.model.api.query.INodeQuery;
import org.topicquests.model.api.IPredicate;
import org.topicquests.model.api.node.ITuple;
import org.topicquests.model.api.query.ITupleQuery;
import org.topicquests.model.api.ITicket;
import org.topicquests.persist.json.api.IJSONDocStoreModel;
import org.topicquests.topicmap.json.model.api.IJSONTopicDataProvider;
//import org.topicquests.topicmap.json.model.api.IJSONTopicMapOntology;
import org.topicquests.util.LoggingPlatform;
import org.topicquests.model.Node;
/**
* @author park
*
*/
public class NodeQuery implements INodeQuery {
private LoggingPlatform log = LoggingPlatform.getLiveInstance();
private IJSONTopicDataProvider database;
// private IJSONDocStoreModel jsonModel;
private INode me;
public List<HasContainer> hasContainers = new ArrayList<HasContainer>();
private List<JSONObject>foundTuples = null;
private List<ITuple>filteredTuples = null;
private List<INode>filteredNodes = null;
private boolean isFiltered = false;
// private JSONParser parser;
private ITupleQuery tupleQuery;
/**
*
* @param n
* @param dp
* @param m
*/
public NodeQuery(INode n, IJSONTopicDataProvider dp, IJSONDocStoreModel m) {
me = n;
// jsonModel = m;
this.database = dp;
tupleQuery = database.getTupleQuery();
// parser = new JSONParser();
}
/* (non-Javadoc)
* @see org.topicquests.topicmap.json.model.api.INodeQuery#tuples(java.util.Set)
*/
@Override
public IResult tuples(ITicket credentials) {
IResult result = new ResultPojo();
if (!isFiltered) {
IResult r = executeQuery(credentials);
if (r.hasError())
result.addErrorString(r.getErrorString());
isFiltered = true;
}
result.setResultObject(filteredTuples);
return result;
}
/* (non-Javadoc)
* @see org.topicquests.topicmap.json.model.api.INodeQuery#nodes(java.util.Set)
*/
@Override
public IResult nodes(ITicket credentials) {
IResult result = new ResultPojo();
if (!isFiltered) {
IResult r = executeQuery(credentials);
if (r.hasError())
result.addErrorString(r.getErrorString());
isFiltered = true;
}
if (filteredTuples != null && !filteredTuples.isEmpty()) {
ITuple t;
IResult r;
filteredNodes = new ArrayList<INode>();
result.setResultObject(filteredNodes);
Iterator<ITuple>itr = filteredTuples.iterator();
String lox;
while (itr.hasNext()) {
t = itr.next();
if (!t.getSubjectLocator().equals(me.getLocator()))
lox = t.getSubjectLocator();
else
lox = t.getObject();
r = database.getNode(lox, credentials);
if (r.hasError())
result.addErrorString(r.getErrorString());
if (r.getResultObject() != null)
filteredNodes.add((INode)r.getResultObject());
else
result.addErrorString("NodeQuery missing node for "+lox);
}
}
return result;
}
/* (non-Javadoc)
* @see org.topicquests.topicmap.json.model.api.INodeQuery#setRelationType(java.lang.String, java.util.Set)
*/
@Override
public INodeQuery setRelationType(String relationType,
int start, int count, ITicket credentials) {
//clear everything
foundTuples = null;
filteredTuples = null;
filteredNodes = null;
hasContainers.clear();
isFiltered = false;
//TODO: wrong query
//We must work off what we already have in this topic
//This topic might be either the subject or object of its tuples of the given relationType
IResult r = tupleQuery.listTuplesByPredTypeAndObjectOrSubject(relationType, this.me.getLocator(), start, count, credentials);
if (r.getResultObject() != null)
foundTuples = (List<JSONObject>)r.getResultObject();
return this;
}
/* (non-Javadoc)
* @see org.topicquests.model.api.INodeQuery#count()
*/
@Override
public long count() {
//cardinality of this node's tuples as filtered by labels
if (foundTuples != null)
return (long)foundTuples.size();
return 0;
}
/* (non-Javadoc)
* @see org.topicquests.topicmap.json.model.api.INodeQuery#nodeLocators(java.util.Set)
*/
@Override
public IResult nodeLocators(ITicket credentials) {
IResult result = new ResultPojo();
if (foundTuples == null)
result.addErrorString("No tuples found in this query");
//that error means that somebody didn't setLabels
else {
List<String>lox = new ArrayList<String>();
result.setResultObject(lox);
IResult r;
//here, we must fetch every tuple and get its subject or object
JSONObject t;
Iterator<JSONObject>itr = foundTuples.iterator();
while(itr.hasNext()) {
t = itr.next();
lox.add((String)t.get(ITopicQuestsOntology.LOCATOR_PROPERTY));
}
}
return result;
}
/* (non-Javadoc)
* @see org.topicquests.topicmap.json.model.api.INodeQuery#has(java.lang.String, java.lang.Object)
*/
@Override
public INodeQuery tupleHas(String key, Object value) {
this.hasContainers.add(new HasContainer(key, Compare.EQUAL, value));
return this;
}
/* (non-Javadoc)
* @see org.topicquests.topicmap.json.model.api.INodeQuery#hasNot(java.lang.String, java.lang.Object)
*/
@Override
public INodeQuery tupleHasNot(String key, Object value) {
this.hasContainers.add(new HasContainer(key, Compare.NOT_EQUAL, value));
return this;
}
/* (non-Javadoc)
* @see org.topicquests.topicmap.json.model.api.INodeQuery#has(java.lang.String, org.topicquests.model.api.IPredicate, java.lang.Object)
*/
@Override
public INodeQuery tupleHas(String key, IPredicate predicate, Object value) {
this.hasContainers.add(new HasContainer(key, predicate, value));
return this;
}
/* (non-Javadoc)
* @see org.topicquests.topicmap.json.model.api.INodeQuery#has(java.lang.String)
*/
@Override
public INodeQuery tupleHas(String key) {
this.hasContainers.add(new HasContainer(key, Compare.NOT_EQUAL, null));
return this;
}
/* (non-Javadoc)
* @see org.topicquests.topicmap.json.model.api.INodeQuery#hasNot(java.lang.String)
*/
@Override
public INodeQuery tupleHasNot(String key) {
this.hasContainers.add(new HasContainer(key, Compare.EQUAL, null));
return this;
}
private IResult executeQuery(ITicket credentials) {
IResult result = new ResultPojo();
filteredTuples = new ArrayList<ITuple>();
if (foundTuples != null && !foundTuples.isEmpty()) {
filteredTuples = new ArrayList<ITuple>();
Iterator<JSONObject>itr = foundTuples.iterator();
ITuple t;
JSONObject jo;
if (hasContainers.isEmpty()) {
while(itr.hasNext()) {
jo = itr.next();
t = new Node(jo);
filteredTuples.add(t);
}
} else {
HasContainer x;
Iterator<HasContainer>itx;
while (itr.hasNext()) {
jo = itr.next();
t = new Node(jo);
itx = hasContainers.iterator();
while (itx.hasNext()) {
x = itx.next();
if (x.isLegal(t))
filteredTuples.add(t);
}
}
}
}
return result;
}
////////////////////
protected class HasContainer {
public String key;
public Object value;
public IPredicate predicate;
public HasContainer(final String key, final IPredicate predicate, final Object value) {
this.key = key;
this.value = value;
this.predicate = predicate;
}
public boolean isLegal(final INode element) {
return this.predicate.evaluate(element.getProperty(this.key), this.value);
}
}
}