ofbiz实体引擎(五) ModelGroupReader

时间:2022-05-03
本文章向大家介绍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;
    }