All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.cassite.daf4j.jpa.JPQLEntityDataParser Maven / Gradle / Ivy

The newest version!
package net.cassite.daf4j.jpa;

import net.cassite.daf4j.DataUtils;
import net.cassite.daf4j.IData;
import net.cassite.daf4j.PreResult;
import net.cassite.daf4j.QueryParameterTypes;
import net.cassite.daf4j.ds.DSUtils;
import net.cassite.daf4j.ds.EntityDataParser;
import net.cassite.daf4j.ds.ParserPacket;
import net.cassite.daf4j.types.*;
import net.cassite.daf4j.util.Location;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.*;

/**
 * 将实体和IData实例转化为JPQL
 */
public class JPQLEntityDataParser implements EntityDataParser {
        @Override
        public String parseData(JPQLContext jpqlContext, IData iData) {
                return parseEntity(jpqlContext, iData.getEntity()) + "." + DataUtils.findFieldNameByIData(iData);
        }

        @Override
        public String parseEntity(JPQLContext jpqlContext, Object o) {
                Location loc = findEntity(o, jpqlContext);
                return jpqlContext.aliasMap.get(loc);
        }

        @Override
        public String parsePlain(JPQLContext jpqlContext, Object o) {
                return "?" + jpqlContext.constantMap.add(o);
        }

        @Override
        public  String parseQuery(JPQLContext jpqlContext, PreResult preResult, ParserPacket parserPacket) throws Exception {
                JPQLContext cont = jpqlContext.copyForSubQuery(preResult.entity, preResult.parameter == null || !preResult.parameter.parameters.containsKey(QueryParameterTypes.distinct));
                String res = DSUtils.listGenerationProcess(cont, preResult.whereClause, preResult.parameter, parserPacket).generalJPQL.toString();
                jpqlContext.aliasMap.setAliasCount(cont.aliasMap.getAliasCount());
                return res;
        }

        /**
         * 获取实体的调用位置
* 使用广度优先搜索
* 找到时自动加入AliasMap * * @param entity 从该实体开始寻找 * @param toFind 要寻找的实体 * @param list 已经经过的路径 * @param args 上下文 * @param alreadySearched 已经寻找过的实体 * @return 找到的实体位置(Location对象), 没找到则返回null */ private static Location findEntity(Object entity, Object toFind, List list, JPQLContext args, Set alreadySearched, List> locationsMightBeJoined) { Map objectStringMap = new LinkedHashMap(); try { for (Field f : entity.getClass().getFields()) { // is IData if (IData.class.isAssignableFrom(f.getType())) { // get 1st generic type Class cls; try { cls = ((Class) ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0]); } catch (ClassCastException e) { // not generic type , maybe one of XTypes Class type = f.getType(); if (XInt.class.isAssignableFrom(type)) { cls = Integer.class; } else if (XLong.class.isAssignableFrom(type)) { cls = Long.class; } else if (XDouble.class.isAssignableFrom(type)) { cls = Double.class; } else if (XDate.class.isAssignableFrom(type)) { cls = Date.class; } else if (XString.class.isAssignableFrom(type)) { cls = String.class; } else if (XBool.class.isAssignableFrom(type)) { cls = Boolean.class; } else { throw e; } } // is not java. / javax. if (!cls.getName().startsWith("java.") && !cls.getName().startsWith("javax.")) { IData data = (IData) f.get(entity); Object obj = data.get(); if (obj == null) continue; if (obj instanceof Iterable) { // is aggregate Iterator it = ((Iterable) obj).iterator(); if (it.hasNext()) { Object o = it.next(); List tmp = new ArrayList(list); tmp.add(f.getName()); locationsMightBeJoined.add(new ArrayList(tmp)); if (o == toFind) { list.add(f.getName()); if (toFind != args.entity) { for (List locationList : locationsMightBeJoined) { Location loc = DataUtils.generateLocationAndFillMap(locationList, args.aliasMap); if (!args.toJoin.containsKey(loc)) { args.toJoin.put(loc, args.aliasMap.get(loc)); } } } return DataUtils.generateLocationAndFillMap(list, args.aliasMap); } else { if (!alreadySearched.contains(o)) { alreadySearched.add(o); objectStringMap.put(o, f.getName()); } } } } else { List tmp = new ArrayList(list); tmp.add(f.getName()); locationsMightBeJoined.add(new ArrayList(tmp)); // is plain object if (obj == toFind) { list.add(f.getName()); if (toFind != args.entity) { for (List locationList : locationsMightBeJoined) { Location loc = DataUtils.generateLocationAndFillMap(locationList, args.aliasMap); if (!args.toJoin.containsKey(loc)) { args.toJoin.put(loc, args.aliasMap.get(loc)); } } } return DataUtils.generateLocationAndFillMap(list, args.aliasMap); } else { if (!alreadySearched.contains(obj)) { alreadySearched.add(obj); objectStringMap.put(obj, f.getName()); } } } } } } // not found for (Object obj : objectStringMap.keySet()) { List nextList = new ArrayList(list); nextList.add(objectStringMap.get(obj)); List> nextLocationsMightBeJoined = new ArrayList>(locationsMightBeJoined); Location location = findEntity(obj, toFind, nextList, args, alreadySearched, nextLocationsMightBeJoined); if (null != location) { // found return location; } } return null; } catch (IllegalAccessException e) { throw new RuntimeException(e); } } /** * 获取Entity位置,若没有找到则抛出异常 * * @param toFind 要寻找的实体 * @param args 上下文 * @return 实体的位置(Location对象) */ static Location findEntity(Object toFind, JPQLContext args) { if (toFind == args.entity) { return new Location(null); } else { Location l = findEntity(args.entity, toFind, new ArrayList(), args, new HashSet(), new ArrayList>()); if (l == null) { throw new IllegalArgumentException("Cannot find location of " + toFind); } return l; } } }