ofbiz实体引擎(五) ModelGroupReader

public class ModelGroupReader implements Serializable {

    public static final String module = ModelGroupReader.class.getName();
    //缓存所有ModelGroupReader,其k是entity-group-reader属性值
    private static final UtilCache<String, ModelGroupReader> readers = UtilCache.createUtilCache("entity.ModelGroupReader", 0, 0);

    private Map<String, String> groupCache = null;//以entityName为k groupName为v
    private Set<String> groupNames = null;//delegator所有的组名

    public String modelName;//entity-group-reader属性值
    public List<ResourceHandler> entityGroupResourceHandlers = new LinkedList<ResourceHandler>();//存放像entity-resource这样标签实例

    /**
     * @author 郑小康
     * 1.获取当前delegatorName的delegator标签的DelegatorElement实例
     *
     * 2.获取delegator的entity-group-reader属性值
     *
     * 3.根据属性值获取ModelGroupReader
     *
     * 4.如果没有获取到根据delegatorName和entity-group-reader属性值构造一个ModelGroupReader实例,具体过程就在本类中
     *
     * */
    public static ModelGroupReader getModelGroupReader(String delegatorName) throws GenericEntityConfException {
        DelegatorElement delegatorInfo = EntityConfig.getInstance().getDelegator(delegatorName);

        if (delegatorInfo == null) {
            throw new GenericEntityConfException("不能发现叫做" + delegatorName+"的delegator");
        }

        String tempModelName = delegatorInfo.getEntityGroupReader();
        ModelGroupReader reader = readers.get(tempModelName);

        if (reader == null) {
            reader = readers.putIfAbsentAndGet(tempModelName, new ModelGroupReader(delegatorName, tempModelName));
        }
        return reader;
    }

    /**
     * @author 郑小康
     * 1. 赋值entity-group-reader的属性值
     *
     * 2. 根据entity-group-reader的属性值获取其对应的EntityGroupReader实例,如果为空就抛出异常
     *    原因:其获取的是EntityConfig实例的中的属性,EntityGroupReader是在EntityConfig实例化是加载的属性标签的对象,所以没有是肯定有问题的
     *
     * 3. 添加entityngine.xml中的句柄属性标签MainResourceHandler实例
     *
     * 4. 获取component.xml文件中entity-resource标签类型为group,根据与entity-group-reader的属性值对应reader-name构建ComponentResourceHandler实例添加到entityGroupResourceHandlers这个集合
     *    作用是通过这个属性在对应文件中entityName所在的组,后续将其放入到对应的组中,与具体的数据源关联
     *
     * 5. 获取delegator中与entity-group-reader的属性值对应的entity-resource中reader-name相同的标签实例
     *    根据entity-resource的路径获取文件下所有entity-group实例,将其以entityName为k,groupNam为v存入到具体的groupCache中
     * */
    public ModelGroupReader(String delegatorName, String modelName) throws GenericEntityConfException {
        this.modelName = modelName;
        EntityGroupReader entityGroupReaderInfo = EntityConfig.getInstance().getEntityGroupReader(modelName);

        if (entityGroupReaderInfo == null) {
            throw new GenericEntityConfException("Cound not find an entity-group-reader with the name " + modelName);
        }

        for (Resource resourceElement: entityGroupReaderInfo.getResourceList()) {
            this.entityGroupResourceHandlers.add(new MainResourceHandler(EntityConfig.ENTITY_ENGINE_XML_FILENAME, resourceElement.getLoader(), resourceElement.getLocation()));
        }

        // get all of the component resource group stuff, ie specified in each fadp-component.xml file
        for (ComponentConfig.EntityResourceInfo componentResourceInfo: ComponentConfig.getAllEntityResourceInfos("group")) {
            if (modelName.equals(componentResourceInfo.readerName)) {
                this.entityGroupResourceHandlers.add(componentResourceInfo.createResourceHandler());
            }
        }

        // preload caches...
        getGroupCache(delegatorName);
    }

    /**
     * @author 郑小康
     * 如果groupCache为空则将当前delegator下,如果不为空才进行下面的操作
     *
     * 1.构建对应的groupCache和groupNames
     *
     * 2.加载所有资源句柄文件
     *   即根据与当前entity-group-reader的属性值相同的entity-resource中reader-name的entity-resource标签
     *   根据entity-resource的路径获取文件下所有entity-group实例,将其以entityName为k,groupNam为v存入到具体的groupCache中
     *   以entityName为k groupName为v 这样做的作用就是像getEntityGroupName等方法可以根据实体名获取对应的组名
     * */
    public Map<String, String> getGroupCache(String delegatorName) {
        if (this.groupCache == null) { // don't want to block here
            synchronized (ModelGroupReader.class) {
                //再次检查groupCache是否为空,避免其它线程创建
                if (this.groupCache == null) {
                    //构造groupCache这个hashMap 和groupNames这个TreeSet
                    this.groupCache = new HashMap<String, String>();
                    this.groupNames = new TreeSet<String>();

                    //做一些时间的通知
                    UtilTimer utilTimer = new UtilTimer();
                    utilTimer.timerString("[ModelGroupReader.getGroupCache] Before getDocument");

                    int i = 0;
                    //遍历所有entity-resource标签对应ComponentResourceHandler实例
                    for (ResourceHandler entityGroupResourceHandler: this.entityGroupResourceHandlers) {
                        Document document = null;

                        try {
                            //解析为文档元素
                            document = entityGroupResourceHandler.getDocument();
                        } catch (GenericConfigException e) {
                            Debug.logError(e, "Error loading entity group model", module);
                        }

                        //如果document为空,缓存置为空,并且返回
                        if (document == null) {
                            this.groupCache = null;
                            return null;
                        }

                        // utilTimer.timerString("[ModelGroupReader.getGroupCache] Before getDocumentElement");
                        Element docElement = document.getDocumentElement();
                        if (docElement == null) {
                            continue;
                        }
                        //移除空的文本节点
                        docElement.normalize();

                        //以获取首个节点,而后进行遍历,处理所有entity-group节点将其组名加到groupNames这个集合,并以entityName为k,groupName为v存到对应groupCache中
                        //注意有一个检查,检查是否具有entityengine.xml对应的group-map的实例,如果没有加载就没有任何意义
                        Node curChild = docElement.getFirstChild();
                        if (curChild != null) {
                            utilTimer.timerString("[ModelGroupReader.getGroupCache] Before start of entity loop");
                            do {
                                if (curChild.getNodeType() == Node.ELEMENT_NODE && "entity-group".equals(curChild.getNodeName())) {
                                    Element curEntity = (Element) curChild;
                                    String entityName = UtilXml.checkEmpty(curEntity.getAttribute("entity")).intern();
                                    String groupName = UtilXml.checkEmpty(curEntity.getAttribute("group")).intern();

                                    if (groupName == null || entityName == null) continue;
                                    try {
                                        if (null == EntityConfig.getInstance().getDelegator(delegatorName).getGroupDataSource(groupName)) {
                                            Debug.logError("The declared group name " + groupName + " has no corresponding group-map in entityengine.xml: ", module);
                                        }
                                    } catch (GenericEntityConfException e) {
                                        Debug.logWarning(e, "Exception thrown while getting group name: ", module);
                                    }
                                    this.groupNames.add(groupName);
                                    this.groupCache.put(entityName, groupName);

                                    i++;
                                }
                            } while ((curChild = curChild.getNextSibling()) != null);
                        } else {
                            Debug.logWarning("[ModelGroupReader.getGroupCache] No child nodes found.", module);
                        }
                    }
                    utilTimer.timerString("[ModelGroupReader.getGroupCache] FINISHED - Total Entity-Groups: " + i + " FINISHED");
                }
            }
        }
        return this.groupCache;
    }

    /**
     * @author 郑小康
     * 方法作用:根据entityName和delegatorBaseName获取其对应的组名
     *
     * 1.根据方法获取groupCache
     *
     * 2.根据entityName获取组名
     *
     * 3.如果组名为空,获取delegator标签实体,获取其默认组名
     *
     * 4.返回组名
     * */
    public String getEntityGroupName(String entityName, String delegatorBaseName) {
        Map<String, String> gc = getGroupCache(delegatorBaseName);

        if (gc != null) {
            String groupName = gc.get(entityName);
            if (groupName == null) {
                DelegatorElement delegatorInfo = null;
                try {
                    delegatorInfo = EntityConfig.getInstance().getDelegator(delegatorBaseName);
                } catch (GenericEntityConfException e) {
                    Debug.logWarning(e, "Exception thrown while getting delegator config: ", module);
                }
                if (delegatorInfo == null) {
                    throw new RuntimeException("Could not find DelegatorInfo for delegatorBaseName [" + delegatorBaseName + "]");
                }
                groupName = delegatorInfo.getDefaultGroupName();
            }
            return groupName;
        } else {
            return null;
        }
    }

    /**
     * @author 郑小康
     *
     * 1.确保delegatorName是默认的delegatorName
     *
     * 2.调用getGroupCache方法的作用确保将对应的groupCache给加载到类属性
     *
     * 3.根据delegator的default-group-name获取所有其下面默认group-name标签实例的name,将其添加到一个HashSet集合
     *
     * 4.向该集合中添加已经通过getGroupCache方法加载的存放过entityName的groupNames集合
     * */
    public Set<String> getGroupNames(String delegatorBaseName) {
        if (delegatorBaseName.indexOf('#') >= 0) {
            delegatorBaseName = delegatorBaseName.substring(0, delegatorBaseName.indexOf('#'));
        }
        getGroupCache(delegatorBaseName);
        if (this.groupNames == null) return null;
        Set<String> newSet = new HashSet<String>();
        try {
            newSet.add(EntityConfig.getInstance().getDelegator(delegatorBaseName).getDefaultGroupName());
        } catch (GenericEntityConfException e) {
            Debug.logWarning(e, "Exception thrown while getting delegator config: ", module);
        }
        newSet.addAll(this.groupNames);
        return newSet;
    }

    /**
     *
     * @author 郑小康
     *
     * 1.构造一个Set根据delegatorBaseName和groupName,向该set注入该组里面所有的实体名
     *
     * 2.遍历groupCache,将组名相同的entityName添加到enames这个HashSet
     *
     * 3.返回对应的enames
     */
    public Set<String> getEntityNamesByGroup(String delegatorBaseName, String groupName) {
        Map<String, String> gc = getGroupCache(delegatorBaseName);
        Set<String> enames = new HashSet<String>();

        if (groupName == null || groupName.length() <= 0) return enames;
        if (UtilValidate.isEmpty(gc)) return enames;
        for (Map.Entry<String, String> entry: gc.entrySet()) {
            if (groupName.equals(entry.getValue())) enames.add(entry.getKey());
        }
        return enames;
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码匠的流水账

kafka0.8消费者实例

消费者实例数*每个实例的消费线程数 <= topic的partition数量,否则多余的就浪费了。

1531
来自专栏小灰灰

Java容器篇小结之Map自问自答

采用问答的方式对常见的问题进行整理小结 I. Map篇 0. 什么是Map 看到这个有点懵逼,一时还真不知道怎么解释,能让完全没有接触过的人都能听懂 想到生活...

18510
来自专栏软件开发 -- 分享 互助 成长

二分查找

二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列...

1957
来自专栏二进制文集

JDK源码分析 异常

对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我的JDK源码分析,着重在JDK的体系架构层面,具体源...

1084
来自专栏开发与安全

《linux c 编程一站式学习》课后部分习题解答

1、假设变量x和n是两个正整数,我们知道x/n这个表达式的结果要取Floor,例如x是17,n是4,则结果是4。如果希望结果取Ceiling应该怎么写表达式呢?...

2976
来自专栏有趣的Python

3-玩转数据结构-栈和队列

栈也是一种线性结构;相比数组,栈对应的操作是数组的子集;只能从一端添加元素,也只能从一端取出元素(这一端称之为栈顶)

2942
来自专栏Lambda

Java 常见内存溢出异常与代码实现

Java 堆 OutOfMemoryError Java 堆是用来存储对象实例的, 因此如果我们不断地创建对象, 并且保证 GC Root 和创建的对象之间...

1888
来自专栏Spark学习技巧

JAVA集合框架中的常用集合及其特点、适用场景、实现原理简介

943
来自专栏小灰灰

Java容器篇小结之List自问自答

I. List篇 0. 什么是List 看到这个有点懵逼,一时还真不知道怎么解释,能让完全没有接触过的人都能听懂 列表,什么是列表呢? 好比你到了一个村里,看...

1948
来自专栏青玉伏案

算法与数据结构(一) 线性表的顺序存储与链式存储(Swift版)

温故而知新,在接下来的几篇博客中,将会系统的对数据结构的相关内容进行回顾并总结。数据结构乃编程的基础呢,还是要不时拿出来翻一翻回顾一下。当然数据结构相关博客中我...

1957

扫码关注云+社区