use of com.orientechnologies.orient.core.sql.method.OSQLMethod in project orientdb by orientechnologies.
the class ODocumentHelper method getFieldValue.
@SuppressWarnings("unchecked")
public static <RET> RET getFieldValue(Object value, final String iFieldName, final OCommandContext iContext) {
if (value == null)
return null;
final int fieldNameLength = iFieldName.length();
if (fieldNameLength == 0)
return (RET) value;
OIdentifiable currentRecord = value instanceof OIdentifiable ? (OIdentifiable) value : null;
int beginPos = iFieldName.charAt(0) == '.' ? 1 : 0;
int nextSeparatorPos = iFieldName.charAt(0) == '.' ? 1 : 0;
boolean firstInChain = true;
do {
char nextSeparator = ' ';
for (; nextSeparatorPos < fieldNameLength; ++nextSeparatorPos) {
nextSeparator = iFieldName.charAt(nextSeparatorPos);
if (nextSeparator == '.' || nextSeparator == '[')
break;
}
final String fieldName;
if (nextSeparatorPos < fieldNameLength)
fieldName = iFieldName.substring(beginPos, nextSeparatorPos);
else {
nextSeparator = ' ';
if (beginPos > 0)
fieldName = iFieldName.substring(beginPos);
else
fieldName = iFieldName;
}
if (nextSeparator == '[') {
if (fieldName != null && fieldName.length() > 0) {
if (currentRecord != null)
value = getIdentifiableValue(currentRecord, fieldName);
else if (value instanceof Map<?, ?>)
value = getMapEntry((Map<String, ?>) value, fieldName);
else if (OMultiValue.isMultiValue(value)) {
final HashSet<Object> temp = new LinkedHashSet<Object>();
for (Object o : OMultiValue.getMultiValueIterable(value, false)) {
if (o instanceof OIdentifiable) {
Object r = getFieldValue(o, iFieldName);
if (r != null)
OMultiValue.add(temp, r);
}
}
value = temp;
}
}
if (value == null)
return null;
else if (value instanceof OIdentifiable)
currentRecord = (OIdentifiable) value;
// final int end = iFieldName.indexOf(']', nextSeparatorPos);
final int end = findClosingBracketPosition(iFieldName, nextSeparatorPos);
if (end == -1)
throw new IllegalArgumentException("Missed closed ']'");
String indexPart = iFieldName.substring(nextSeparatorPos + 1, end);
if (indexPart.length() == 0)
return null;
nextSeparatorPos = end;
if (value instanceof OCommandContext)
value = ((OCommandContext) value).getVariables();
if (value instanceof OIdentifiable) {
final ORecord record = currentRecord != null && currentRecord instanceof OIdentifiable ? ((OIdentifiable) currentRecord).getRecord() : null;
final boolean backtick;
if ((indexPart.startsWith("`") && indexPart.endsWith("`"))) {
indexPart = OIOUtils.getStringContent(indexPart);
backtick = true;
} else
backtick = false;
final Object index = getIndexPart(iContext, indexPart);
final String indexAsString = index != null ? index.toString() : null;
final List<String> indexParts = OStringSerializerHelper.smartSplit(indexAsString, ',', OStringSerializerHelper.DEFAULT_IGNORE_CHARS);
final List<String> indexRanges = OStringSerializerHelper.smartSplit(indexAsString, '-', ' ');
final List<String> indexCondition = OStringSerializerHelper.smartSplit(indexAsString, '=', ' ');
if (backtick || (indexParts.size() == 1 && indexCondition.size() == 1 && indexRanges.size() == 1))
// SINGLE VALUE
value = ((ODocument) record).field(indexAsString);
else if (indexParts.size() > 1) {
// MULTI VALUE
final Object[] values = new Object[indexParts.size()];
for (int i = 0; i < indexParts.size(); ++i) {
values[i] = ((ODocument) record).field(OIOUtils.getStringContent(indexParts.get(i)));
}
value = values;
} else if (indexRanges.size() > 1) {
// MULTI VALUES RANGE
String from = indexRanges.get(0);
String to = indexRanges.get(1);
final ODocument doc = (ODocument) record;
final String[] fieldNames = doc.fieldNames();
final int rangeFrom = from != null && !from.isEmpty() ? Integer.parseInt(from) : 0;
final int rangeTo = to != null && !to.isEmpty() ? Math.min(Integer.parseInt(to), fieldNames.length - 1) : fieldNames.length - 1;
final Object[] values = new Object[rangeTo - rangeFrom + 1];
for (int i = rangeFrom; i <= rangeTo; ++i) values[i - rangeFrom] = doc.field(fieldNames[i]);
value = values;
} else if (!indexCondition.isEmpty()) {
// CONDITION
final String conditionFieldName = indexCondition.get(0);
Object conditionFieldValue = ORecordSerializerStringAbstract.getTypeValue(indexCondition.get(1));
if (conditionFieldValue instanceof String)
conditionFieldValue = OIOUtils.getStringContent(conditionFieldValue);
final Object fieldValue = getFieldValue(currentRecord, conditionFieldName);
if (conditionFieldValue != null && fieldValue != null)
conditionFieldValue = OType.convert(conditionFieldValue, fieldValue.getClass());
if (fieldValue == null && !conditionFieldValue.equals("null") || fieldValue != null && !fieldValue.equals(conditionFieldValue))
value = null;
}
} else if (value instanceof Map<?, ?>) {
final boolean backtick;
if ((indexPart.startsWith("`") && indexPart.endsWith("`"))) {
indexPart = OIOUtils.getStringContent(indexPart);
backtick = true;
} else
backtick = false;
final Object index = getIndexPart(iContext, indexPart);
final String indexAsString = index != null ? index.toString() : null;
final List<String> indexParts = OStringSerializerHelper.smartSplit(indexAsString, ',', OStringSerializerHelper.DEFAULT_IGNORE_CHARS);
final List<String> indexRanges = OStringSerializerHelper.smartSplit(indexAsString, '-', ' ');
if (!allIntegers(indexRanges)) {
indexRanges.clear();
indexRanges.add(indexAsString);
}
final List<String> indexCondition = OStringSerializerHelper.smartSplit(indexAsString, '=', ' ');
final Map<String, ?> map = (Map<String, ?>) value;
if (backtick || (indexParts.size() == 1 && indexCondition.size() == 1 && indexRanges.size() == 1))
// SINGLE VALUE
value = map.get(index);
else if (indexParts.size() > 1) {
// MULTI VALUE
final Object[] values = new Object[indexParts.size()];
for (int i = 0; i < indexParts.size(); ++i) {
values[i] = map.get(OIOUtils.getStringContent(indexParts.get(i)));
}
value = values;
} else if (indexRanges.size() > 1) {
// MULTI VALUES RANGE
String from = indexRanges.get(0);
String to = indexRanges.get(1);
final List<String> fieldNames = new ArrayList<String>(map.keySet());
final int rangeFrom = from != null && !from.isEmpty() ? Integer.parseInt(from) : 0;
final int rangeTo = to != null && !to.isEmpty() ? Math.min(Integer.parseInt(to), fieldNames.size() - 1) : fieldNames.size() - 1;
final Object[] values = new Object[rangeTo - rangeFrom + 1];
for (int i = rangeFrom; i <= rangeTo; ++i) values[i - rangeFrom] = map.get(fieldNames.get(i));
value = values;
} else if (!indexCondition.isEmpty()) {
// CONDITION
final String conditionFieldName = indexCondition.get(0);
Object conditionFieldValue = ORecordSerializerStringAbstract.getTypeValue(indexCondition.get(1));
if (conditionFieldValue instanceof String)
conditionFieldValue = OIOUtils.getStringContent(conditionFieldValue);
final Object fieldValue = map.get(conditionFieldName);
if (conditionFieldValue != null && fieldValue != null)
conditionFieldValue = OType.convert(conditionFieldValue, fieldValue.getClass());
if (fieldValue == null && !conditionFieldValue.equals("null") || fieldValue != null && !fieldValue.equals(conditionFieldValue))
value = null;
}
} else if (OMultiValue.isMultiValue(value)) {
// MULTI VALUE
final Object index = getIndexPart(iContext, indexPart);
final String indexAsString = index != null ? index.toString() : null;
final List<String> indexParts = OStringSerializerHelper.smartSplit(indexAsString, ',');
final List<String> indexRanges = OStringSerializerHelper.smartSplit(indexAsString, '-');
final List<String> indexCondition = OStringSerializerHelper.smartSplit(indexAsString, '=', ' ');
if (isFieldName(indexAsString)) {
// SINGLE VALUE
if (value instanceof Map<?, ?>)
value = getMapEntry((Map<String, ?>) value, index);
else if (Character.isDigit(indexAsString.charAt(0)))
value = OMultiValue.getValue(value, Integer.parseInt(indexAsString));
else
// FILTER BY FIELD
value = getFieldValue(value, indexAsString, iContext);
} else if (isListOfNumbers(indexParts)) {
// MULTI VALUES
final Object[] values = new Object[indexParts.size()];
for (int i = 0; i < indexParts.size(); ++i) values[i] = OMultiValue.getValue(value, Integer.parseInt(indexParts.get(i)));
if (indexParts.size() > 1) {
value = values;
} else {
value = values[0];
}
} else if (isListOfNumbers(indexRanges)) {
// MULTI VALUES RANGE
String from = indexRanges.get(0);
String to = indexRanges.get(1);
final int rangeFrom = from != null && !from.isEmpty() ? Integer.parseInt(from) : 0;
final int rangeTo = to != null && !to.isEmpty() ? Math.min(Integer.parseInt(to), OMultiValue.getSize(value) - 1) : OMultiValue.getSize(value) - 1;
int arraySize = rangeTo - rangeFrom + 1;
if (arraySize < 0) {
arraySize = 0;
}
final Object[] values = new Object[arraySize];
for (int i = rangeFrom; i <= rangeTo; ++i) values[i - rangeFrom] = OMultiValue.getValue(value, i);
value = values;
} else {
// CONDITION
OSQLPredicate pred = new OSQLPredicate(indexAsString);
final HashSet<Object> values = new LinkedHashSet<Object>();
for (Object v : OMultiValue.getMultiValueIterable(value)) {
if (v instanceof OIdentifiable) {
Object result = pred.evaluate((OIdentifiable) v, (ODocument) ((OIdentifiable) v).getRecord(), iContext);
if (Boolean.TRUE.equals(result)) {
values.add(v);
}
} else if (v instanceof Map) {
ODocument doc = new ODocument().fromMap((Map<String, ? extends Object>) v);
Object result = pred.evaluate(doc, doc, iContext);
if (Boolean.TRUE.equals(result)) {
values.add(v);
}
}
}
if (values.isEmpty())
// RETURNS NULL
value = values;
else if (values.size() == 1)
// RETURNS THE SINGLE ODOCUMENT
value = values.iterator().next();
else
// RETURNS THE FILTERED COLLECTION
value = values;
}
}
} else {
if (fieldName.length() == 0) {
// NO FIELD NAME: THIS IS THE CASE OF NOT USEFUL . AFTER A ] OR .
beginPos = ++nextSeparatorPos;
continue;
}
if (fieldName.startsWith("$"))
value = iContext.getVariable(fieldName);
else if (fieldName.contains("(")) {
boolean executedMethod = false;
if (!firstInChain && fieldName.endsWith("()")) {
OSQLMethod method = OSQLEngine.getInstance().getMethod(fieldName.substring(0, fieldName.length() - 2));
if (method != null) {
value = method.execute(value, currentRecord, iContext, value, new Object[] {});
executedMethod = true;
}
}
if (!executedMethod) {
value = evaluateFunction(value, fieldName, iContext);
}
} else {
final List<String> indexCondition = OStringSerializerHelper.smartSplit(fieldName, '=', ' ');
if (indexCondition.size() == 2) {
final String conditionFieldName = indexCondition.get(0);
Object conditionFieldValue = ORecordSerializerStringAbstract.getTypeValue(indexCondition.get(1));
if (conditionFieldValue instanceof String)
conditionFieldValue = OIOUtils.getStringContent(conditionFieldValue);
value = filterItem(conditionFieldName, conditionFieldValue, value);
} else if (currentRecord != null) {
// GET THE LINKED OBJECT IF ANY
value = getIdentifiableValue(currentRecord, fieldName);
if (value != null && value instanceof ORecord && ((ORecord) value).getInternalStatus() == STATUS.NOT_LOADED)
// RELOAD IT
((ORecord) value).reload();
} else if (value instanceof Map<?, ?>)
value = getMapEntry((Map<String, ?>) value, fieldName);
else if (OMultiValue.isMultiValue(value)) {
final Set<Object> values = new LinkedHashSet<Object>();
for (Object v : OMultiValue.getMultiValueIterable(value, false)) {
final Object item;
if (v instanceof OIdentifiable)
item = getIdentifiableValue((OIdentifiable) v, fieldName);
else if (v instanceof Map)
item = ((Map<?, ?>) v).get(fieldName);
else
item = null;
if (item != null)
if (item instanceof Collection<?>)
values.addAll((Collection<? extends Object>) item);
else
values.add(item);
}
if (values.isEmpty())
value = null;
else
value = values;
} else
return null;
}
}
if (value instanceof OIdentifiable)
currentRecord = (OIdentifiable) value;
else
currentRecord = null;
beginPos = ++nextSeparatorPos;
firstInChain = false;
} while (nextSeparatorPos < fieldNameLength && value != null);
return (RET) value;
}
use of com.orientechnologies.orient.core.sql.method.OSQLMethod in project orientdb by orientechnologies.
the class OMethodCall method execute.
private Object execute(Object targetObjects, OCommandContext ctx, String name, List<OExpression> iParams, Iterable<OIdentifiable> iPossibleResults) {
List<Object> paramValues = new ArrayList<Object>();
for (OExpression expr : iParams) {
paramValues.add(expr.execute((OIdentifiable) ctx.getVariable("$current"), ctx));
}
if (graphMethods.contains(name)) {
OSQLFunction function = OSQLEngine.getInstance().getFunction(name);
if (function instanceof OSQLFunctionFiltered) {
return ((OSQLFunctionFiltered) function).execute(targetObjects, (OIdentifiable) ctx.getVariable("$current"), null, paramValues.toArray(), iPossibleResults, ctx);
} else {
return function.execute(targetObjects, (OIdentifiable) ctx.getVariable("$current"), null, paramValues.toArray(), ctx);
}
}
OSQLMethod method = OSQLEngine.getMethod(name);
if (method != null) {
return method.execute(targetObjects, (OIdentifiable) ctx.getVariable("$current"), ctx, targetObjects, paramValues.toArray());
}
throw new UnsupportedOperationException("OMethod call, something missing in the implementation...?");
}
Aggregations