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: package org.griphyn.cPlanner.classes;
016:
017: import org.griphyn.common.catalog.ReplicaCatalogEntry;
018:
019: import java.util.Collection;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.ArrayList;
023:
024: /**
025: * A Data Class that associates a LFN with the PFN's. Attributes associated
026: * with the LFN go here.
027: *
028: * @author Karan Vahi
029: * @author Gaurang Mehta
030: *
031: * @version $Revision: 50 $
032: *
033: * @see org.griphyn.common.catalog.ReplicaCatalogEntry
034: */
035: public class ReplicaLocation extends Data implements Cloneable {
036:
037: /**
038: * The site name that is associated in the case the resource handle is not
039: * specified with the PFN.
040: */
041: public static final String UNDEFINED_SITE_NAME = "UNDEFINED_SITE";
042:
043: /**
044: * The LFN associated with the entry.
045: */
046: private String mLFN;
047:
048: /**
049: * A list of <code>ReplicaCatalogEntry</code> objects containing the PFN's
050: * and associated attributes.
051: */
052: private List mPFNList;
053:
054: /**
055: * Default constructor.
056: */
057: public ReplicaLocation() {
058: mLFN = new String();
059: mPFNList = new ArrayList();
060: }
061:
062: /**
063: * Overloaded constructor.
064: * Intializes the member variables to the values passed.
065: *
066: * @param lfn the logical filename.
067: * @paran pfns the list of <code>ReplicaCatalogEntry</code> objects.
068: */
069: public ReplicaLocation(String lfn, List pfns) {
070: mLFN = lfn;
071: mPFNList = pfns;
072: //sanitize pfns. add a default resource handle if not specified
073: sanitize(mPFNList);
074: }
075:
076: /**
077: * Overloaded constructor.
078: * Intializes the member variables to the values passed.
079: *
080: * @param lfn the logical filename.
081: * @paran pfns the list of <code>ReplicaCatalogEntry</code> objects.
082: */
083: public ReplicaLocation(String lfn, Collection pfns) {
084: mLFN = lfn;
085:
086: //create a separate list only if required
087: mPFNList = (pfns instanceof List) ? (List) pfns :
088: //create a new list from the collection
089: new ArrayList(pfns);
090:
091: //sanitize pfns. add a default resource handle if not specified
092: sanitize(mPFNList);
093:
094: }
095:
096: /**
097: * Add a PFN and it's attributes. Any existing
098: * mapping with the same PFN will be replaced, including all its
099: * attributes.
100: *
101: * @param tuple the <code>ReplicaCatalogEntry</code> object containing the
102: * PFN and the attributes.
103: */
104: public void addPFN(ReplicaCatalogEntry tuple) {
105: boolean seen = false;
106: String pfn = tuple.getPFN();
107:
108: sanitize(tuple);
109:
110: //traverse through the existing PFN's to check for the
111: //same pfn
112: for (Iterator i = this .pfnIterator(); i.hasNext() && !seen;) {
113: ReplicaCatalogEntry rce = (ReplicaCatalogEntry) i.next();
114: if ((seen = pfn.equals(rce.getPFN()))) {
115: try {
116: i.remove();
117: } catch (UnsupportedOperationException uoe) {
118: //ignore for time being
119: }
120: }
121: }
122:
123: this .mPFNList.add(tuple);
124:
125: }
126:
127: /**
128: * Add a PFN and it's attributes.
129: *
130: * @param tuples the <code>List</code> object of <code>ReplicaCatalogEntry</code>
131: * objects, each containing the PFN and the attributes.
132: */
133: protected void addPFNs(List tuples) {
134: for (Iterator it = tuples.iterator(); it.hasNext();) {
135: addPFN((ReplicaCatalogEntry) it.next());
136: }
137: }
138:
139: /**
140: * Sets the LFN.
141: *
142: * @param lfn the lfn.
143: */
144: public void setLFN(String lfn) {
145: this .mLFN = lfn;
146: }
147:
148: /**
149: * Returns the associated LFN.
150: *
151: * @return lfn
152: */
153: public String getLFN() {
154: return this .mLFN;
155: }
156:
157: /**
158: * Return a PFN as a <code>ReplicaCatalogEntry</code>
159: *
160: * @param index the pfn location.
161: *
162: * @return the element at the specified position in this list.
163: *
164: * @throws IndexOutOfBoundsException - if the index is out of range (index < 0 || index >= size()).
165: */
166: public ReplicaCatalogEntry getPFN(int index) {
167: return (ReplicaCatalogEntry) this .mPFNList.get(index);
168: }
169:
170: /**
171: * Returns the list of pfn's as <code>ReplicaCatalogEntry</code> objects.
172: *
173: * @return List
174: */
175: public List getPFNList() {
176: return this .mPFNList;
177: }
178:
179: /**
180: * Returns an iterator to the list of <code>ReplicaCatalogEntry</code>
181: * objects.
182: *
183: * @return Iterator.
184: */
185: public Iterator pfnIterator() {
186: return this .mPFNList.iterator();
187: }
188:
189: /**
190: * Returns the number of pfn's associated with the lfn.
191: *
192: * @return int
193: */
194: public int getPFNCount() {
195: return this .mPFNList.size();
196: }
197:
198: /**
199: * Returns the clone of the object.
200: *
201: * @return the clone
202: */
203: public Object clone() {
204: ReplicaLocation rc;
205: try {
206: rc = (ReplicaLocation) super .clone();
207: } catch (CloneNotSupportedException e) {
208: //somewhere in the hierarch chain clone is not implemented
209: throw new RuntimeException(
210: "Clone not implemented in the base class of "
211: + this .getClass().getName(), e);
212: }
213: rc.setLFN(this .mLFN);
214:
215: //add all the RCE's
216: for (Iterator it = this .pfnIterator(); it.hasNext();) {
217: //rc.addPFN( (( ReplicaCatalogEntry )it.next()).clone() );
218: }
219: //clone is not implemented fully.
220: throw new RuntimeException("Clone not implemented for "
221: + this .getClass().getName());
222:
223: // return rc;
224: }
225:
226: /**
227: * Merges the <code>ReplicaLocation</code> object to the existing one,
228: * only if the logical filenames match.
229: *
230: * @param location is another <code>ReplicaLocations</code> to merge with.
231: *
232: * @return true if a merge was successful, false if the LFNs did not
233: * match.
234: */
235: public boolean merge(ReplicaLocation location) {
236: String lfn1 = this .getLFN();
237: String lfn2 = (location == null) ? null : location.getLFN();
238: boolean result = (lfn1 == null && lfn2 == null || lfn1 != null
239: && lfn2 != null && lfn1.equals(lfn2));
240:
241: // only merge if PFN match
242: if (result) {
243: this .addPFNs(location.getPFNList());
244: }
245:
246: return result;
247: }
248:
249: /**
250: * Returns the textual description of the data class.
251: *
252: * @return the textual description.
253: */
254: public String toString() {
255: StringBuffer sb = new StringBuffer();
256: sb.append(mLFN).append(" -> {");
257: for (Iterator it = this .pfnIterator(); it.hasNext();) {
258: sb.append(it.next());
259: sb.append(",");
260: }
261: sb.append("}");
262: return sb.toString();
263: }
264:
265: /**
266: * Sanitizes a tuple list . Sets the resource handle to a default value if not
267: * specified.
268: *
269: * @param tuples the tuple to be sanitized.
270: */
271: private void sanitize(List tuples) {
272: for (Iterator it = tuples.iterator(); it.hasNext();) {
273: this .sanitize((ReplicaCatalogEntry) it.next());
274: }
275: }
276:
277: /**
278: * Sanitizes a tuple . Sets the resource handle to a default value if not
279: * specified.
280: *
281: * @param tuple the tuple to be sanitized.
282: */
283: private void sanitize(ReplicaCatalogEntry tuple) {
284: //sanity check
285: if (tuple.getResourceHandle() == null) {
286: tuple.setResourceHandle(this.UNDEFINED_SITE_NAME);
287: }
288: }
289: }
|