components/visual-panels/core/src/java/util/com/oracle/solaris/vp/util/misc/ChangeableAggregator.java
changeset 3553 f1d133b09a8c
parent 3552 077ebe3d0d24
child 3554 ef58713bafc4
equal deleted inserted replaced
3552:077ebe3d0d24 3553:f1d133b09a8c
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 package com.oracle.solaris.vp.util.misc;
       
    27 
       
    28 import java.io.PrintWriter;
       
    29 import java.util.*;
       
    30 import javax.swing.event.*;
       
    31 import com.oracle.solaris.vp.util.swing.event.ChangeListeners;
       
    32 
       
    33 public class ChangeableAggregator implements Changeable, ChangeListener {
       
    34     //
       
    35     // Static data
       
    36     //
       
    37 
       
    38     private static boolean debug;
       
    39 
       
    40     //
       
    41     // Instance data
       
    42     //
       
    43 
       
    44     private String name;
       
    45     private final List<Changeable> changeables = new ArrayList<Changeable>();
       
    46 
       
    47     private List<Changeable> roChangeables =
       
    48 	Collections.unmodifiableList(changeables);
       
    49 
       
    50     private ChangeListeners listeners = new ChangeListeners();
       
    51     private boolean changed;
       
    52     private ChangeEvent event = new ChangeEvent(this);
       
    53 
       
    54     //
       
    55     // Constructors
       
    56     //
       
    57 
       
    58     /**
       
    59      * Constructs a {@code ChangeableAggregator} with a {@code null} name.
       
    60      */
       
    61     public ChangeableAggregator() {
       
    62     }
       
    63 
       
    64     /**
       
    65      * Constructs a {@code ChangeableAggregator} with the given name.
       
    66      *
       
    67      * @see	    #setName
       
    68      */
       
    69     public ChangeableAggregator(String name) {
       
    70 	this();
       
    71 	setName(name);
       
    72     }
       
    73 
       
    74     //
       
    75     // Changeable methods
       
    76     //
       
    77 
       
    78     @Override
       
    79     public void addChangeListener(ChangeListener listener) {
       
    80 	listeners.add(listener);
       
    81     }
       
    82 
       
    83     @Override
       
    84     public boolean isChanged() {
       
    85 	return changed;
       
    86     }
       
    87 
       
    88     @Override
       
    89     public boolean removeChangeListener(ChangeListener listener) {
       
    90 	return listeners.remove(listener);
       
    91     }
       
    92 
       
    93     @Override
       
    94     public void reset() {
       
    95 	// Avoid thread deadlock by iterating over a copy of changeables, rather
       
    96 	// than synchronzing on it
       
    97 	List<Changeable> changeables = new ArrayList<Changeable>(
       
    98 	    this.changeables);
       
    99 
       
   100 	for (Changeable changeable : changeables) {
       
   101 	    changeable.reset();
       
   102 	}
       
   103     }
       
   104 
       
   105     @Override
       
   106     public void save() {
       
   107 	// Avoid thread deadlock by iterating over a copy of changeables, rather
       
   108 	// than synchronzing on it
       
   109 	List<Changeable> changeables = new ArrayList<Changeable>(
       
   110 	    this.changeables);
       
   111 
       
   112 	for (Changeable changeable : changeables) {
       
   113 	    changeable.save();
       
   114 	}
       
   115     }
       
   116 
       
   117     //
       
   118     // ChangeListener methods
       
   119     //
       
   120 
       
   121     @Override
       
   122     public void stateChanged(ChangeEvent e) {
       
   123 	boolean changed = false;
       
   124 	synchronized (changeables) {
       
   125 	    for (Changeable changeable : changeables) {
       
   126 		if (changeable.isChanged()) {
       
   127 		    changed = true;
       
   128 		    break;
       
   129 		}
       
   130 	    }
       
   131 	    setChanged(changed);
       
   132 	}
       
   133     }
       
   134 
       
   135     //
       
   136     // ChangeableAggregator methods
       
   137     //
       
   138 
       
   139     public void addChangeables(Changeable... changeables) {
       
   140 	synchronized (this.changeables) {
       
   141 	    for (Changeable changeable : changeables) {
       
   142 		this.changeables.add(changeable);
       
   143 		changeable.addChangeListener(this);
       
   144 	    }
       
   145 
       
   146 	    // Initialize
       
   147 	    stateChanged(null);
       
   148 	}
       
   149     }
       
   150 
       
   151     public void clearChangeables() {
       
   152 	synchronized (changeables) {
       
   153 	    for (int i = changeables.size() - 1; i >= 0; i--) {
       
   154 		removeChangeable(changeables.get(i));
       
   155 	    }
       
   156 	}
       
   157     }
       
   158 
       
   159     /**
       
   160      * Returns an unmodifiable wrapper around this {@code
       
   161      * ChangeableAggregator}'s list of {@link Changeable}s.
       
   162      */
       
   163     public List<Changeable> getChangeables() {
       
   164 	synchronized (changeables) {
       
   165 	    return roChangeables;
       
   166 	}
       
   167     }
       
   168 
       
   169     /**
       
   170      * Gets this {@code ChangeableAggregator}'s name.  This field is
       
   171      * nonessential and may be used for debugging purposes.
       
   172      */
       
   173     public String getName() {
       
   174 	return name;
       
   175     }
       
   176 
       
   177     public boolean removeChangeable(Changeable changeable) {
       
   178 	synchronized (changeables) {
       
   179 	    if (changeables.remove(changeable)) {
       
   180 		changeable.removeChangeListener(this);
       
   181 
       
   182 		// Re-initialize
       
   183 		stateChanged(null);
       
   184 
       
   185 		return true;
       
   186 	    }
       
   187 	}
       
   188 
       
   189 	return false;
       
   190     }
       
   191 
       
   192     /**
       
   193      * Sets this {@code ChangeableAggregator}'s name.  This field is
       
   194      * nonessential and may be used for debugging purposes.
       
   195      */
       
   196     public void setName(String name) {
       
   197 	this.name = name;
       
   198     }
       
   199 
       
   200     //
       
   201     // Private methods
       
   202     //
       
   203 
       
   204     private void setChanged(boolean changed) {
       
   205 	if (this.changed != changed) {
       
   206 	    this.changed = changed;
       
   207 	    listeners.stateChanged(event);
       
   208 	}
       
   209     }
       
   210 
       
   211     //
       
   212     // Static methods
       
   213     //
       
   214 
       
   215     /**
       
   216      * Enable debugging.  Subsequent calls to {@link DebugUtil#dump} with a
       
   217      * {@code ChangeableAggregator} as an argument will provide more meaningful
       
   218      * data.
       
   219      */
       
   220     public static void debug() {
       
   221 	if (!debug) {
       
   222 	    debug = true;
       
   223 	    DebugUtil.DumpHandler handler = new DebugUtil.DumpHandler() {
       
   224 		@Override
       
   225 		public boolean dump(String prefix, Object object, int indent,
       
   226 		    PrintWriter out) {
       
   227 
       
   228 		    if (object instanceof ChangeableAggregator) {
       
   229 			ChangeableAggregator aggregator =
       
   230 			    (ChangeableAggregator)object;
       
   231 
       
   232 			String name = aggregator.getName();
       
   233 			boolean changed = aggregator.isChanged();
       
   234 
       
   235 			out.printf("%s%s%s %s (%s)\n",
       
   236 			    DebugUtil.indent(indent), prefix,
       
   237 			    DebugUtil.toBaseName(aggregator),
       
   238 			    name == null ? "(unnamed)" : ("\"" + name + "\""),
       
   239 			    changed ? "changed" : "not changed");
       
   240 
       
   241 			indent++;
       
   242 
       
   243 			if (changed) {
       
   244 			    for (Changeable changeable :
       
   245 				aggregator.getChangeables()) {
       
   246 
       
   247 				if (changeable.isChanged()) {
       
   248 				    DebugUtil.dump("", changeable, indent, out);
       
   249 				    break;
       
   250 				}
       
   251 			    }
       
   252 			}
       
   253 
       
   254 			return true;
       
   255 		    }
       
   256 
       
   257 		    return false;
       
   258 		}
       
   259 	    };
       
   260 	    DebugUtil.handlers.add(handler);
       
   261 	}
       
   262     }
       
   263 }