/************************************************************************
* Copyright (c) 2014-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.query.values;
import iot.jcypher.query.values.FunctionCapsule.FunctionEnd;
import iot.jcypher.query.values.FunctionCapsule.FunctionStart;
import iot.jcypher.query.values.operators.OPERATOR;
import iot.jcypher.query.values.operators.OPTYPE;
import iot.jcypher.query.writer.WriterContext;
import iot.jcypher.query.writer.CypherWriter.PrimitiveCypherWriter;
import java.util.ArrayList;
import java.util.List;
public class ValueWriter {
public static void toValueExpression(ValueElement valueElem, WriterContext context, StringBuilder sb) {
List<IFragment> elementList = new ArrayList<IFragment>();
int insertIndex = 0;
ValueElement ve = valueElem;
List<FunctionStackEntry> functionStack = new ArrayList<FunctionStackEntry>();
while (ve != null) {
if (ve.getOperatorOrFunction() instanceof FunctionInstance) {
FunctionInstance fi = (FunctionInstance)ve.getOperatorOrFunction();
FunctionStart start = new FunctionCapsule.FunctionStart(fi.getFunction().getPrefix());
FunctionEnd end = new FunctionCapsule.FunctionEnd(fi.getFunction().getPostfix());
functionStack.add(0, new FunctionStackEntry(fi, start));
elementList.add(insertIndex, end);
elementList.add(insertIndex, start);
insertIndex++;
}
elementList.add(insertIndex, ve);
if (ve.getOperatorOrFunction() instanceof Operator) {
if ((Operator)ve.getOperatorOrFunction() == OPERATOR.Common.COMMA_SEPARATOR) {
FunctionStackEntry outmost = null;
while (functionStack.size() > 0) {
FunctionStackEntry fe = functionStack.get(0);
fe.remainingNumArgs--;
if (fe.remainingNumArgs > 0)
break;
outmost = fe;
functionStack.remove(0);
insertIndex--;
}
if (outmost != null) {
outmost.functionStart.setOperator((Operator)ve.getOperatorOrFunction());
ve.setOperatorOrFunction(null);
}
}
}
ve = ve.getPredecessor();
}
int idx = 0;
for (IFragment ifrag : elementList) {
toValueExpression(ifrag, idx, context, sb);
idx++;
}
}
private static void toValueExpression(IFragment ifragment, int index, WriterContext context, StringBuilder sb) {
if (ifragment instanceof ValueElement) {
boolean writeAsValue = true;
ValueElement valueElem = (ValueElement)ifragment;
IOperatorOrFunction opf = valueElem.getOperatorOrFunction();
if (opf instanceof Operator) {
sb.append(((Operator)opf).getPrettySymbol());
// the value represents a property name
if (((Operator)opf).getType() == OPTYPE.PropertyContainer.PROPERTY_ACCESS)
writeAsValue = false;
// the value represents a label
else if (((Operator)opf).getType() == OPTYPE.Node.LABEL_ACCESS)
writeAsValue = false;
Object opVal;
if (((Operator)opf).getPostfixSymbol() != null && (opVal = valueElem.getHint(ValueAccess.hintKey_opValue)) != null) {
if (opVal instanceof ValueElement)
toValueExpression((ValueElement)opVal, context, sb);
else
PrimitiveCypherWriter.writePrimitiveValue(opVal, context, sb);
sb.append(((Operator)opf).getPostfixSymbol());
}
}
boolean nameWritten = false;
if (valueElem instanceof JcValue) {
if (((JcValue)valueElem).getName() != null) {
// exception for JcString and JcNumber having name and value set
if (!((valueElem instanceof JcString || valueElem instanceof JcNumber) &&
((JcPrimitive)valueElem).getValue() != null)) {
sb.append(((JcValue)valueElem).getName());
nameWritten = true;
}
}
}
Object listVal = null;
if (!nameWritten && valueElem instanceof JcCollection)
listVal = ((JcCollection)valueElem).getValue();
if ((valueElem instanceof JcPrimitive || listVal != null) && !nameWritten) {
Object val = listVal != null ? listVal : ((JcPrimitive)valueElem).getValue();
if (val instanceof ValueElement) {
toValueExpression((ValueElement)val, context, sb);
} else if (val != null) {
if (writeAsValue)
PrimitiveCypherWriter.writePrimitiveValue(val, context, sb);
else
sb.append(val.toString());
}
}
} else if (ifragment instanceof FunctionCapsule) {
if (ifragment instanceof FunctionStart) {
Operator op = ((FunctionStart)ifragment).getOperator();
if (op != null)
sb.append(op.getPrettySymbol());
}
sb.append(((FunctionCapsule)ifragment).getToken());
}
}
/**************************************/
private static class FunctionStackEntry {
private FunctionStart functionStart;
private int remainingNumArgs;
FunctionStackEntry(FunctionInstance functionInstance, FunctionStart functionStart) {
super();
this.functionStart = functionStart;
this.remainingNumArgs = functionInstance.getNumArgs();
}
}
}