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

com.viaoa.object.OAPreLoader Maven / Gradle / Ivy

/* Copyright 1999-2015 Vince Via [email protected] Licensed under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a copy of
 * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed
 * to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
 * language governing permissions and limitations under the License. */
package com.viaoa.object;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Logger;

import com.viaoa.ds.OADataSource;
import com.viaoa.ds.OASelect;
import com.viaoa.ds.jdbc.OADataSourceJDBC;
import com.viaoa.ds.jdbc.db.ManyToMany;
import com.viaoa.hub.*;
import com.viaoa.util.*;

/* This is used to preload objects.
 * 
 * Compared to OALoader, which loads objects by following a root object or Hub, and then goes through calling all of the methods in the property path.
 * ex:  Customers.Orders.Items.products
 * This can lead to a lot of calls to DS.
 *  
 * OAPreLoader is used when loading all objects, so that it can first preload the objects in the property path, and then use the cached objects to set
 * the property values.
 * 
 * This will load and set recursive properties, M2M properties.
 * 
 * Ex: from calss: ItemCategory, pp: items.products 
 *  where itemCategory is recursive and itemCategory.items is M2M 
 * 
 * */
public class OAPreLoader {
    private static Logger LOG = Logger.getLogger(OAPreLoader.class.getName());

    private Class classFrom;
    private String strPropertyPath;

    /**
     * Create a new pre loader.  Call load method to run.
     * @param classFrom base/root class for property path
     * @param propPath property path to load.  Note: all links need to be of type Many
     */
    public OAPreLoader(Class classFrom, String propPath) {
        this.classFrom = classFrom;
        this.strPropertyPath = propPath;
    }

    /**
     * load the property path. 
     * @return objects load from classFrom, so that gc does not remove objects from OAObjectCache
     */
    public ArrayList load() {
        if (classFrom == null) return null;

        OAPropertyPath propertyPath = null;
        OALinkInfo[] linkInfos = null;

        if (OAString.isNotEmpty(strPropertyPath)) {
            propertyPath = new OAPropertyPath(classFrom, strPropertyPath);
            linkInfos = propertyPath.getLinkInfos();
        }
        ArrayList al = null;
        try {
            OAThreadLocalDelegate.setLoading(true);
            al = _load(linkInfos);
        }
        finally {
            OAThreadLocalDelegate.setLoading(false);
        }
        return al;
    }

    protected ArrayList _load(OALinkInfo[] linkInfos) {
        final HashMap hm = new HashMap<>();

        final ArrayList al = load(classFrom, null);
        hm.put(classFrom, al);

        if (linkInfos != null) {
            for (OALinkInfo linkInfo : linkInfos) {
                Class c = linkInfo.getToClass();

                if (linkInfo.getType() != OALinkInfo.MANY) break;
                
                ArrayList alx = hm.get(c);
                if (alx == null) {
                    alx = load(c, linkInfo);
                    hm.put(c, alx);
                }
                
                if (linkInfo.isMany2Many()) {
                    loadMtoM(linkInfo);
                }
                else {
                    loadOtoM(linkInfo, alx);
                }
            }
        }
        return al;
    }

    protected void loadOtoM(OALinkInfo linkInfo, ArrayList alMany) {
        if (linkInfo == null || linkInfo.getType() != OALinkInfo.MANY) return;
        if (linkInfo.getPrivateMethod()) return;

        OALinkInfo liMany = linkInfo;
        OALinkInfo liOne = linkInfo.getReverseLinkInfo();
        if (liOne == null || liOne.getType() != OALinkInfo.ONE) return;
        
        for (Object objFromMany : alMany) {
            Object objOne = ((OAObject)objFromMany).getProperty(liOne.getName());
            if (!(objOne instanceof OAObject)) continue;
            
            Hub hub;
            Object objOneHub = OAObjectPropertyDelegate.getProperty((OAObject)objOne, liMany.getName(), false, true); 
            if (objOneHub instanceof Hub) {
                hub = (Hub) objOneHub;
            }
            else {
                hub = new Hub(liMany.getToClass());
                OAObjectPropertyDelegate.setProperty((OAObject) objOne, liMany.getName(), hub);
            }
            hub.add(objFromMany);
        }
    }
    
    
    protected void loadMtoM(OALinkInfo linkInfo) {
        if (linkInfo == null || !linkInfo.isMany2Many()) return;
        OADataSource ds = OADataSource.getDataSource(linkInfo.getToClass());
        if (!(ds instanceof OADataSourceJDBC)) return;

        OALinkInfo liA = linkInfo;
        OALinkInfo liB = linkInfo.getReverseLinkInfo();
        if (liB == null) return;
        
        Class classA = liB.getToClass();
        Class classB = liA.getToClass();
        
        ArrayList alManyToMany = ((OADataSourceJDBC) ds).getManyToMany(linkInfo);
        if (alManyToMany == null) return;
        
        for (ManyToMany mm : alManyToMany) {
            Object objA = OAObjectCacheDelegate.get(classA, mm.ok1);
            Object objB = OAObjectCacheDelegate.get(classB, mm.ok2);
            if (objA == null || objB == null) continue;

            if (!liA.getPrivateMethod()) {
                Hub hub;
                Object objx = OAObjectPropertyDelegate.getProperty((OAObject) objA, liA.getName(), false, true);
                if (objx instanceof Hub) {
                    hub = (Hub) objx;
                }
                else {
                    hub = new Hub(classB);
                    OAObjectPropertyDelegate.setProperty((OAObject) objA, liA.getName(), hub);
                }
                hub.add(objB);
            }
            
            if (!liB.getPrivateMethod()) {
                Hub hub;
                Object objx = OAObjectPropertyDelegate.getProperty((OAObject) objB, liB.getName(), false, true);
                if (objx instanceof Hub) {
                    hub = (Hub) objx;
                }
                else {
                    hub = new Hub(classA);
                    OAObjectPropertyDelegate.setProperty((OAObject) objB, liB.getName(), hub);
                }
                hub.add(objA);
            }
        }
    }

    // 1toM recursive - load all then populate f.hubChildren
    protected ArrayList load(Class clazz, final OALinkInfo linkInfo) {
        OASelect sel = new OASelect<>(clazz);
        OAObjectInfo oi = OAObjectInfoDelegate.getObjectInfo(clazz);
        OALinkInfo liRecursive = OAObjectInfoDelegate.getRecursiveLinkInfo(oi, OALinkInfo.MANY);

        String sortOrder = null;
        if (liRecursive != null) {
            OALinkInfo liRev = liRecursive.getReverseLinkInfo();
            if (liRev != null) {
                sortOrder = liRecursive.getSortProperty();
            }
        }
        if (sortOrder == null && linkInfo != null) {
            sortOrder = linkInfo.getSortProperty();
        }
        if (OAString.isNotEmpty(sortOrder)) sel.setOrder(sortOrder);

        ArrayList al = new ArrayList<>();
        for (;;) {
            Object obj = sel.next();
            if (obj == null) break;
            al.add(obj);
        }
        
        if (liRecursive != null) {
            loadRecursive(clazz, al, liRecursive);

            // might need to reselect if both had different sortOrder
            String s = liRecursive.getSortProperty();
            if (linkInfo != null && OAString.isNotEmpty(s)) {
                String s2 = linkInfo.getSortProperty();
                if (OAString.isNotEmpty(s2)) {
                    if (!OAString.isEqual(s, s2, true)) {
                        sel = new OASelect<>(clazz);
                        sel.setOrder(s);
                        al = new ArrayList<>();
                        for (;;) {
                            Object obj = sel.next();
                            if (obj == null) break;
                            al.add(obj);
                        }
                    }
                }
            }
        }
        return al;
    }

    protected void loadRecursive(Class clazz, ArrayList al, OALinkInfo liMany) {
        if (liMany == null) return;
        OALinkInfo liOne = liMany.getReverseLinkInfo();
        if (liOne == null) return;

        for (Object f : al) {
            Object fParent = liOne.getValue(f);
            if (!(fParent instanceof OAObject)) continue;

            Hub hub;
            Object objx = OAObjectPropertyDelegate.getProperty((OAObject) fParent, liMany.getName(), false, true);
            if (objx instanceof Hub) {
                hub = (Hub) objx;
            }
            else {
                hub = new Hub(clazz);
                OAObjectPropertyDelegate.setProperty((OAObject) fParent, liMany.getName(), hub);
            }
            hub.add(f);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy