/*
* 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.runtime.task;
import net.hasor.data.ql.runtime.QueryContext;
import net.hasor.data.ql.runtime.TaskType;
import net.hasor.data.ql.runtime.TaskUtils;
import java.util.Arrays;
/**
*
* @author 赵永春(zyc@hasor.net)
* @version : 2017-03-23
*/
public class RouteTask extends AbstractPrintTask {
private String routeExpression;
public RouteTask(String nameOfParent, AbstractTask parentTask, AbstractTask dataSource) {
super(nameOfParent, parentTask, dataSource);
}
//
@Override
protected TaskType initTaskType() {
return TaskType.F;
}
public void setRouteExpression(String routeExpression) {
this.routeExpression = routeExpression;
}
@Override
public Object doTask(QueryContext taskContext, Object inData) throws Throwable {
//
if (this.routeExpression.contains(".")) {
return this.evalRoute(taskContext, this, this.routeExpression.split("\\."), inData);
}
//
if (inData != null) {
return TaskUtils.readProperty(inData, this.routeExpression);
}
//
AbstractTask nearDS = this.getDataSource();
if (TaskType.F == this.getTaskType()) {
nearDS = TaskUtils.nearDS(this);//最近的数据源
}
//
if (nearDS != null) {
Object value = nearDS.getValue();
return TaskUtils.readProperty(value, this.routeExpression);
}
//
return taskContext.get(this.routeExpression);
}
private Object evalRoute(final QueryContext taskContext, final AbstractTask routeTask, final String[] routeSplit, final Object inData) throws Throwable {
AbstractTask curTask = routeTask;
AbstractTask dataTask = null;
AbstractTask dataSource = curTask.getDataSource();
//
// - 根节点
if (routeSplit[0].charAt(0) == '$') {
while (curTask.getParent() != null) {
curTask = curTask.getParent();
}
dataTask = curTask;
dataSource = TaskUtils.nearDS(curTask); //先找到根节点,然后定位根节点的数据源
}
// - 最近的DS
if (routeSplit[0].charAt(0) == '~') {
dataTask = TaskUtils.nearData(curTask);
dataSource = TaskUtils.nearDS(dataTask);//最近的数据源
}
// - 其它
if (dataTask == null) {
AbstractTask tempTask = curTask;
while (tempTask != null) {
dataTask = tempTask.findFieldTask(routeSplit[0]);
if (dataTask != null) {
dataSource = TaskUtils.nearDS(dataTask);
break;
}
tempTask = tempTask.getParent();
}
}
// - 定位 route 表达式所处的 Task
AbstractTask atTask = dataTask;
String[] newRouteSplit = Arrays.copyOfRange(routeSplit, 1, routeSplit.length);
for (String nodeName : newRouteSplit) {
atTask = atTask.findFieldTask(nodeName);
if (atTask == null)
break;
}
// - 如果无法定位到 route 的所处 Task 那么采用 DS 中的数据。
if (atTask == null) {
if (dataSource != null) {
Object value = dataSource.getValue();
for (String nodeName : newRouteSplit) {
if (value == null) {
return null;
}
value = TaskUtils.readProperty(value, nodeName);
}
return value;
}
return null;
}
//
if (TaskType.F == atTask.getTaskType()) {
RouteTask routeAtTask = (RouteTask) atTask;
return routeAtTask.doTask(taskContext, inData);//如果找到的目标节点是一个 F 节点,那么继续递归求值
}
return taskContext.get(this.routeExpression);
// throw new IllegalStateException("result is not ready or task is does support run.");
}
}