/*
* Copyright 2008-2009 the original author or authors.
*
* 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 net.hasor.data.ql.dsl;
import net.hasor.core.utils.StringUtils;
import net.hasor.data.ql.dsl.domain.*;
import java.util.List;
/**
* @author 赵永春(zyc@hasor.net)
* @version : 2017-03-23
*/
class QueryModelImpl implements QueryModel {
private QueryDomain queryDomain;
public QueryModelImpl(QueryDomain queryDomain) {
this.queryDomain = queryDomain;
}
@Override
public String buildQuery() {
StringBuilder builder = new StringBuilder();
buildQuery(this.queryDomain, true, builder, 1);
return builder.toString();
}
@Override
public String buildQueryWithoutFragment() {
StringBuilder builder = new StringBuilder();
buildQuery(this.queryDomain, false, builder, 1);
return builder.toString();
}
@Override
public QueryDomain getDomain() {
return this.queryDomain;
}
//
// --------------------------------------------------------------------------------------------
private static String genDepthStr(int depth) {
return StringUtils.leftPad("", depth * 4, " ");
}
public static void buildQuery(final QueryDomain queryDomain, final boolean useFragment, final StringBuilder builder, final int depth) {
DataUDF graphUDF = queryDomain.getUDF();
if (graphUDF != null) {
builder.append(graphUDF.getName());
builder.append(" (");
List<String> paramNames = graphUDF.getParamNames();
for (int i = 0; i < paramNames.size(); i++) {
if (i != 0) {
builder.append(", ");
}
String name = paramNames.get(i);
DValue atParam = graphUDF.getParam(name);
builder.append("\"");
builder.append(name);
builder.append("\" ");
builder.append(" " + atParam.getEqType().getTypeString() + " ");
buildParam(builder, useFragment, atParam, depth);
}
builder.append(")");
}
//
if (builder.length() > 0) {
builder.append(" ");
}
//
if (ReturnType.Object == queryDomain.getReturnType()) {
builder.append("{\n");
buildFields(queryDomain, useFragment, builder, depth);
builder.append("\n" + genDepthStr(depth - 1) + "}");
} else if (ReturnType.ListObject == queryDomain.getReturnType()) {
builder.append("[\n");
{
builder.append(genDepthStr(depth) + "{\n");
buildFields(queryDomain, useFragment, builder, depth + 1);
builder.append("\n" + genDepthStr(depth) + "}");
}
builder.append("\n" + genDepthStr(depth - 1) + "]");
} else if (ReturnType.ListValue == queryDomain.getReturnType()) {
builder.append("[\n");
List<String> fieldNames = queryDomain.getFieldNames();
String fieldName = fieldNames.get(0);
builder.append(genDepthStr(depth));
buildFieldValue(null, useFragment, queryDomain.getField(fieldName), builder, depth);
builder.append("\n" + genDepthStr(depth - 1) + "]");
}
return;
}
private static void buildParam(final StringBuilder builder, final boolean useFragment, final DValue param, final int depth) {
if (param instanceof RouteValue) {
RouteValue val = (RouteValue) param;
builder.append(val.getRouteExpression());
return;
}
if (param instanceof FixedValue) {
buildBaseValue(builder, (FixedValue) param);
return;
}
if (param instanceof QueryValue) {
QueryValue val = (QueryValue) param;
QueryDomain queryDomain = val.getQueryDomain();
buildQuery(queryDomain, useFragment, builder, depth + 1);
}
}
private static void buildBaseValue(StringBuilder builder, FixedValue param) {
FixedValue val = param;
if (ValueType.Null == val.getValueType()) {
builder.append("null");
}
if (ValueType.Boolean == val.getValueType()) {
Boolean boolVal = (Boolean) val.getValue();
builder.append(boolVal.toString());
}
if (ValueType.Number == val.getValueType()) {
Number numVal = (Number) val.getValue();
builder.append(numVal.toString());
}
if (ValueType.String == val.getValueType()) {
String strVal = (String) val.getValue();
StringUtils.quote(builder, strVal);
}
}
//
private static void buildFields(final QueryDomain queryDomain, final boolean useFragment, final StringBuilder builder, final int depth) {
List<String> fieldNames = queryDomain.getFieldNames();
for (int i = 0; i < fieldNames.size(); i++) {
if (i != 0) {
builder.append(",\n");
}
builder.append(genDepthStr(depth));
String fieldName = fieldNames.get(i);
buildField(fieldName, useFragment, queryDomain.getField(fieldName), builder, depth);
}
}
private static void buildField(final String fieldName, final boolean useFragment, final DValue field, final StringBuilder builder, final int depth) {
buildFieldKey(fieldName, field, builder);
buildFieldValue(fieldName, useFragment, field, builder, depth);
}
private static void buildFieldKey(final String fieldName, final DValue field, final StringBuilder builder) {
builder.append("\"" + fieldName.replace("\"", "\\\"") + "\"");
if (field instanceof RouteValue) {
RouteValue val = (RouteValue) field;
if (!fieldName.equals(val.getRouteExpression())) {
builder.append(" : ");
}
return;
}
if (field instanceof FixedValue) {
builder.append(" : ");
}
if (field instanceof QueryValue) {
builder.append(" : ");
}
}
private static void buildFieldValue(final String fieldName, final boolean useFragment, final DValue field, final StringBuilder builder, final int depth) {
if (field instanceof FixedValue) {
buildBaseValue(builder, (FixedValue) field);
return;
}
if (field instanceof QueryValue) {
QueryValue val = (QueryValue) field;
QueryDomain queryDomain = val.getQueryDomain();
if (fieldName.equals(queryDomain.getQueryName()) || !useFragment) {
buildQuery(queryDomain, useFragment, builder, depth + 1);
} else {
buildFragment(queryDomain, useFragment, builder, depth + 1);
builder.append(queryDomain.getQueryName());
}
}
if (field instanceof RouteValue) {
RouteValue val = (RouteValue) field;
if (fieldName == null || !fieldName.equals(val.getRouteExpression())) {
builder.append(val.getRouteExpression());
}
}
return;
}
//
private static void buildFragment(QueryDomain queryDomain, boolean useFragment, StringBuilder builder, int depth) {
StringBuilder fragment = new StringBuilder();
fragment.append("fragment " + queryDomain.getQueryName() + " on ");
buildQuery(queryDomain, useFragment, fragment, 1);
fragment.append("\n\n");
builder.insert(0, fragment.toString());
}
}