alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.java.codesync;

import java.util.*;
import org.openide.src.*;

/**
 * This container caches changes made to a specific type of elements until properties
 * of the change are mature enough to pass the event to the listeners. In particular,
 * changes that require identifier resolution are cached inside until the parser or
 * resolver resolves properties of the element in question.
 *
 * @author  sdedic
 * @version 
 */
public abstract class ChangeCache extends Object {
    Set     created;
    Map     changed;
    
    public Collection elementsChanged(Map changeMap) {
        Collection changes = null;
        
        for (Iterator it = changeMap.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry en = (Map.Entry)it.next();
            
            // the map is keyed by element instances; those instances represent the
            // "new" state of the element.
            Element newValue = getNewValue(en);
            Element oldValue = getOldValue(en);
            Element ref = getEntityReference(en);
            
            if (!isMature(newValue, oldValue)) {
                enterChange(ref, oldValue);
            } else {
                boolean c = created != null && created.remove(ref);
                // try to lookup the element in the cache:
                Element ancientValue = c ? null : removeChange(ref);
                if (changes == null)
                    changes = new LinkedList();
                changes.add(ref);
                if (!c && ancientValue == null)
                    changes.add(oldValue);
                else
                    changes.add(ancientValue);
            }
        }
        // changes now contains list of pairs 
        return changes;
    }
    
    private Element getOldValue(Map.Entry en) {
        return (Element)((Object[])en.getValue())[0];
    }
    
    private Element getNewValue(Map.Entry en) {
        return (Element)((Object[])en.getValue())[1];
    }
    
    private Element getEntityReference(Map.Entry en) {
        return (Element)en.getKey();
    }
    
    /*
    private Element getOldValue(Map.Entry en) {
        return (Element)en.getValue();
    }
    
    private Element getNewValue(Map.Entry en) {
        return (Element)en.getKey();
    }
    
    private Element getEntityReference(Map.Entry en) {
        return (Element)en.getKey();
    }
    */
    
    
    protected Element removeChange(Element ref) {
        if (created != null && created.remove(ref))
            return null;
        if (changed != null)
            return (Element)changed.remove(ref);
        else
            return null;
    }
    
    /**
     * Registers the change within the cache. The method does nothing, if a change
     * on that element was already seen, or the element was created fresh and those
     * events are held in the cache.
     * @param ref the element itself, used as a lookup key
     * @param oldState copy of the element just before the change was made.
     */
    protected void enterChange(Element ref, Element oldState) {
        if (created != null && created.contains(ref))
            return;
        if (changed != null && changed.containsKey(ref))
            return;
        if (changed == null)
            changed = new HashMap(17);
        changed.put(ref, oldState);
    }
    
    public Collection elementsCreated(Collection col) {
        if (col == null || col.isEmpty())
            return null;
        
        Collection changes = null;
        
        for (Iterator it = col.iterator(); it.hasNext(); ) {
            Element el = (Element)it.next();
            if (!isMature(el, null)) {
                if (created == null)
                    created = new HashSet(11);
                created.add(el);
            } else {
                if (changes == null)
                    changes = new LinkedList();
                changes.add(el);
            } 
        }
        return changes;
    }
    
    public Collection elementsRemoved(Collection rem) {
        if (rem == null || rem.isEmpty())
            return null;
        for (Iterator it = rem.iterator(); it.hasNext(); ) {
            Element el = (Element)it.next();
            removeChange(el);
            if (created != null)
                created.remove(el);
        }
        return rem;
    }
    
    /**
     * This method determines whether the element's property values are mature enough
     * to be broadcasted; for example, if the element's definition contains unresolved
     * identifiers, the change will be cached until new data arrive.
     * @param el the element to test.
     * @param hint if not null, it contains previously seen element's state. The implementation
     * may speed up analysis of complex property values by using the prev state information.
     */
    protected abstract boolean isMature(Element el, Element hint);
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.