001: /*
002: * This file or a portion of this file is licensed under the terms of
003: * the Globus Toolkit Public License, found in file GTPL, or at
004: * http://www.globus.org/toolkit/download/license.html. This notice must
005: * appear in redistributions of this file, with or without modification.
006: *
007: * Redistributions of this Software, with or without modification, must
008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
009: * some other similar material which is provided with the Software (if
010: * any).
011: *
012: * Copyright 1999-2004 University of Chicago and The University of
013: * Southern California. All rights reserved.
014: */
015:
016: package org.griphyn.cPlanner.namespace;
017:
018: import org.griphyn.cPlanner.classes.Data;
019: import org.griphyn.cPlanner.classes.Profile;
020:
021: import org.griphyn.cPlanner.common.LogManager;
022:
023: import org.griphyn.cPlanner.common.PegasusProperties;
024:
025: import org.griphyn.common.catalog.TransformationCatalogEntry;
026:
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Map;
030: import java.util.Set;
031:
032: /**
033: * The base namespace class that all the othernamepsace handling classes extend.
034: * Some constants are defined.
035: *
036: * @author Karan Vahi
037: * @author Gaurang Mehta
038: * @version $Revision: 50 $
039: */
040:
041: public abstract class Namespace extends Data {
042:
043: /**
044: * The version number associated with this API of Profile Namespaces.
045: */
046: public static final String VERSION = "1.2";
047:
048: //constants for whether the key
049: //is valid in the namespace or not
050:
051: /**
052: * Either the key or the value specified is null or malformed.
053: */
054: public static final int MALFORMED_KEY = -1;
055:
056: /**
057: * The key is a valid key and can be put in the profiles.
058: */
059: public static final int VALID_KEY = 0;
060:
061: /**
062: * The key is unknown. Upto the profile namespace implementation whether to
063: * use it or not.
064: */
065: public static final int UNKNOWN_KEY = 1;
066:
067: /**
068: * The key is not permitted in as it clashes with default Pegasus constructs.
069: */
070: public static final int NOT_PERMITTED_KEY = 2;
071:
072: /**
073: * The key is deprecated. Support is for a limited time.
074: */
075: public static final int DEPRECATED_KEY = 3;
076:
077: /**
078: * The Map object that contains the profiles for a particular namespace.
079: * The Map is indexed by profile key. Each value, is a profile value.
080: */
081: protected Map mProfileMap;
082:
083: /**
084: * Checks if the namespace specified is valid or not.
085: *
086: * @param namespace The namespace you want to check
087: */
088: public static boolean isNamespaceValid(String namespace) {
089:
090: boolean valid = false;
091:
092: //sanity checks
093: if (namespace == null || namespace.length() < 2) {
094: return valid;
095: }
096:
097: if (namespace.equalsIgnoreCase(Profile.CONDOR)
098: || namespace.equalsIgnoreCase(Profile.GLOBUS)
099: || namespace.equalsIgnoreCase(Profile.VDS)
100: || namespace.equalsIgnoreCase(Profile.DAGMAN)
101: || namespace.equalsIgnoreCase(Profile.HINTS)
102: || namespace.equalsIgnoreCase(Profile.ENV)) {
103:
104: valid = true;
105: }
106:
107: return valid;
108: }
109:
110: /**
111: * This checks the whether a key value pair specified is valid in the current
112: * namespace or not, and whether it clashes with other key value pairs that
113: * might have been set by Pegasus internally.
114: *
115: * @return MALFORMED_KEY
116: * VALID_KEY
117: * UNKNOWN_KEY
118: * NOT_PERMITTED_KEY
119: */
120: public abstract int checkKey(String key, String value);
121:
122: /**
123: * Merge the profiles in the namespace in a controlled manner.
124: * The profiles should be merged only if the namespace object containing them
125: * matches to the current namespace.
126: *
127: * @param profiles the <code>Namespace</code> object containing the profiles.
128: */
129: public abstract void merge(Namespace profiles);
130:
131: /**
132: * Returns the name of the namespace associated with the profile implementations.
133: *
134: * @return the namespace name.
135: */
136: public abstract String namespaceName();
137:
138: /**
139: * Provides an iterator to traverse the profiles by their keys.
140: *
141: * @return an iterator over the keys to walk the profile list.
142: */
143: public Iterator getProfileKeyIterator() {
144: return (mProfileMap == null) ? new EmptyIterator()
145: : this .mProfileMap.keySet().iterator();
146: }
147:
148: /**
149: * Singleton access to the deprecated table that holds the deprecated keys,
150: * and the keys that replace them. It should be overriden in the namespaces,
151: * that have deprecated keys.
152: *
153: * @return Map
154: */
155: public Map deprecatedTable() {
156: throw new UnsupportedOperationException(
157: "No Deprecation support in the namespace "
158: + namespaceName());
159: }
160:
161: /**
162: * It puts in the namespace specific information from the Transformation
163: * Catalog into the namespace.
164: *
165: * @param entry the <code>TCEntry</code> object containing the result from
166: * the Transformation Catalog.
167: */
168: public void checkKeyInNS(TransformationCatalogEntry entry) {
169: //sanity check
170: if (entry == null) {
171: return;
172: }
173: //pass down the list of Profile objects to be sucked in.
174: checkKeyInNS(entry.getProfiles(this .namespaceName()));
175:
176: }
177:
178: /**
179: * It takes in a Profiles object and puts them into the namespace after
180: * checking if the namespace in the Profile object is same as the namepsace
181: * implementation.
182: *
183: * @param profile the <code>Profile</code> object containing the key and
184: * value.
185: *
186: * @exception IllegalArgumentException if the namespace in the profile
187: * is not the same as the profile namepsace in which the profile
188: * is being incorporated.
189: *
190: * @see org.griphyn.cPlanner.classes.Profile
191: */
192: public void checkKeyInNS(Profile profile)
193: throws IllegalArgumentException {
194: if (profile.getProfileNamespace().equals(this .namespaceName())) {
195: checkKeyInNS(profile.getProfileKey(), profile
196: .getProfileValue());
197: } else {
198: //throw an exception for the illegal Profile Argument
199: throw new IllegalArgumentException("Illegal Profile "
200: + profile);
201: }
202:
203: }
204:
205: /**
206: * It takes in a list of profiles and puts them into the namespace after
207: * checking if they are valid or not. Note, there are no checks on the
208: * namespace however. The user should ensure that each Profile object in
209: * the list is of the same namespace type.
210: *
211: * @param vars List of <code>Profile</code> objects, each referring
212: * to a key value for the profile.
213: *
214: *
215: * @see org.griphyn.cPlanner.classes.Profile
216: */
217: public void checkKeyInNS(List vars) {
218: if (vars == null || vars.isEmpty()) {
219: //no variables to insert
220: return;
221: }
222:
223: Profile p = null;
224: for (Iterator it = vars.iterator(); it.hasNext();) {
225: p = (Profile) it.next();
226: checkKeyInNS(p.getProfileKey(), p.getProfileValue());
227: }
228:
229: }
230:
231: /**
232: * It puts in the namespace specific information specified in the properties
233: * file into the namespace. The name of the pool is also passed, as many of
234: * the properties specified in the properties file are on a per pool basis.
235: *
236: * @param properties the <code>PegasusProperties</code> object containing
237: * all the properties that the user specified at various
238: * places (like .chimerarc, properties file, command line).
239: * @param pool the pool name where the job is scheduled to run.
240: */
241: public abstract void checkKeyInNS(PegasusProperties properties,
242: String pool);
243:
244: /**
245: * This checks the whether a key value pair specified is valid in the current
246: * namespace or not by calling the checkKey function and then on the basis of
247: * the values returned puts them into the associated map in the class.
248: *
249: * @param key key that needs to be checked in the namespace for validity.
250: * @param value value of the key
251: *
252: */
253: public void checkKeyInNS(String key, String value) {
254: int rslVal = checkKey(key, value);
255:
256: switch (rslVal) {
257:
258: case Namespace.MALFORMED_KEY:
259: //key is malformed ignore
260: malformedKey(key, value);
261: break;
262:
263: case Namespace.NOT_PERMITTED_KEY:
264: notPermitted(key);
265: break;
266:
267: case Namespace.UNKNOWN_KEY:
268: unknownKey(key, value);
269: break;
270:
271: case Namespace.VALID_KEY:
272: construct(key, value);
273: break;
274:
275: case Namespace.DEPRECATED_KEY:
276: deprecatedKey(key, value);
277: break;
278: }
279:
280: }
281:
282: /**
283: * Returns true if the namespace contains a mapping for the specified key.
284: * More formally, returns true if and only if this map contains at a mapping
285: * for a key k such that (key==null ? k==null : key.equals(k)).
286: * (There can be at most one such mapping.)
287: *
288: * @param key The key that you want to search for
289: * in the namespace.
290: */
291: public boolean containsKey(Object key) {
292: return (mProfileMap == null) ? false : mProfileMap
293: .containsKey(key);
294: }
295:
296: /**
297: * Constructs a new element of the format (key=value).
298: *
299: * @param key is the left-hand-side
300: * @param value is the right hand side
301: */
302: public void construct(String key, String value) {
303: mProfileMap.put(key, value);
304: }
305:
306: /**
307: * Removes the key from the namespace.
308: *
309: * @param key The key you want to remove.
310: *
311: * @return the value object if it exists.
312: * null if the key does not exist in the namespace.
313: */
314: public Object removeKey(Object key) {
315: return mProfileMap.remove(key);
316: }
317:
318: /**
319: * Returns the key set associated with the namespace.
320: *
321: * @return key set if the mProfileMap is populated.
322: * null if the associated mProfileMap is not populated.
323: */
324: public Set keySet() {
325: return (mProfileMap == null) ? null : mProfileMap.keySet();
326: }
327:
328: /**
329: * Returns the value to which this namespace maps the specified key.
330: * Returns null if the map contains no mapping for this key. A return value
331: * of null does not necessarily indicate that the map contains no mapping for
332: * the key; it's also possible that the map explicitly maps the key to null.
333: * The containsKey operation may be used to distinguish these two cases.
334: *
335: * @param key The key whose value you want.
336: *
337: */
338: public Object get(Object key) {
339: return mProfileMap.get(key);
340: }
341:
342: /**
343: * Warns about an unknown profile key and constructs it anyway.
344: * Constructs a new RSL element of the format (key=value).
345: *
346: * @param key is the left-hand-side
347: * @param value is the right hand side
348: */
349: public void unknownKey(String key, String value) {
350: mLogger.log("unknown profile " + namespaceName() + "." + key
351: + ", using anyway", LogManager.WARNING_MESSAGE_LEVEL);
352: construct(key, value);
353: }
354:
355: /**
356: * Warns about a deprecated profile key. It constructs the corresponding
357: * replacement key.
358: *
359: * @param key is the left-hand-side
360: * @param value is the right hand side
361: *
362: * @see #deprecatedTable()
363: */
364: public void deprecatedKey(String key, String value) {
365: String replacement = (String) deprecatedTable().get(key);
366: if (replacement == null) {
367: //no replacement key for the deprecated
368: //profile! Fatal Internal Error
369: StringBuffer error = new StringBuffer();
370: error
371: .append(
372: "No replacement key exists for deprecated profile ")
373: .append(namespaceName()).append(".").append(key);
374: throw new RuntimeException(error.toString());
375: }
376: mLogger.log("profile " + namespaceName() + "." + key
377: + " is deprecated. Replacing with " + namespaceName()
378: + "." + replacement, LogManager.WARNING_MESSAGE_LEVEL);
379:
380: if (containsKey(replacement)) {
381: //replacement key already exists.
382: //use that ! might break profile overriding ??
383: } else {
384: construct(replacement, value);
385: }
386:
387: }
388:
389: /**
390: * Warns about a namespace profile key that cannot be permitted.
391: *
392: * @param key is the key that induced the warning.
393: */
394: public void notPermitted(String key) {
395: mLogger.log("profile " + namespaceName() + "." + key
396: + " is not permitted, ignoring!",
397: LogManager.WARNING_MESSAGE_LEVEL);
398: }
399:
400: /**
401: * Warns about a namespace profile key-value pair that is malformed.
402: *
403: * @param key is the key that induced the warning.
404: * @param value is the corresponding value of the key.
405: */
406: public void malformedKey(String key, String value) {
407: mLogger.log("profile " + namespaceName() + "." + key
408: + " with value " + value + " is malformed, ignoring!",
409: LogManager.WARNING_MESSAGE_LEVEL);
410: }
411:
412: /**
413: * An empty iterator that allows me to traverse in case of null objects.
414: */
415: protected class EmptyIterator implements Iterator {
416:
417: /**
418: * Always returns false, as an empty iterator.
419: *
420: * @return false
421: */
422: public boolean hasNext() {
423: return false;
424: }
425:
426: /**
427: * Returns a null as we are iterating over nothing.
428: *
429: * @return null
430: */
431: public Object next() {
432: return null;
433: }
434:
435: /**
436: * Returns a false, as no removal
437: *
438: */
439: public void remove() {
440: }
441:
442: }
443:
444: }
|