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-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.openide.windows;

import java.io.IOException;
import java.util.*;

import org.openide.util.io.NbMarshalledObject;
import org.openide.util.NbBundle;

/** A top component which may be cloned.
* Typically cloning is harmless, i.e. the data contents (if any)
* of the component are the same, and the new component is merely
* a different presentation.
* Also, a list of all cloned components is kept.
*
* @author Jaroslav Tulach
*/
public abstract class CloneableTopComponent extends TopComponent
    implements java.io.Externalizable, TopComponent.Cloneable {
    /** generated Serialized Version UID */
    static final long serialVersionUID = 4893753008783256289L;

    /** reference with list of components */
    private Ref ref;

    /** Create a cloneable top component.
    */
    public CloneableTopComponent () {
    }

    /** Clone the top component and register the clone.
    * @return the new component
    */
    public final Object clone () {
        return cloneComponent ();
    }

    /** Clone the top component and register the clone.
    * Simply calls createClonedObject () and registers the component to
    * Ref.
    *
    * @return the new cloneable top component
    */
    public final CloneableTopComponent cloneTopComponent() {
        CloneableTopComponent top = createClonedObject ();
        // register the component if it has not been registered before
        top.setReference (getReference ());
        return top;
    }

    /** Clone the top component and register the clone.
    * @return the new component
    */
    public final TopComponent cloneComponent() {
        return cloneTopComponent ();
    }

    /** Called from {@link #clone} to actually create a new component from this one.
    * The default implementation only clones the object by calling {@link Object#clone}.
    * Subclasses may leave this as is, assuming they have no special needs for the cloned
    * data besides copying it from one object to the other. If they do, the superclass
    * method should be called, and the returned object modified appropriately.
    * @return a copy of this object
    */
    protected CloneableTopComponent createClonedObject () {
        try {
            // clones the component using serialization
            NbMarshalledObject o = new NbMarshalledObject (this);
            CloneableTopComponent top = (CloneableTopComponent)o.get ();
            return top;
        } catch (IOException ex) {
            ex.printStackTrace();
            throw new InternalError ();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
            throw new InternalError ();
        }
    }

    /** Get a list of all components which are clone-sisters of this one.
    *
    * @return the clone registry for this component's group
    */
    public synchronized final Ref getReference () {
        if (ref == null) {
            ref = new Ref (this);
        }
        return ref;
    }

    /** Changes the reference to which this components belongs.
    * @param another the new reference this component should belong
    */
    public synchronized final void setReference (Ref another) {
        if (another == EMPTY) {
            throw new IllegalArgumentException(
                NbBundle.getBundle(CloneableTopComponent.class).getString("EXC_CannotAssign")
            );
        }

        if (ref != null) {
            // Remove from old ref, we are going to belong to 'another' reference.
            ref.removeComponent(this);
        }
        // Register with the new reference.
        another.register (this);
        // Finally set the field.
        ref = another;
    }
    
    /** Overrides superclass method, adds unregistering from references. 
     * @see Ref */
    protected void componentClosed() {
        super.componentClosed();
        if(!isOpened()) {
            getReference().unregister(this);
        }
    }

    /** Called when this component is about to close.
    * The default implementation just unregisters the clone from its clone list.
    * 

If this is the last component in its clone group, then * {@link #closeLast} is called to clean up. * * @return true if there are still clone sisters left, or this was the last in its group * but {@link #closeLast} returned true */ public boolean canClose (Workspace workspace, boolean last) { if (last) { return getReference ().unregister (this); } return true; } /** Called when the last component in a clone group is closing. * The default implementation just returns true. * Subclasses may specify some hooks to run. * @return true if the component is ready to be * closed, false to cancel */ protected boolean closeLast () { return true; } public void readExternal (java.io.ObjectInput oi) throws java.io.IOException, java.lang.ClassNotFoundException { super.readExternal (oi); if (serialVersion != 0) { // since serialVersion > 0 // the reference object is also stored Ref ref = (Ref)oi.readObject (); if (ref != null) { setReference (ref); } } } public void writeExternal (java.io.ObjectOutput oo) throws java.io.IOException { super.writeExternal (oo); oo.writeObject (ref); } // say what? --jglick /* Empty set that should save work with testing like *

    * if (ref == null || ref.isEmpty ()) {
    *   CloneableTopComponent c = new CloneableTopComponent (obj);
    *   ref = c.getReference ();
    * }
    * 
* Instead one can always set ref = Ref.EMPTY and test only if * ref.isEmpty returns true. */ /** Empty clone-sister list. */ public static final Ref EMPTY = new Ref (); /** Keeps track of a group of sister clones. *

* Warning: * For proper use * subclasses should have method readResolve () and implement it * in right way to deal with separate serialization of TopComponent. */ public static class Ref implements java.io.Serializable { /** generated Serialized Version UID */ static final long serialVersionUID = 5543148876020730556L; /** manipulation lock */ private static final Object LOCK = new Object (); /** Set of registered components. */ private transient /*final*/ Set componentSet = new HashSet(7); /** Default constructor for creating empty reference. */ protected Ref () { } /** Constructor. * @param c the component to refer to */ private Ref (CloneableTopComponent c) { synchronized(LOCK) { componentSet.add (c); } } /** Enumeration of all registered components. * @return enumeration of CloneableTopComponent */ public Enumeration getComponents () { Set components; synchronized (LOCK) { components = new HashSet(componentSet); } return java.util.Collections.enumeration(components); } /** Test whether there is any component in this set. * @return true if the reference set is empty */ public boolean isEmpty () { synchronized (LOCK) { return componentSet.isEmpty(); } } /** Retrieve an arbitrary component from the set. * @return some component from the list of registered ones * @exception NoSuchElementException if the set is empty * @deprecated Use {@link #getArbitraryComponent} instead. * It doesn't throw a runtime exception. */ public CloneableTopComponent getAnyComponent () { synchronized (LOCK) { return (CloneableTopComponent)componentSet.iterator().next(); } } /** Gets arbitrary component from the set. Preferrably returns currently * active component if found in the set. * @return arbitratry CloneableTopComponent from the set * or null if the set is empty * @since 3.41 */ public CloneableTopComponent getArbitraryComponent() { TopComponent activated = WindowManager.getDefault().getRegistry().getActivated(); synchronized(LOCK) { // prefer already active component if (componentSet.contains(activated)) return (CloneableTopComponent)activated; Iterator it = componentSet.iterator(); if(it.hasNext()) { return (CloneableTopComponent)it.next(); } else { return null; } } } /** Register new component. * @param c the component to register */ private final void register (CloneableTopComponent c) { synchronized (LOCK) { componentSet.add (c); } } /** Unregister the component. If this is the last asks if it is * allowed to unregister it. * * @param c the component to unregister * @return true if the component agreed to be unregister */ private final boolean unregister (CloneableTopComponent c) { int componentCount; synchronized(LOCK) { if(!componentSet.contains(c)) { return true; } componentCount = componentSet.size(); } if (componentCount > 1 || c.closeLast()) { removeComponent(c); return true; } else { return false; } } private void removeComponent(CloneableTopComponent c) { synchronized (LOCK) { componentSet.remove(c); } } /** Adds also initializing of componentSet field. */ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); synchronized(LOCK) { componentSet = new HashSet(7); } } } // end of Ref }

... 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.