/************************************************************************
* Copyright (c) 2016 IoT-Solutions e.U.
*
* 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 iot.jcypher.domainquery;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import iot.jcypher.database.IDBAccess;
import iot.jcypher.domain.internal.IIntDomainAccess;
import iot.jcypher.domainquery.api.APIAccess;
import iot.jcypher.domainquery.api.DomainObjectMatch;
import iot.jcypher.domainquery.internal.JSONConverter;
import iot.jcypher.domainquery.internal.QueryRecorder;
import iot.jcypher.domainquery.internal.RecordedQuery;
import iot.jcypher.query.JcQuery;
import iot.jcypher.query.JcQueryResult;
import iot.jcypher.query.api.IClause;
import iot.jcypher.query.factories.clause.DO;
import iot.jcypher.query.factories.clause.MERGE;
import iot.jcypher.query.values.JcNode;
import iot.jcypher.query.writer.Format;
import iot.jcypher.util.Util;
public class QueryPersistor {
public static final String Q_LABEL_POSTFIX = "_query";
public static final String PROP_NAME = "name";
static final String PROP_Q_JSON = "queryJSON";
static final String PROP_Q_JAVA = "queryJava";
private AbstractDomainQuery query;
private Object domainAccess; // can be IDomainAccess or IGenericDomainAccess
private Map<DomainObjectMatch<?>, String> augmentations;
private Format prettyFormat;
QueryPersistor(AbstractDomainQuery query, Object domAccess) {
this.query = query;
this.domainAccess = domAccess;
this.prettyFormat = Format.NONE;
}
/**
* The memento contains a JSON representation of the query as well as a Java-DSL like string representation.
* @return
*/
public QueryMemento createMemento() {
RecordedQuery rq = this.query.getRecordedQuery();
if (this.augmentations != null) {
Map<Object, String> domMap = InternalAccess.getRecordedQueryObjects(this.query);
Map<String, String> augments = new HashMap<String, String>();
Iterator<Entry<DomainObjectMatch<?>, String>> it = this.augmentations.entrySet().iterator();
while(it.hasNext()) {
Entry<DomainObjectMatch<?>, String> entry = it.next();
DomainObjectMatch<?> dom = entry.getKey();
DomainObjectMatch<?> delegate = APIAccess.getDelegate(dom);
if (delegate != null)
dom = delegate;
augments.put(domMap.get(dom), entry.getValue());
}
rq.setAugmentations(augments);
}
QueryMemento ret = new QueryMemento(rq.toString(), new JSONConverter().setPrettyFormat(this.prettyFormat).toJSON(rq));
return ret;
}
/**
* Store the query with the domain model under the given name.
* @param queryName
*/
public void storeAs(String queryName) {
QueryRecorder.queryCompleted(this.query);
QueryMemento qm = this.createMemento();
IDBAccess dbAccess = ((IIntDomainAccess)this.domainAccess).getInternalDomainAccess().getDBAccess();
String qLabel = ((IIntDomainAccess)this.domainAccess).getInternalDomainAccess().getDomainLabel()
.concat(Q_LABEL_POSTFIX);
JcNode n = new JcNode("n");
IClause[] clauses = new IClause[] {
MERGE.node(n).label(qLabel).property(PROP_NAME).value(queryName),
DO.SET(n.property(PROP_Q_JAVA)).to(qm.getQueryJava()),
DO.SET(n.property(PROP_Q_JSON)).to(qm.getQueryJSON())
};
JcQuery q = new JcQuery();
q.setClauses(clauses);
JcQueryResult result = dbAccess.execute(q);
if (result.hasErrors()) {
StringBuilder sb = new StringBuilder();
Util.appendErrorList(Util.collectErrors(result), sb);
throw new RuntimeException(sb.toString());
}
return;
}
/**
* Give a name to a DomainObjectMatch for better readability in a Java-DSL like string representation
* @param domainObjectMatch
* @param as
* @return
*/
public QueryPersistor augment(DomainObjectMatch<?> domainObjectMatch, String as) {
if (this.augmentations == null)
this.augmentations = new HashMap<DomainObjectMatch<?>, String>();
this.augmentations.put(domainObjectMatch, as);
return this;
}
/**
* Support for pretty printing the JSON representation
* @param prettyFormat
* @return
*/
public QueryPersistor setPrettyFormat(Format prettyFormat) {
this.prettyFormat = prettyFormat;
return this;
}
}