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;
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章