package com.redhat.lightblue.assoc;
import java.util.List;
import org.junit.Test;
import org.junit.Assert;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.redhat.lightblue.util.Path;
import com.redhat.lightblue.util.JsonUtils;
import com.redhat.lightblue.query.*;
import com.redhat.lightblue.metadata.CompositeMetadata;
import com.redhat.lightblue.metadata.AbstractGetMetadata;
import com.redhat.lightblue.metadata.EntityMetadata;
import com.redhat.lightblue.metadata.TypeResolver;
import com.redhat.lightblue.metadata.PredefinedFields;
import com.redhat.lightblue.metadata.types.DefaultTypes;
import com.redhat.lightblue.metadata.parser.Extensions;
import com.redhat.lightblue.metadata.parser.JSONMetadataParser;
import com.redhat.lightblue.TestDataStoreParser;
import com.redhat.lightblue.util.test.AbstractJsonNodeTest;
public class AnalyzeQueryTest extends AbstractJsonNodeTest {
private class GMD extends AbstractGetMetadata {
public GMD(Projection p, QueryExpression q) {
super(p, q);
}
@Override
protected EntityMetadata retrieveMetadata(Path injectionField,
String entityName,
String version) {
try {
return getMd("composite/" + entityName + ".json");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private EntityMetadata getMd(String fname) {
try {
JsonNode node = loadJsonNode(fname);
Extensions<JsonNode> extensions = new Extensions<>();
extensions.addDefaultExtensions();
extensions.registerDataStoreParser("mongo", new TestDataStoreParser<JsonNode>());
TypeResolver resolver = new DefaultTypes();
JSONMetadataParser parser = new JSONMetadataParser(extensions, resolver, JsonNodeFactory.instance);
EntityMetadata md = parser.parseEntityMetadata(node);
PredefinedFields.ensurePredefinedFields(md);
return md;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private QueryExpression query(String s) throws Exception {
return QueryExpression.fromJson(JsonUtils.json(s.replace('\'', '\"')));
}
private Projection projection(String s) throws Exception {
return Projection.fromJson(JsonUtils.json(s.replace('\'', '\"')));
}
@Test
public void testReqQueryInfo() throws Exception {
GMD gmd = new GMD(projection("{'field':'obj1.c','include':1}"), null);
CompositeMetadata md = CompositeMetadata.buildCompositeMetadata(getMd("composite/A.json"), gmd);
// Process request query at root
AnalyzeQuery pq = new AnalyzeQuery(md, null);
QueryExpression q = query("{'$and':[ { 'field':'field1','op':'=','rvalue':'x'},{'field':'obj1.c.*.field1','op':'=','rvalue':'y'}]}");
pq.iterate(q);
List<QueryFieldInfo> list = pq.getFieldInfo();
Assert.assertEquals(new Path("field1"), list.get(0).getFieldNameInClause());
Assert.assertEquals(new Path("field1"), list.get(0).getFullFieldName());
Assert.assertTrue(md.resolve(new Path("field1")) == list.get(0).getFieldMd());
Assert.assertTrue(md == list.get(0).getFieldEntity());
Assert.assertEquals(new Path("field1"), list.get(0).getEntityRelativeFieldName());
Assert.assertEquals(new Path("obj1.c.*.field1"), list.get(1).getFieldNameInClause());
Assert.assertEquals(new Path("obj1.c.*.field1"), list.get(1).getFullFieldName());
Assert.assertTrue(md.resolve(new Path("obj1.c.*.field1")) == list.get(1).getFieldMd());
Assert.assertTrue(md.getChildMetadata(new Path("obj1.c")) == list.get(1).getFieldEntity());
Assert.assertEquals(new Path("field1"), list.get(1).getEntityRelativeFieldName());
}
@Test
public void testAssocQueryInfo() throws Exception {
GMD gmd = new GMD(projection("{'field':'obj1.c','include':1}"), null);
CompositeMetadata md = CompositeMetadata.buildCompositeMetadata(getMd("composite/A.json"), gmd);
// Process query at root
AnalyzeQuery pq = new AnalyzeQuery(md, md.getResolvedReferenceOfField(new Path("obj1.c")));
QueryExpression q = query("{'field':'_id','op':'$eq','rfield':'$parent.c_ref'}");
pq.iterate(q);
List<QueryFieldInfo> list = pq.getFieldInfo();
Assert.assertEquals(new Path("_id"), list.get(0).getFieldNameInClause());
Assert.assertEquals(new Path("_id"), list.get(0).getFullFieldName());
Assert.assertTrue(md.resolve(new Path("obj1.c.*._id")) == list.get(0).getFieldMd());
Assert.assertTrue(md.getChildMetadata(new Path("obj1.c")) == list.get(0).getFieldEntity());
Assert.assertEquals(new Path("_id"), list.get(0).getEntityRelativeFieldName());
Assert.assertEquals(new Path("$parent.c_ref"), list.get(1).getFieldNameInClause());
Assert.assertEquals(new Path("$parent.c_ref"), list.get(1).getFullFieldName());
Assert.assertTrue(md.resolve(new Path("obj1.c_ref")) == list.get(1).getFieldMd());
Assert.assertTrue(md == list.get(1).getFieldEntity());
Assert.assertEquals(new Path("obj1.c_ref"), list.get(1).getEntityRelativeFieldName());
}
@Test
public void testAssocQueryInfo_secondNode() throws Exception {
GMD gmd = new GMD(projection("{'field':'obj1.c','include':1}"), null);
CompositeMetadata md = CompositeMetadata.buildCompositeMetadata(getMd("composite/A.json"), gmd);
// Process query at root
AnalyzeQuery pq = new AnalyzeQuery(md, md.getResolvedReferenceOfField(new Path("obj1.c")));
QueryExpression q = query("{'field':'_id','op':'$eq','rfield':'$parent.c_ref'}");
pq.iterate(q);
List<QueryFieldInfo> list = pq.getFieldInfo();
Assert.assertEquals(new Path("_id"), list.get(0).getFieldNameInClause());
Assert.assertEquals(new Path("_id"), list.get(0).getFullFieldName());
Assert.assertTrue(md.resolve(new Path("obj1.c.*._id")) == list.get(0).getFieldMd());
Assert.assertTrue(md.getChildMetadata(new Path("obj1.c")) == list.get(0).getFieldEntity());
Assert.assertEquals(new Path("_id"), list.get(0).getEntityRelativeFieldName());
Assert.assertEquals(new Path("$parent.c_ref"), list.get(1).getFieldNameInClause());
Assert.assertEquals(new Path("$parent.c_ref"), list.get(1).getFullFieldName());
Assert.assertTrue(md.resolve(new Path("obj1.c_ref")) == list.get(1).getFieldMd());
Assert.assertTrue(md == list.get(1).getFieldEntity());
Assert.assertEquals(new Path("obj1.c_ref"), list.get(1).getEntityRelativeFieldName());
}
@Test
public void testReqQueryInfo_forEach() throws Exception {
GMD gmd = new GMD(projection("{'field':'obj1.c','include':1}"), null);
CompositeMetadata md = CompositeMetadata.buildCompositeMetadata(getMd("composite/A.json"), gmd);
// Process query at root
AnalyzeQuery pq = new AnalyzeQuery(md, null);
QueryExpression q = query("{'array' : 'obj1.c', 'elemMatch':{'field':'_id','op':'$eq','rfield':'$parent.c_ref'}}");
pq.iterate(q);
List<QueryFieldInfo> list = pq.getFieldInfo();
Assert.assertEquals(new Path("_id"), list.get(1).getFieldNameInClause());
Assert.assertEquals(new Path("obj1.c.*._id"), list.get(1).getFullFieldName());
Assert.assertTrue(md.resolve(new Path("obj1.c.*._id")) == list.get(1).getFieldMd());
Assert.assertTrue(md.getChildMetadata(new Path("obj1.c")) == list.get(1).getFieldEntity());
Assert.assertEquals(new Path("_id"), list.get(1).getEntityRelativeFieldName());
Assert.assertEquals(new Path("$parent.c_ref"), list.get(2).getFieldNameInClause());
Assert.assertEquals(new Path("obj1.c.*.$parent.c_ref"), list.get(2).getFullFieldName());
Assert.assertTrue(md.resolve(new Path("obj1.c_ref")) == list.get(2).getFieldMd());
Assert.assertTrue(md == list.get(2).getFieldEntity());
Assert.assertEquals(new Path("obj1.c_ref"), list.get(2).getEntityRelativeFieldName());
}
@Test
public void testNestedElemMatch() throws Exception {
GMD gmd = new GMD(projection("{'field':'us','include':1}"), null);
CompositeMetadata md = CompositeMetadata.buildCompositeMetadata(getMd("composite/L.json"), gmd);
// Process query at root
AnalyzeQuery pq = new AnalyzeQuery(md, null);
QueryExpression q = query("{'array':'us','elemMatch':{'array':'authentications','elemMatch':{ '$and':[ { 'field':'principal','op':'$in','values':['a']}, {'field':'providerName','op':'$eq','rvalue':'p'} ] } }}");
pq.iterate(q);
List<QueryFieldInfo> list = pq.getFieldInfo();
System.out.println(list);
Assert.assertEquals(new Path("us"), list.get(0).getFullFieldName());
Assert.assertEquals(new Path("us"), list.get(0).getEntityRelativeFieldNameWithContext());
Assert.assertFalse(list.get(0).isLeaf());
Assert.assertEquals(new Path("us.*.authentications"), list.get(1).getFullFieldName());
Assert.assertEquals(new Path("authentications"), list.get(1).getEntityRelativeFieldNameWithContext());
Assert.assertFalse(list.get(1).isLeaf());
Assert.assertEquals(new Path("us.*.authentications.*.principal"), list.get(2).getFullFieldName());
Assert.assertEquals(new Path("authentications.*.principal"), list.get(2).getEntityRelativeFieldNameWithContext());
Assert.assertTrue(list.get(2).isLeaf());
Assert.assertEquals(new Path("us.*.authentications.*.providerName"), list.get(3).getFullFieldName());
Assert.assertEquals(new Path("authentications.*.providerName"), list.get(3).getEntityRelativeFieldNameWithContext());
Assert.assertTrue(list.get(3).isLeaf());
}
}