/*
* Copyright 2014 mango.jfaster.org
*
* The Mango Project licenses this file to you 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 org.jfaster.mango.parser.visitor;
import org.jfaster.mango.binding.BindingParameter;
import org.jfaster.mango.binding.BindingParameterInvoker;
import org.jfaster.mango.binding.ParameterContext;
import org.jfaster.mango.exception.IncorrectParameterTypeException;
import org.jfaster.mango.parser.*;
import org.jfaster.mango.type.TypeHandler;
import org.jfaster.mango.type.TypeHandlerRegistry;
import org.jfaster.mango.util.reflect.TypeWrapper;
import java.lang.reflect.Type;
/**
* 类型检测
*
* @author ash
*/
public enum CheckAndBindVisitor implements ParserVisitor {
INSTANCE;
@Override
public Object visit(SimpleNode node, Object data) {
throw new UnsupportedOperationException();
}
@Override
public Object visit(ASTRootNode node, Object data) {
throw new UnsupportedOperationException();
}
@Override
public Object visit(ASTInsert node, Object data) {
throw new UnsupportedOperationException();
}
@Override
public Object visit(ASTDelete node, Object data) {
throw new UnsupportedOperationException();
}
@Override
public Object visit(ASTUpdate node, Object data) {
throw new UnsupportedOperationException();
}
@Override
public Object visit(ASTSelect node, Object data) {
throw new UnsupportedOperationException();
}
@Override
public Object visit(ASTReplace node, Object data) {
throw new UnsupportedOperationException();
}
@Override
public Object visit(ASTMerge node, Object data) {
throw new UnsupportedOperationException();
}
@Override
public Object visit(ASTTruncate node, Object data) {
throw new UnsupportedOperationException();
}
@Override
public Object visit(ASTBlock node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTJDBCParameter node, Object data) {
ParameterContext context = getParameterContext(data);
BindingParameter bp = node.getBindingParameter();
BindingParameterInvoker invoker = context.getBindingParameterInvoker(bp);
Type type = invoker.getTargetType();
TypeWrapper tw = new TypeWrapper(type);
Class<?> mappedClass = tw.getMappedClass();
TypeHandler<?> typeHandler = TypeHandlerRegistry.getNullableTypeHandler(mappedClass, bp.getJdbcType());
if (mappedClass == null || tw.isIterable() || typeHandler == null) {
throw new IncorrectParameterTypeException("invalid type of " + node.getFullName() + ", " +
"expected a class can be identified by jdbc but " + type);
}
node.setBindingParameterInvoker(invoker);
node.setTypeHandler(typeHandler);
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTJDBCIterableParameter node, Object data) {
ParameterContext context = getParameterContext(data);
BindingParameterInvoker invoker = context.getBindingParameterInvoker(node.getBindingParameter());
Type type = invoker.getTargetType();
TypeWrapper tw = new TypeWrapper(type);
Class<?> mappedClass = tw.getMappedClass();
if (!tw.isIterable()) { // 不是集合或数组抛出异常
throw new IncorrectParameterTypeException("invalid type of " + node.getFullName() + ", " +
"expected array or implementations of java.util.List or implementations of java.util.Set " +
"but " + type);
}
TypeHandler<?> typeHandler = TypeHandlerRegistry.getNullableTypeHandler(mappedClass);
if (mappedClass == null || typeHandler == null) {
String s = tw.isArray() ? "component" : "actual";
throw new IncorrectParameterTypeException("invalid " + s + " type of " + node.getFullName() + ", " +
s + " type of " + node.getFullName() + " expected a class can be identified by jdbc " +
"but " + tw.getMappedType());
}
node.setBindingParameterInvoker(invoker);
node.setTypeHandler(typeHandler);
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTGlobalTable node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTJoinParameter node, Object data) {
ParameterContext context = getParameterContext(data);
BindingParameterInvoker invoker = context.getBindingParameterInvoker(node.getBindingParameter());
node.setBindingParameterInvoker(invoker);
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTQuoteText node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTText node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTBlank node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTIfStatement node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTElseStatement node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTElseIfStatement node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTExpression node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTOrNode node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTAndNode node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTLTNode node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTGTNode node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTLENode node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTGENode node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTEQNode node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTNENode node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTNotNode node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTExpressionParameter node, Object data) {
ParameterContext context = getParameterContext(data);
BindingParameterInvoker invoker = context.getBindingParameterInvoker(node.getBindingParameter());
node.setBindingParameterInvoker(invoker);
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTIntegerLiteral node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTStringLiteral node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTTrue node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTFalse node, Object data) {
return node.childrenAccept(this, data);
}
@Override
public Object visit(ASTNull node, Object data) {
return node.childrenAccept(this, data);
}
private ParameterContext getParameterContext(Object data) {
ParameterContext context = (ParameterContext) data;
return context;
}
}