欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HQL伪代码解析算法(易扩展)

程序员文章站 2022-07-02 19:22:02
...
解析的语法规则:

$req{key}$:
典型应用:
1.表示从 当前的requset中 获取数据 key为获取数据的键值.


$sen{key}$
典型应用:
1. $sen{User}$ 表示 从当前session中获取User对象的Id.
2. $sen{User.id}$ 与上面是等价的.
3. $sen{User.userName}$ 表示 从当前session中获取User对象的 用户名
4. $sen{User.field1.field2.fieild...n} 深层属性取值的时候.


$date{day,format}$
典型应用:
1. $date{3}$ 表示获取前三天的时间点 , 默认第二个参数可以不写 默认为:yyyy-MM-dd
2. $date{current}$ 获取当前时期 :默认格式为:yyyy-MM-dd


$time{hour,format}$
典型应用:
1. $time{8}$ 表示获取前8小时的时间点,第二个参数可以不写:默认格式为:yyyy-MM-dd HH:mm:ss
2. $time{current}$ 获取当前时间 :默认格式为:yyyy-MM-dd HH:mm:ss


以下为代码示例:


public class DynHqlUtil {


/**
* hql语句装配 将伪代码转化为可执行代码
*
* @param hql
* @return
* @throws Exception
*/
public static String hqlLoader(String hql) throws Exception{

DynHqlConfig cfg = new DynHqlConfig();
DynHqlLoader loader = new DynHqlLoader();

return loader.loader(hql, cfg);
}


public static void main(String[] args) {
String hql;
try {
hql = DynHqlUtil.hqlLoader("from User where xxx = $date{7}$ and bb='k' and kk=$date{current}$");
System.out.println( hql );

} catch (Exception e) {
e.printStackTrace();
}

}

}


/***************************************************************************/

public class DynHqlConfig {

public static final char BOR = '$'; //$...$ 定义边框
public static final char LEFTSIGN = '{';// 左 括 弧
public static final char RIGHTSIGN = '}';// 右 括 弧

public static final String REQ = "req";//$req{key}$ 定义HttpRequest
public static final String SEN = "sen";//$sen{key}$ 定义HttpSession
public static final String DATE = "date";//$date{day,format}$ 定义日期
public static final String TIME = "time";//$time{hour}$ 定义时间

public static final String DATE_CURRENT ="current";//定义 本地当前时间

private Map<String,String> mapKey;

public DynHqlConfig(){

//此处重定义 伪代码key值
mapKey = new HashMap<String, String>();

mapKey.put("user",Constants.USER_AUTH);//定义取用户的 key值
}

public String getKey( String contentKey ) {

String key = contentKey.trim().toLowerCase();
if( !mapKey.containsKey(key) )
return key;

return mapKey.get(key);
}
}

/*******************************************************************************/

@SuppressWarnings("unused")
public class DynHqlLoader {

static char[] hex = "0123456789ABCDEF".toCharArray();

private StringBuilder buf ;
private DynHqlConfig cfg ;

private int startInx = 0;
private int endInx = -1;

//边框 开始与结束
private boolean borStar = false;
private boolean borEnd = false;
//大括弧 开始与结束
private boolean bracStar = false;
private boolean bracEnd = false;

/**
* 装配 hql 语句
* @param hql
* @param cfg
* @return
* @throws Exception
*/
public String loader(String hql , DynHqlConfig cfg) throws Exception{

this.cfg = cfg;
this.buf = new StringBuilder();
this.parseHql(hql);

return buf.toString();
}

/**
* 解析 hql
* @param hql
* @throws Exception
*/
@SuppressWarnings("static-access")
private void parseHql(String hql) throws Exception{

int length = hql.length();
String str = "";
CharacterIterator it = new StringCharacterIterator(hql);

boolean sbor = false;
boolean ebor = false;

int inx = -1;
for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
endInx++;//实时记录 当前处理的下标

//当遇到第一个 $符号时 开始进入等待下一个对称$ 结束符的出现 否则视为语法错误 原样输出
if( c == cfg.BOR ){

if( sbor && !ebor ) ebor =true;

if( !sbor ){
sbor = true;
this.appendHql(hql);
}
}


if(sbor && ebor){
sbor = ebor = false ;
this.appendFakcCode(hql);
}
}

String h = hql.substring(this.startInx,length);
this.buf.append(h);
}

/**
* 拼接 非动态部分 hql
* 调整索引下标
* @param hql
*/
private void appendHql(String hql){

String h = hql.substring(this.startInx,this.endInx);
this.buf.append(h);

this.startInx = this.endInx;
}

/**
* 处理 动态部分 hql
* 调整索引下标
* @param hql
*/
@SuppressWarnings("static-access")
private void appendFakcCode(String hql) throws Exception{

String fcode = hql.substring(this.startInx,this.endInx+1);
this.startInx = this.endInx+1;

String value = fcode;

System.out.println("之前:fcode "+value);

if( this.validBracket(fcode) ){

if(fcode.indexOf(cfg.REQ )!=-1){
value = this.request(fcode);
}else if(fcode.indexOf(cfg.SEN )!=-1){
value = this.session(fcode);
}else if(fcode.indexOf(cfg.DATE )!=-1){
value = this.date(fcode);
} else if(fcode.indexOf(cfg.TIME)!=-1){
value = this.time(fcode);
}
}

System.out.println("之后:fcode "+value);

this.buf.append(value);
}

/**
* 从 HttpRequest 中取值
*/
@SuppressWarnings("static-access")
private String request(String fcode){

Object value = fcode;

String[] params = null;
String key = fcode.substring( fcode.indexOf(cfg.LEFTSIGN)+1,fcode.indexOf(cfg.RIGHTSIGN) );

if(key!=null){
params = (String[])ServletActionContext.getContext().getParameters().get(key.trim());
if( params!=null && params.length>=1 ){
value = params[0];
}
}

return value.toString();
}

/**
* 从 HttpSession 中取值
*/
@SuppressWarnings("static-access")
private String session(String fcode)throws Exception{

String value = fcode;
String content = fcode.substring( fcode.indexOf(cfg.LEFTSIGN)+1,fcode.indexOf(cfg.RIGHTSIGN) );

Object obj = null;
String key = null;

if(content!=null){

//假设 单对象的情况
if( content.indexOf(".")==-1 ){
key = cfg.getKey(content);
if( key!=null )
obj = ServletActionContext.getContext().getSession().get( key );

if( obj != null && key != null ){

String methodName = "getId";
if( methodName!=null )
value = (String)obj.getClass().getMethod( methodName ).invoke(obj);
}
}
//假设 对象.属性的情况
if( content.indexOf(".")!=-1 ){
String[] prop = content.split("\\.");

key = cfg.getKey(prop[0]);
if( key!=null )
obj = ServletActionContext.getContext().getSession().get( key );

if( obj != null && key != null ){
//截取 属性链 (将属性链的第一个去掉)
String nextPropLink = content.substring(content.indexOf(".")+1,content.length());
value = this.getParameter(obj,nextPropLink);
}
}
}

return value ;
}

private String getParameter(Object obj , String propLink ) throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{

System.out.println( propLink );
String[] fields = propLink.split("\\.");
String fieldName = null;
String nextPropLink = null;
boolean exeRecursion = true; //是否继续执行递归

if( fields.length == 1 ){
exeRecursion = false;
fieldName = fields[0];
}

if( fields.length > 1 ){
exeRecursion = true;
fieldName = propLink.substring(0,propLink.indexOf("."));
nextPropLink = propLink.substring(propLink.indexOf(".")+1,propLink.length());
}

BeanInfo info = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] props = info.getPropertyDescriptors();

Object value = obj;

for (int i = 0; i < props.length; i++) {

PropertyDescriptor prop = props[i];
String name = prop.getName();

if( !name.equals( fieldName ) ){
continue;
}
Method method = prop.getReadMethod();
value = method.invoke(obj, new Object[0]);

if(exeRecursion)
return this.getParameter(value, nextPropLink);
else
break;
}

return value.toString();
}


/**
* 获取相对 日期-时间
*
* 解析格式 : $date{day,format}$ 第2个参数可不指定 默认为:默认时间格式:yyyy-MM-dd
* 默认格式 : $date{current}$ 默认时间格式:yyyy-MM-dd
* @param value
* @return
* @throws Exception
*/
@SuppressWarnings("static-access")
private String date(String fcode) throws Exception{

String content = fcode.substring( fcode.indexOf(cfg.LEFTSIGN)+1,fcode.indexOf(cfg.RIGHTSIGN) );
String value = fcode ;
if(content!=null){

String[] args = content.split(",");

if(args.length==2){

//获取当前日期 $date{current,yyyy-MM-dd HH:mm:ss}$
if( content.indexOf( cfg.DATE_CURRENT )!=-1 ){

value = this.date(0,args[1]);;

} else {//获取指定的相对日期 $date{7,yyyy-MM-dd HH:mm:ss}$

int day = -1;
if( (day = this.validNumber(args[0]) )!=-1 ){
value = this.date(day,args[1]);
}
}
}

if(args.length==1){

//获取当前日期 $date{current}$
if( content.indexOf( cfg.DATE_CURRENT )!=-1 ){

value = this.date(0,"yyyy-MM-dd");;

} else {//获取指定的相对日期 $date{7}$

int day = -1;
if( (day = this.validNumber(args[0]) )!=-1 ){
value = this.date(day,"yyyy-MM-dd");
}
}
}
}

return value;
}

/**
* 获取 指定的相对时间( 日期-时间 )
*
* @param number
* @return
* @throws Exception
*/
private String date(int number,String format) throws Exception{

long l = System.currentTimeMillis();
long subDay = (24L*60L*60L*1000L)*(long)number;

return DateUtil.getAppointTime( (l-subDay) ,format);
}

/**
* 获取相对 时间(小时)
*
* 解析格式 : $time{hour,format}$ 第2个参数可不指定 默认为:默认时间格式:yyyy-MM-dd HH:mm:ss
* 默认格式 : $time{current}$ 默认时间格式:yyyy-MM-dd HH:mm:ss
* @param fcode
* @return
* @throws Exception
*/
@SuppressWarnings("static-access")
private String time(String fcode)throws Exception{

String content = fcode.substring( fcode.indexOf(cfg.LEFTSIGN)+1,fcode.indexOf(cfg.RIGHTSIGN) );
String value = fcode ;
if(content!=null){

String[] args = content.split(",");

if(args.length==2){

//获取当前日期 $date{current,yyyy-MM-dd HH:mm:ss}$
if( content.indexOf( cfg.DATE_CURRENT )!=-1 ){

value = this.time(0,args[1]);

} else {//获取指定的相对日期 $date{7,yyyy-MM-dd HH:mm:ss}$

int hour = -1;
if( (hour = this.validNumber(args[0]) )!=-1 ){
value = this.time(hour,args[1]);
}
}
}

if(args.length==1){

//获取当前日期 $date{current}$
if( content.indexOf( cfg.DATE_CURRENT )!=-1 ){

value = this.time(0,"yyyy-MM-dd HH:mm:ss");

} else {//获取指定的相对日期 $date{7}$

int hour = -1;
if( (hour = this.validNumber(args[0]) )!=-1 ){
value = this.time(hour,"yyyy-MM-dd HH:mm:ss");
}
}
}
}

return value;
}

/**
* 获取 相对时间 (小时)
* @param hour
* @param format
* @return
* @throws Exception
*/
private String time(int hour,String format)throws Exception{

long l = System.currentTimeMillis();
long subHour = (60L*60L*1000L)*(long)hour;
return DateUtil.getAppointTime(l-subHour,format);
}

/**
* 验证 括弧的合法性
* @return
*/
@SuppressWarnings("static-access")
private boolean validBracket(String fakcCode){

String fcode = fakcCode;
boolean bool = false ;
if( (fcode.indexOf(cfg.LEFTSIGN)!=-1) && (fcode.indexOf(cfg.RIGHTSIGN)!=-1)){
bool = true ;
}
return bool;
}

/**
* 验证是否是 数字字符
* @param strNumber
* @return
*/
private int validNumber(String strNumber){

String strNum = strNumber.trim();
int ascall = -1;
if(strNum!=null&&!"".equals(strNum)){
for (int i = 0; i < strNum.length(); i++) {
ascall = strNum.charAt(i);
if(ascall<'0'|| ascall>'9') return -1;
}
}

return Integer.parseInt( strNum );
}
}

相关标签: 算法 Access