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

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

There is a newer version: 3.7.10
Show newest version
/*  Copyright 1999 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.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.*;

import com.viaoa.ds.OADataSource;
import com.viaoa.ds.objectcache.OADataSourceObjectCache;
import com.viaoa.hub.Hub;
import com.viaoa.hub.HubDetailDelegate;
import com.viaoa.hub.HubSelectDelegate;
import com.viaoa.hub.HubTemp;
import com.viaoa.sync.OASyncDelegate;
import com.viaoa.util.OAFilter;
import com.viaoa.util.OAPropertyPath;
import com.viaoa.util.OAString;
import com.viaoa.util.filter.OAEqualFilter;
import com.viaoa.util.filter.OAFilterDelegate;
import com.viaoa.util.filter.OAFilterDelegate.FinderInfo;

/**
 * 
 * @author vincevia
 * @see OAThreadLocalDelegate#setObjectCacheAddMode(int)
 * @see OAThreadLocalDelegate#getObjectCacheAddMode()
 */
public class OAObjectCacheDelegate {
	private static Logger LOG = Logger.getLogger(OAObjectCacheDelegate.class.getName());
	
	protected static int DefaultAddMode = 1;

    /** throw an exception if a duplicate object is added. This is Default.  
	    see HubController#setAddMode
	*/
	static public final int NO_DUPS = 1;   // dont use 0
	
	/** dont store object if a duplicate is already stored. 
	    If the object is being deserialized (see OAObject.readResolve)
	    then the object that is already loaded will be used.
	    see HubController#setAddMode
	    @see OAObject#readResolve
	*/
	static public final int IGNORE_DUPS = 2;
	
	/** store object even if another exists
	    see HubController#setAddMode
	*/
	static public final int OVERWRITE_DUPS = 3;
	
	/** dont store objects.
	    see HubController#setAddMode
	*/
	static public final int IGNORE_ALL = 4;
	static protected final int MODE_MAX = 4;
    
    /**
     * Automatically set by Hub.select() when a select is done without a where clause.
     * A WeakReference is used for storage.  
     * When a new OAObject is created, it will be added to a SelectAllHub.
     * @since 2007/08/16
     */
    public static Hub[] getSelectAllHubs(Class clazz) {
    	if (clazz == null) return null;
        WeakReference[] refs = (WeakReference[]) OAObjectHashDelegate.hashCacheSelectAllHub.get(clazz);
        if (refs == null) return null;
    	synchronized (OAObjectHashDelegate.hashCacheSelectAllHub) {
	        Hub[] hubs = new Hub[refs.length];
	        for (int i=0; i 0) return hs[0];
    	return null;
    }   
    private static WeakReference[] removeSelectAllHubs(WeakReference[] refs, WeakReference refRemove) {
		WeakReference[] refs2 = new WeakReference[refs.length-1];
		boolean bFound = false;
        int j = 0;
		for (int i=0; ivisit every object in the Cache.
	*/
    public static void callback(OACallback callback) {
        visit(callback);
    }
	public static void visit(OACallback callback) {
        LOG.fine("visit");
        for (Class c : OAObjectHashDelegate.hashCacheClass.keySet()) {
            visit(callback, c);
        }
	}

	public static void callback(Class clazz, OACallback callback) {
		visit(callback, clazz);
	}
    public static void visit(Class clazz, OACallback callback) {
        visit(callback, clazz);
    }
	
    /**
    Used to visit every object in the Cache for a Class.
	*/
    public static void callback(OACallback callback, Class clazz) {
        visit(callback, clazz);
    }
	public static void visit(OACallback callback, Class clazz) {
        if (callback == null) return;
        TreeMapHolder tmh = (TreeMapHolder) OAObjectHashDelegate.hashCacheClass.get(clazz);
        if (tmh == null) return;
        
        try {
            // 2081223 removed lock so that thisdoes not cause a deadlock
            //      since the callback could be doing something that could cause one.
            //was: tmh.rwl.readLock().lock();
            
            tmh.rwl.readLock().lock();
            TreeMap tm = tmh.treeMap;
            Map.Entry me = tm.firstEntry();
            tmh.rwl.readLock().unlock();
            
            while (me != null) {
                WeakReference ref = (WeakReference) me.getValue();
                Object obj = ref.get();
                if (obj != null) {
                    if (!callback.updateObject(obj)) break;
                }
                me = tm.higherEntry(me.getKey());
            }
        }
        finally {
            //was: tmh.rwl.readLock().unlock();
        }
    }

	
	
    /**
        Populates a Vector of Strings that describe the Classes and amount of objects that are loaded.
    */
    public static void getInfo(Vector vec) {
        // LOG.finer("called");
        Vector v = getInfo();
        int x = v.size();
        for (int i=0; i al = new ArrayList<>();
        Enumeration enumx = OAObjectHashDelegate.hashCacheClass.keys();
        for (; enumx.hasMoreElements(); ) {
            Class c = enumx.nextElement();
            al.add(c);
        }
        Class[] cs = new Class[al.size()];
        al.toArray(cs);
        return cs;
    }
    public static int getTotal(Class clazz) {
        TreeMapHolder tmh = (TreeMapHolder) OAObjectHashDelegate.hashCacheClass.get(clazz);
        if (tmh == null) return 0;
        try {
            tmh.rwl.readLock().lock();
            return tmh.treeMap.size();
        }
        finally {
            tmh.rwl.readLock().unlock();
        }
    }
    
    public static OAObject getRandom(Class clazz, int max) {
        TreeMapHolder tmh = (TreeMapHolder) OAObjectHashDelegate.hashCacheClass.get(clazz);
        Map.Entry> ent = null;

        if (tmh == null) return null;
        try {
            tmh.rwl.readLock().lock();
            int x = Math.min(tmh.treeMap.size(), max);
            x = (int) (Math.random() * x);
            ent = tmh.treeMap.firstEntry();
            for (int i=0; i ref = ent.getValue();
            if (ref == null) return null;
            return ref.get();
        }
        finally {
            tmh.rwl.readLock().unlock();
        }
    }
    
    
    /**
        Returns a Vector of Strings that describe the Classes and amount of objects that are loaded.
    */
    public static Vector getInfo() {
        // LOG.finer("called");
        Vector vec = new Vector(20,20);
        vec.addElement("HubController Info --- ");
        
    	Class[] cs = getClasses();
    	if (cs == null) return vec;
    	int x = cs.length;
    	
    	int max = 0;
    	for (int i=0; i alResults) {
        if (bDisableCache) return null;

        TreeMapHolder tmh = getTreeMapHolder(clazz, false);
        if (tmh == null) return null;

        try {
            tmh.rwl.readLock().lock();
        
            Map.Entry> me = null;
            if (fromObject != null) {
                OAObjectKey key;
                if (fromObject instanceof OAObjectKey) key = (OAObjectKey) fromObject;
                else if (fromObject instanceof OAObject) key = OAObjectKeyDelegate.getKey((OAObject) fromObject);
                else key = OAObjectKeyDelegate.convertToObjectKey(clazz, fromObject);
                if (key != null) {
                    me = tmh.treeMap.ceilingEntry(key);
                }
            }
            if (me == null) me = tmh.treeMap.firstEntry();
            
            boolean b = OAObject.class.isAssignableFrom(clazz);
            while (me != null) {
                WeakReference ref = (WeakReference) me.getValue();
                Object object = ref.get();
                if (object != null && object != fromObject) {
                    if (!bSkipNew || !b || !((OAObject)object).getNew()) {
                        if (finder == null || finder.findFirst((OAObject) object) != null) {
                            if (alResults == null) return object;
                            alResults.add(object);
                            if (alResults.size() >= fetchAmount) return object;
                        }
                    }
                }            
                me = tmh.treeMap.higherEntry(me.getKey());
            }
        }
        finally {
            tmh.rwl.readLock().unlock();
        }
        return null;
    }


    /**
     * Refresh all objects from the datasource.
     * This will be ran on the server, if called by client then it will async to run on server.
     * @param clazz Class of objects to update, will also requery all hubs for this class.
     */
    public static void refresh(Class clazz) {
        if (clazz == null) return;
        LOG.fine("refreshing "+clazz.getSimpleName());
        
        if (!OASyncDelegate.isServer(clazz)) {
            OASyncDelegate.getRemoteServer(clazz).refresh(clazz);
            LOG.fine("refreshing "+clazz.getSimpleName()+" will be ran on the server");
            return;
        }
        HashSet hsHub = new HashSet();
        
        OADataSource ds = OADataSource.getDataSource(clazz);
        if (ds == null) return;
        
        OAObjectInfo oi = OAObjectInfoDelegate.getOAObjectInfo(clazz);
        
        OADataSourceObjectCache dsCache = new OADataSourceObjectCache(false);
        Iterator it = dsCache.select(clazz);

        int cntTotal = 0;
        int cntAlone = 0;
        for ( ;it.hasNext(); cntTotal++) {
            OAObject obj = (OAObject) it.next();
            Hub[] hubs = OAObjectHubDelegate.getHubReferences(obj);

            boolean bNeedsRefreshed = true;
            if (hubs != null) {
                for (Hub h : hubs) {
                    if (h == null) continue;
                    if (h.getSelect() == null) {
                        if (h.getMasterObject() == null) continue;
                        OALinkInfo li = HubDetailDelegate.getLinkInfoFromDetailToMaster(h);
                        if (li != null) {
                            li = li.getReverseLinkInfo();
                            if (li == null || li.getCalculated()) continue;
                            if (li.getPrivateMethod()) continue;
                        }
                    }                
                    bNeedsRefreshed = false;
                    if (!hsHub.contains(h)) hsHub.add(h);
                }
            }
            
            if (bNeedsRefreshed) {
                OAObjectKey key = OAObjectKeyDelegate.getKey(obj);
                ds.getObject(oi, clazz, key, true);
                cntAlone++;
                continue;
            }
        }

        int cntHubs = 0;
        int cntInHubs = 0;
        for (Hub h: hsHub) {
            HubSelectDelegate.refreshSelect(h);
            cntHubs++;
            cntInHubs += h.getSize();
        }
        dsCache.close();
        LOG.fine(String.format("refreshed %s, total=%d, alongCnt=%d, hubCnt=%d, inHubsCnt=%d", 
                clazz.getSimpleName(), cntTotal, cntAlone, cntHubs, cntInHubs));
    }
    
    
   
/*qqq    
    public static void updateClientInfo(OAClientInfo ci) {
    	// LOG.fine("called");
        Enumeration enumx = OAObjectHashDelegate.hashCacheClass.keys();
        ci.getCacheHashMap().clear();

        Object[] cs = OAObjectHashDelegate.hashCacheClass.keySet().toArray();
    	if (cs == null) return;
    	int x = cs.length;
    	for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy