001 /* 002 * UniqueNodeNamePolicy.java 003 * 004 * Developed for the "Rethinking CS101" project. See http://www.cs101.org, the 005 * CS101 homepage or email las@olin.edu. 006 * 007 * Created on February 20, 2003, 11:54 AM 008 */ 009 010 package nodenet.registrar; 011 012 import nodenet.Node; 013 014 import java.beans.PropertyChangeEvent; 015 import java.beans.PropertyVetoException; 016 017 import java.util.Vector; 018 import java.util.ArrayList; 019 020 /** 021 * This class is designed to be plugged into {@link NodeNameRegistry} 022 * via the <code>setPolicy(NodeNameRegistrar)</code> method. It enforces 023 * the uniqueness of node names, and provides access to a node via its 024 * textual name. 025 * 026 * @author Patrick G. Heck, gus.heck@olin.edu 027 * @version $Id: UniqueNodeNamePolicy.java,v 1.8 2004/01/14 21:43:17 gus Exp $ 028 */ 029 public class UniqueNodeNamePolicy implements NodeNameRegistrar { 030 031 private static final String NAME_PREFIX = "Node "; 032 private volatile int nodeSerialNum; 033 034 private Vector nodes = new Vector(); 035 036 /** Creates a new instance of UniqueNodeNamePolicy */ 037 public UniqueNodeNamePolicy() { 038 } 039 040 /* (Copy of original doc. Generated version is inherited) 041 * 042 * Provides a name that is currently legal. The legality of the name is 043 * not guaranteed to remain legal for all time. This is particularly true 044 * if the policy implemented by the <code>Registrar</code> requires names 045 * to be unique. The implementation of this method should make a reasonable 046 * attempt not to give out names that will become illegal quickly, either 047 * due to temporal relevance of the name, or due to copetition between 048 * names given out to the clients. For example, this method should not 049 * give out the same node name on consecutive invocations if uniqueness is 050 * a qualification for legality. 051 * 052 * @returns A name that is currently legal, and should remain legal for a 053 * reasonable period of time, if possible. 054 */ 055 public synchronized String getLegalName() { 056 String temp; 057 do { 058 nodeSerialNum++; 059 temp = NAME_PREFIX + nodeSerialNum; 060 } while (!isUnique(temp)); 061 062 return temp; 063 } 064 065 066 /* (Copy of original doc. Generated version is inherited) 067 * 068 * Provides access to nodes via their registred name. This method is 069 * optional, but if it is not implemented it should throw an 070 * <code>UnsupportedOperationException</code> rather than returning 071 * a bogus node or null. 072 * 073 * @param aName The name of the node to look for. 074 * @return A reference to the node if found, null otherwise. 075 */ 076 public synchronized Node getNode(String aName) throws UnsupportedOperationException { 077 for (int i=0; i<nodes.size(); i++) { 078 Node aNode = ((Node)nodes.get(i)); 079 if(aNode.getName().equals(aName)) { 080 return aNode; 081 } 082 } 083 return null; 084 } 085 086 /* (Copy of original doc. Generated version is inherited) 087 * 088 * Provides a list of currently registered node names. This method is 089 * optional, but if it is not implemented it should throw an 090 * <code>UnsupportedOperationException</code> rather than returning 091 * a bogus list or null. 092 * 093 * @returns An array of node names currently in use. 094 */ 095 public synchronized String[] getRegisteredNames() throws UnsupportedOperationException { 096 String[] temp = new String[nodes.size()]; 097 for (int i=0; i<temp.length;i++) { 098 temp[i] = ((Node)nodes.get(i)).getName(); 099 } 100 return temp; 101 } 102 103 /* (Copy of original doc. Generated version is inherited) 104 * 105 * Tests a name to see if it is currently legal. The legality of the name is 106 * not guaranteed to remain invariant for all time. This is particularly 107 * true if the policy implemented by the <code>Registrar</code> requires 108 * names to be unique. 109 * 110 * @param aName The node name to be tested. 111 * @returns <code>true</code> if the name is legal, <code>false</code> 112 * otherwise. 113 */ 114 public boolean isLegalName(String aName) { 115 return isUnique(aName); 116 } 117 118 /* (Copy of original doc. Generated version is inherited) 119 * 120 * Tests to see if a name belongs to a registered node. For obvious reasons 121 * the results of this test are only valid while the client has a lock 122 * on the registry. 123 * 124 * @param The node name to test 125 * @return <code>true</code> if the name is registered <code>false</code> 126 * otherwise. 127 */ 128 public boolean isRegistered(String aName) { 129 String[] names = getRegisteredNames(); 130 for (int i=0; i<names.length; i++) { 131 if (names[i].equals(aName)) { 132 return true; 133 } 134 } 135 return false; 136 } 137 138 /* (Copy of original doc. Generated version is inherited) 139 * 140 * Tests to see if a node has been registered. 141 * 142 * @param The node to test 143 * @return <code>true</code> if the node is registered <code>false</code> 144 * otherwise. 145 */ 146 public boolean isRegistered(Node aNode) { 147 return isRegistered(aNode.getName()); 148 } 149 150 /* (Copy of original doc. Generated version is inherited) 151 * 152 * Gives the node a legal name and registers the node in one step. This 153 * method guarantees that the node will be registered, and no exceptions 154 * should be thrown. The node to be registered must expose a method 155 * with the signature setName(String). 156 */ 157 public synchronized void nameAndRegister(Node aNode) { 158 aNode.setName(getLegalName()); 159 this.register(aNode); 160 } 161 162 /* (Copy of original doc. Generated version is inherited) 163 * 164 * Attempt to register a node. This method proposes to register a node 165 * with an existing name. The node will be rejected if and only if it 166 * contains a name that would currently generate a false response 167 * from {@link #isLegalName(String)}. If the name contained in the node 168 * is rejected, The node is not registered or tracked in any way and an 169 * <code>IllegalArgumentException</code> will be thrown. 170 * 171 * @param aNode The node that wishes to register itself. 172 */ 173 public synchronized void register(Node aNode) throws IllegalArgumentException { 174 175 if (!isUnique(aNode.getName())) { 176 throw new IllegalArgumentException("Tried to register " + 177 "a node with a name that exists!\n Use nameNode to " + 178 "get a unique name before registering.\n"); 179 } else { 180 nodes.add(aNode); 181 } 182 } 183 184 /* (Copy of original doc. Generated version is inherited) 185 * 186 * Ensures that the specified node is nolonger registered. If the node 187 * was never registred, it simply returns with no side effects. 188 * 189 * @param aNode the node to unregister 190 */ 191 public void unregister(Node aNode) { 192 nodes.remove(aNode); 193 } 194 195 public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException { 196 if (!isLegalName((String)pce.getNewValue())) { 197 throw new PropertyVetoException("Duplicate names not allowed!",pce); 198 } 199 } 200 201 202 /** 203 * Checks for the uniqueness of the a potential node name. 204 * 205 * @param name The name to check for uniqueness. 206 * @return <code>true</code> if the name is not in use <code>false</code> 207 * otherwise 208 */ 209 private synchronized boolean isUnique(String name) { 210 for (int i=0; i<nodes.size();i++){ 211 if (name.equals(((Node) nodes.get(i)).getName())) { 212 return false; 213 } 214 } 215 return true; 216 } 217 } 218 219 220 /* 221 * $Log: UniqueNodeNamePolicy.java,v $ 222 * Revision 1.8 2004/01/14 21:43:17 gus 223 * more javadoc, plus reformat 224 * 225 * Revision 1.7 2004/01/14 20:23:21 gus 226 * Javadoc and comment cleanup 227 * 228 * Revision 1.6 2003/02/25 22:35:18 gus 229 * adding log comment 230 * 231 */