001: /*
002: * @(#)AbstractMultipleStore.java
003: *
004: * Copyright (C) 2002-2003 Matt Albrecht
005: * groboclown@users.sourceforge.net
006: * http://groboutils.sourceforge.net
007: *
008: * Permission is hereby granted, free of charge, to any person obtaining a
009: * copy of this software and associated documentation files (the "Software"),
010: * to deal in the Software without restriction, including without limitation
011: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
012: * and/or sell copies of the Software, and to permit persons to whom the
013: * Software is furnished to do so, subject to the following conditions:
014: *
015: * The above copyright notice and this permission notice shall be included in
016: * all copies or substantial portions of the Software.
017: *
018: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
021: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
023: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
024: * DEALINGS IN THE SOFTWARE.
025: */
026:
027: package net.sourceforge.groboutils.util.classes.v1;
028:
029: import java.util.Vector;
030: import java.util.Enumeration;
031:
032: import org.apache.log4j.Logger;
033:
034: /**
035: * Similar in concept to the <tt>AbstractSingleStore</tt>, except this houses
036: * multiple instances of 'singletons'.
037: *
038: * @author Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
039: * @version $Date: 2003/02/10 22:52:36 $
040: * @since June 28, 2002
041: */
042: public abstract class AbstractMultipleStore {
043: private static final Logger LOG = Logger
044: .getLogger(AbstractMultipleStore.class.getName());
045:
046: private Class instanceOf;
047: private Vector store = new Vector();
048: private AllowMultiplesAction action;
049:
050: /**
051: * It stores each class already stored.
052: * This should in reality be a HashSet, but Hashtable may be a bit too
053: * much for our purposes.
054: */
055: private Vector usedClasses = new Vector();
056:
057: public static abstract class AllowMultiplesAction {
058: // don't allow outside replacements
059: AllowMultiplesAction() {
060: }
061:
062: protected abstract boolean addedMultiple(Object singleton,
063: Class baseClass);
064:
065: public abstract String toString();
066: }
067:
068: public static final AllowMultiplesAction NO_MULTIPLES_ERROR = new AllowMultiplesAction() {
069: protected boolean addedMultiple(Object singleton,
070: Class baseClass) {
071: throw new IllegalArgumentException("Passed-in singleton "
072: + singleton + " has class " + baseClass.getName()
073: + " which has already been added to the store");
074: }
075:
076: public String toString() {
077: return "[No multiple entries with same class allowed "
078: + "without error]";
079: }
080: };
081:
082: public static final AllowMultiplesAction NO_MULTIPLES_SILENT = new AllowMultiplesAction() {
083: protected boolean addedMultiple(Object singleton,
084: Class baseClass) {
085: // don't allow it
086: return false;
087: }
088:
089: public String toString() {
090: return "[No multiple entries with same class allowed]";
091: }
092: };
093:
094: public static final AllowMultiplesAction MULTIPLES_OK = new AllowMultiplesAction() {
095: protected boolean addedMultiple(Object singleton,
096: Class baseClass) {
097: // allow it
098: return true;
099: }
100:
101: public String toString() {
102: return "[Multiple entries with same class allowed]";
103: }
104: };
105:
106: /**
107: * Constructor specifying all the parameters for using a singleton in this
108: * framework.
109: *
110: * @param instanceOf singletons must be of this class.
111: * @param ama <tt>true</tt> if this store should allow
112: * multiple instances of the exact same class, or <tt>false</tt>
113: * if it should prevent multiple instances sharing the exact
114: * same class. This helps to enforce the idea of 'singleton'.
115: */
116: public AbstractMultipleStore(Class instanceOf,
117: AllowMultiplesAction ama) {
118: this .instanceOf = instanceOf;
119: this .usedClasses = new Vector();
120: this .action = ama;
121: }
122:
123: /**
124: * Returns the current inner singletons. If it has never been set, then
125: * the default will be used instead.
126: *
127: * @return the inner singleton instances.
128: * @exception IllegalStateException if no singleton was created.
129: */
130: public Enumeration getSingletons()
131: {
132: Enumeration enum;
133: synchronized( this )
134: {
135: if (this .store.size() <= 0)
136: {
137: addDefaultSingletons();
138: if (this .store.size() <= 0)
139: {
140: LOG.warn( "No singleton created." );
141: }
142: }
143: enum = this .store.elements();
144: }
145: return enum;
146: }
147:
148: /**
149: * Sets the singleton. It must be of the correct class, and non-null.
150: *
151: * @param singleton the singleton to set.
152: * @exception IllegalArgumentException if <tt>singleton</tt> is
153: * <tt>null</tt>, or is not of the correct type.
154: */
155: public synchronized void addSingleton(Object singleton) {
156: if (singleton == null) {
157: throw new IllegalArgumentException("no null arguments");
158: }
159: if (this .instanceOf != null
160: && !this .instanceOf.isInstance(singleton)) {
161: throw new IllegalArgumentException("Passed-in singleton "
162: + singleton + " is not assignable to class "
163: + this .instanceOf.getName() + ", but is of class "
164: + singleton.getClass().getName());
165: }
166: Class c = singleton.getClass();
167:
168: // optimization of following logic:
169: /*
170: if (!this.usedClasses.contains( c )
171: || this.action.addedMultiple( singleton, this.instanceOf ))
172: {
173: this.store.addElement( singleton );
174: this.usedClasses.addElement( c );
175: }
176: */
177: if (this .usedClasses.contains(c)) {
178: if (this .action.addedMultiple(singleton, this .instanceOf)) {
179: this .store.addElement(singleton);
180: }
181: } else {
182: this .store.addElement(singleton);
183: this .usedClasses.addElement(c);
184: }
185: }
186:
187: /**
188: * Adds the default inner singletons, which is an implementation
189: * specific method.
190: */
191: protected abstract void addDefaultSingletons();
192: }
|