001    /*
002     * file StpLocation.java
003     *
004     * Licensed Materials - Property of IBM
005     * Restricted Materials of IBM 
006     *
007     * com.ibm.rational.wvcm.stp.StpLocation
008     *
009     * (C) Copyright IBM Corporation 2004, 2012.  All Rights Reserved.
010     * Note to U.S. Government Users Restricted Rights:  Use, duplication or 
011     * disclosure restricted by GSA ADP  Schedule Contract with IBM Corp.
012     */
013    
014    package com.ibm.rational.wvcm.stp;
015    
016    import java.io.File;
017    import java.io.Serializable;
018    import java.net.MalformedURLException;
019    import java.util.EnumSet;
020    import java.util.Hashtable;
021    import java.util.Map;
022    
023    import javax.wvcm.Location;
024    import javax.wvcm.Resource;
025    import javax.wvcm.WvcmException;
026    
027    import com.ibm.rational.wvcm.stpex.StpExEnumeration;
028    import com.ibm.rational.wvcm.stpex.annotation.RpcEnum;
029    
030    /**
031     * An extension of the javax.wvcm Location interface that provides a
032     * programmatic representation for the location of a resource.
033     * 
034     * <p>
035     * An StpLocation instance represents a location specification that has been
036     * parsed into its various component fields. A number of different formats or
037     * <i>schemes</i> are used to express the location of various resources as a
038     * string. These schemes consist of one or more of the following fields:
039     * <i>domain</i>, <i>repository name</i>, <i>namespace</i>, and <i>object
040     * name</i>. It is the namespace field that determines the scheme being used.
041     * <p>
042     * Locations are hierarchical, with the domain field specifying the top level of
043     * the hierarchy. Within a domain, resources are partitioned into repositories.
044     * Within a repository, resources are first partitioned into namespaces, and
045     * then uniquely identified by segmented pathnames within that namespace.
046     * <p>
047     * Each scheme requires certain of the above fields to be specified. If required
048     * fields are not present, the StpLocation object will have a non-OK Status.
049     * Individual field values can be queried to determine which fields aren't
050     * present.
051     * <p>
052     * To use this StpLocation to construct a proxy, its Status must be OK.
053     * <p>
054     * When a proxy is constructed, a new StpLocation may need to be constructed, so
055     * clients must not assume that the object returned by Resource.location()
056     * or any of the StpLocation factory methods defined in StpProvider is
057     * the same object passed to the proxy factory that created the proxy.
058     * <p>
059     * The preferred scheme for specifying an object is the <i>object selector
060     * scheme</i>, which has the following structure
061     * <p> [[<i>&lt;domain></i>.][<i>&lt;namespace></i>]:] [<i>&lt;object-name></i>][&#64;[<i>&lt;repository-name></i>]]
062     * <p>
063     * The <i>&lt;object-name></i>, and <i>&lt;repository-name></i> fields are
064     * segmented names where the segments are separated by '/'s or '\'s. The
065     * permitted <i>&lt;namespace></i>s are defined by
066     * {@link StpLocation.Namespace} and the permitted <i>&lt;domain></i>s are
067     * defined by {@link StpProvider.Domain}.
068     * <p>
069     * The character '&#64;' is reserved for use as the repository field delimiter
070     * as defined above. If it is to be part of the name field, it must be escaped
071     * by preceding it with a percent sign '%'. Similarly, the characters '/' and
072     * '\' are reserved in both the name and repository fields to be used as
073     * pathname segment separators. To use them as part of a segment they, too, must
074     * be escaped using a percent sign. Use two percent signs, '%%', to include a
075     * percent sign in the name or repository field. Note that escaped characters
076     * within a field are <i>not</i> unescaped when parsed into a StpLocation.
077     * Utility methods are provided by the StpProvider class for unescaping the
078     * fields, should a client need the unadulterated image.
079     * <p>
080     * Some resources can also be referenced directly or indirectly by an absolute or
081     * relative file system pathname. As an StpLocation image, such
082     * representations are called <i>path-scheme</i> locations, which have the
083     * following structure
084     * <p> [[<i>&lt;domain></i>.][<i>&lt;namespace></i>]:] [<i>&lt;path-name></i>]
085     * <p>
086     * The path-scheme locations are further categorized by their namespace as
087     * indicated in this enumeration...
088     * <ul>
089     * <li>{@linkplain #isOk() <i>invalid</i>} namespaces: NONE, DEFAULT, INVALID,
090     * <li>{@linkplain #isFilePathScheme() <i>file path scheme</i>} namespaces:
091     * PNAME, PNAME_IMPLIED, FILE,
092     * <li>{@linkplain #isRepositoryPathScheme() <i>repository path scheme</i>}
093     * namespaces: VOB, VIEW_UUID, REPLICA_UUID, PROJ_DB, USER_DB, DB_SET, SERVER,
094     * <li>WORKSPACE,
095     * <li>{@linkplain #isUrlPathScheme() <i>URL path scheme</i>} namespaces: FILE,
096     * HTTP, HTTPS,
097     * </ul>
098     * This interface defines a predicate for each of these categories. The reader
099     * is referred to the documentation for those predicates for more information on
100     * the formation and meaning of each type of path-scheme location. Note that if
101     * a namespace is <i>not</i> one of the above path-scheme namespaces, it is an
102     * {@linkplain #isObjectSelectorScheme() <i>object selector scheme</i>}
103     * namespace.
104     * <p>
105     * %-escaping is not used in path-scheme locations.
106     */
107    public interface StpLocation extends javax.wvcm.Location
108    {
109        /**
110         * Returns the StpProvider object that created this StpLocation object
111         * 
112         * @return The StpProvider object that instantiated this instance of
113         *         StpLocation
114         */
115        StpProvider stpProvider();
116    
117        /**
118         * This class enumerates the namespaces that may appear in a location
119         * specification. Instances of the class are used to represent the namespace
120         * of the location represented by an StpLocation object.
121         * 
122         * The Namespace maps directly to the word token used in a location
123         * specification to denote the namespace of the resource named by the
124         * location. Each resource may appear in multiple namespaces.
125         */
126        public static enum Namespace implements StpExEnumeration, Serializable
127        {
128            /**
129             * A special path-scheme Namespace indicating that the namespace field
130             * of a location is unknown.
131             */
132            @RpcEnum(id=23, simpleName="INVALID")
133            INVALID("INVALID" /* NOI18N */),
134    
135            /**
136             * A special path-scheme Namespace indicating that no namespace was
137             * specified in the location specification.
138             */
139            @RpcEnum(id=26, simpleName="NONE")
140            NONE("NONE" /* NOI18N */),
141    
142            /**
143             * A special path-scheme Namespace indicating that the namespace field
144             * in the location specification was empty, which is the convention for
145             * specifying the default namespace of a repository.
146             */
147            @RpcEnum(id=8, simpleName="DEFAULT")
148            DEFAULT("DEFAULT" /* NOI18N */),
149    
150            /**
151             * The special, compound namespace used in stable selector schemes. To
152             * fully specify the stable selector scheme namespace, a resource-type
153             * string must follow the REPO word token in the location specification.
154             */
155            @RpcEnum(id=38, simpleName="repo")
156            REPO("repo" /* NOI18N */),
157    
158            /**
159             * The special, compound namespace used in the selector scheme for
160             * specification of efficiently-accessed locations. To fully specify the
161             * efficient selector scheme namespace, a resource-type string must
162             * follow the FAST word token in the location specification.
163             */
164            @RpcEnum(id=12, simpleName="fast")
165            FAST("fast" /* NOI18N */),
166    
167            /**
168             * A special file-path-scheme namespace that forces the rest of the
169             * location to be interpreted as a ClearCase P-name, a file system
170             * pathname with an optional history-mode extension.
171             */
172            @RpcEnum(id=28, simpleName="pname")
173            PNAME("pname" /* NOI18N */),
174    
175            /**
176             * A special file-path-scheme Namespace indicating a pname without an
177             * explicit PNAME prefix. Locations in the PNAME_IMPLIED namespace
178             * display simply as P-names.
179             */
180            @RpcEnum(id=29, simpleName="implicit")
181            PNAME_IMPLIED("implicit" /* NOI18N */),
182    
183            /**
184             * A repository-path-scheme Namespace for a ClearCase VOB specified
185             * directly by tag or indirectly by an entity within the VOB.
186             */
187            @RpcEnum(id=46, simpleName="vob")
188            VOB("vob" /* NOI18N */),
189    
190            /**
191             * A repository-path-scheme Namespace for a ClearCase VOB specified by
192             * its replica UUID
193             */
194            @RpcEnum(id=37, simpleName="replicauuid")
195            REPLICA_UUID("replicauuid" /* NOI18N */),
196    
197            /**
198             * A repository-path-scheme Namespace for a ClearCase VOB specified by
199             * its VOB family UUID.
200             */
201            @RpcEnum(id=51, simpleName="vobuuid")
202            VOB_UUID("vobuuid" /* NOI18N */),
203    
204            /**
205             * A repository-path-scheme Namespace for a ClearCase view specified by
206             * its UUID
207             */
208            @RpcEnum(id=45, simpleName="viewuuid")
209            VIEW_UUID("viewuuid" /* NOI18N */),
210    
211            /**
212             * A stable-selector-scheme Namespace for a ClearCase resource specified
213             * by its DBID
214             */
215            @RpcEnum(id=6, simpleName="dbid")
216            DBID("dbid" /* NOI18N */),
217    
218            /** A repository-path-scheme Namespace for a ClearQuest user database */
219            @RpcEnum(id=43, simpleName="userdb")
220            USER_DB("userdb" /* NOI18N */),
221    
222            /**
223             * A repository-path-scheme Namespace for a ClearQuest database known
224             * variously as a profile, connection, database-set, master database, or
225             * schema repository
226             */
227            @RpcEnum(id=7, simpleName="dbset")
228            DB_SET("dbset" /* NOI18N */),
229    
230            /**
231             * The user-friendly-selector-scheme Namespace for an action
232             */
233            @RpcEnum(id=0, simpleName="action")
234            ACTION("action" /* NOI18N */),
235    
236            /**
237             * The user-friendly-selector-scheme Namespace for an activity
238             */
239            @RpcEnum(id=1, simpleName="activity")
240            ACTIVITY("activity" /* NOI18N */),
241    
242            /**
243             * The user-friendly-selector-scheme Namespace for an attribute type
244             */
245            @RpcEnum(id=2, simpleName="attype")
246            ATTYPE("attype" /* NOI18N */),
247    
248            /** The user-friendly-selector-scheme Namespace for a baseline */
249            @RpcEnum(id=3, simpleName="baseline")
250            BASELINE("baseline" /* NOI18N */),
251    
252            /** The user-friendly-selector-scheme Namespace for a branch */
253            @RpcEnum(id=50, simpleName="branch")
254            BRANCH("branch" /* NOI18N */),
255    
256            /** The user-friendly-selector-scheme Namespace for a branch type */
257            @RpcEnum(id=4, simpleName="brtype")
258            BRTYPE("brtype" /* NOI18N */),
259    
260            /** The user-friendly-selector-scheme Namespace for a component */
261            @RpcEnum(id=5, simpleName="component")
262            COMPONENT("component" /* NOI18N */),
263    
264            /**
265             * The user-friendly-selector-scheme Namespace for a dynamic choice
266             * list.
267             */
268            @RpcEnum(id=10, simpleName="choicelist")
269            DYNAMIC_CHOICE_LIST("choicelist" /* NOI18N */),
270    
271            /** The user-friendly-selector-scheme Namespace for an element type */
272            @RpcEnum(id=11, simpleName="eltype")
273            ELTYPE("eltype" /* NOI18N */),
274    
275            /** The user-friendly-selector-scheme Namespace for a field definition */
276            @RpcEnum(id=13, simpleName="field")
277            FIELD_DEFINITION("field" /* NOI18N */),
278    
279            /** The URL-path-scheme and file-path-scheme Namespace for a file URL */
280            @RpcEnum(id=14, simpleName="file")
281            FILE("file" /* NOI18N */),
282    
283            /** The user-friendly-selector-scheme Namespace for a folder */
284            @RpcEnum(id=15, simpleName="folder")
285            FOLDER("folder" /* NOI18N */),
286    
287            /** The user-friendly-selector-scheme Namespace for a form */
288            @RpcEnum(id=16, simpleName="form")
289            FORM("form" /* NOI18N */),
290    
291            /** The user-friendly-selector-scheme Namespace for a group */
292            @RpcEnum(id=17, simpleName="group")
293            GROUP("group" /* NOI18N */),
294    
295            /** The user-friendly-selector-scheme Namespace for a hyperlink */
296            @RpcEnum(id=18, simpleName="hlink")
297            HLINK("hlink" /* NOI18N */),
298    
299            /** The user-friendly-selector-scheme Namespace for a hyperlink type */
300            @RpcEnum(id=19, simpleName="hltype")
301            HLTYPE("hltype" /* NOI18N */),
302    
303            /** The user-friendly-selector-scheme Namespace for a hook */
304            @RpcEnum(id=20, simpleName="hook")
305            HOOK("hook" /* NOI18N */),
306    
307            /** The user-friendly-selector-scheme Namespace for a label type */
308            @RpcEnum(id=24, simpleName="lbtype")
309            LBTYPE("lbtype" /* NOI18N */),
310    
311            /**
312             * A stable-selector-scheme Namespace for a ClearCase resource specified
313             * by its OID
314             */
315            @RpcEnum(id=27, simpleName="oid")
316            OID("oid" /* NOI18N */),
317            
318            /** The user-friendly-selector-scheme Namespace for a policy */
319            POLICY("policy" /* NOI18N */),
320    
321            /** The user-friendly-selector-scheme Namespace for a pool */
322            @RpcEnum(id=30, simpleName="pool")
323            POOL("pool" /* NOI18N */),
324    
325            /** The user-friendly-selector-scheme Namespace for a project. */
326            @RpcEnum(id=31, simpleName="project")
327            PROJECT("project" /* NOI18N */),
328    
329            /**
330             * The user-friendly-selector-scheme Namespace for a project
331             * configuration
332             */
333            @RpcEnum(id=32, simpleName="projconfig")
334            PROJECT_CONFIGURATION("projconfig" /* NOI18N */),
335    
336            /**
337             * The user-friendly-selector-scheme Namespace for a query, chart,
338             * report, report format, or query folder.
339             */
340            @RpcEnum(id=33, simpleName="query")
341            QUERY("query" /* NOI18N */),
342    
343            /**
344             * The user-friendly-selector-scheme Namespace for a record, record
345             * type, attachment folder, or attachment
346             */
347            @RpcEnum(id=34, simpleName="record")
348            RECORD("record" /* NOI18N */),
349    
350            /**
351             * The user-friendly, efficient, and stable-scheme Namespace for a
352             * ClearCase registry region.
353             */
354            @RpcEnum(id=35, simpleName="registryregion")
355            REGISTRY_REGION("registryregion" /* NOI18N */),
356    
357            /** The user-friendly-selector-scheme Namespace for a replica */
358            @RpcEnum(id=36, simpleName="replica")
359            REPLICA("replica" /* NOI18N */),
360            
361            /** The user-friendly-selector-scheme Namespace for a rolemap */
362            ROLEMAP("rolemap" /* NOI18N */),
363            
364            /** The user-friendly-selector-scheme Namespace for an rptype */
365            @RpcEnum(id=39, simpleName="rptype")
366            RPTYPE("rptype" /* NOI18N */),
367    
368            /**
369             * The user-friendly, efficient, and stable-scheme Namespace for a
370             * ClearCase storage location.
371             */
372            STORAGE_LOCATION("stgloc" /* NOI18N */),
373    
374            /** The user-friendly-selector-scheme Namespace for a stream */
375            @RpcEnum(id=40, simpleName="stream")
376            STREAM("stream" /* NOI18N */),
377    
378            /**
379             * The user-friendly, efficient, and stable-scheme Namespace for a
380             * ClearCase task.
381             */
382            @RpcEnum(id=52, simpleName="task")
383            TASK("task" /* NOI18N */),
384    
385            /** The user-friendly-selector-scheme Namespace for a trigger type */
386            @RpcEnum(id=41, simpleName="trtype")
387            TRTYPE("trtype" /* NOI18N */),
388    
389            /**
390             * The URL-path-scheme Namespace denoting a location presented in the
391             * form of an HTTP URI or URL
392             */
393            @RpcEnum(id=21, simpleName="http")
394            HTTP("http" /* NOI18N */),
395    
396            /**
397             * The URL-path-scheme Namespace denoting a location presented in the
398             * form of an HTTPS URI or URL
399             */
400            @RpcEnum(id=22, simpleName="https")
401            HTTPS("https" /* NOI18N */),
402    
403            /** The user-friendly-selector-scheme Namespace for a user */
404            @RpcEnum(id=42, simpleName="user")
405            USER("user" /* NOI18N */),
406    
407            /**
408             * The user-friendly, efficient, and stable-scheme Namespace for a view
409             * tag.
410             */
411            @RpcEnum(id=44, simpleName="viewtag")
412            VIEWTAG("viewtag" /* NOI18N */),
413    
414            /**
415             * The user-friendly, efficient, and stable-scheme Namespace for a VOB
416             * tag.
417             */
418            @RpcEnum(id=47, simpleName="vobtag")
419            VOBTAG("vobtag" /* NOI18N */),
420    
421            /**
422             * The path-scheme Namespace for a ClearCase VOB tag, treated in some
423             * senses as a directory.
424             * 
425             * Note: This namespace is an implementation detail of the server, which
426             * unfortunately must be exposed to clients.
427             * 
428             * It is not intended that clients should attempt to create resources
429             * within this namespace.  Undefined behavior is guaranteed if clients
430             * attempt this.
431             * 
432             * It is not expected that the server will return resources within this
433             * namespace.
434             */
435            @RpcEnum(id=48, simpleName="vobtagasdirectory")
436            VOB_TAG_AS_DIRECTORY("vobtagasdirectory" /* NOI18N */),
437            
438            /** The path-scheme Namespace for a workspace */
439            @RpcEnum(id=49, simpleName="workspace")
440            WORKSPACE("workspace" /* NOI18N */),
441    
442            /**
443             * The user-friendly-selector-scheme Namespace for a server;
444             * e.g. ClearCase or ClearQuest
445             */
446            @RpcEnum(id=9, simpleName="domainserver")
447            DOMAINSERVER("server" /* NOI18N */),
448            
449            /** The path-scheme for a CCRC (aka, "legacy") server */
450            @RpcEnum(id=25, simpleName="legacyserver")
451            LEGACYSERVER("legacyserver" /* NOI18N */);
452    
453            /**
454             * Returns the word token for this Namespace in the namespace field of a
455             * location specification.
456             * 
457             * @return A String containing the namespace field value that denotes
458             *         this Namespace.
459             */
460            public String toNamespaceField()
461            {
462                return m_namespaceField;
463            }
464    
465            /**
466             * Finds the Namespace enumerator from the identifier used in the
467             * namespace field of a location specification.
468             * 
469             * @param field The word token as it appears in a location namespace
470             *            field.
471             * 
472             * @return The Namespace that the namespace field identifier denotes.
473             *         Namespace.INVALID is returned if no Namespace enumerator
474             *         matches the symbol exactly.
475             */
476            public static final Namespace fromNamespaceField(String field)
477            {
478                // Force to lower case before consulting symbol map
479                String symbol = field.toLowerCase();
480    
481                Namespace namespace = g_symbolToNamespaceMap.get(symbol);
482    
483                return namespace == null? Namespace.INVALID : namespace;
484            }
485    
486            /**
487             * EnumSet definitions for the various classifications of Namespaces
488             */
489            private static EnumSet<Namespace> invalid = EnumSet.of(INVALID, NONE);
490            private static EnumSet<Namespace> valid = EnumSet.complementOf(invalid);
491            private static EnumSet<Namespace> filePathSchemes =
492                EnumSet.of(PNAME,
493                           PNAME_IMPLIED,
494                           FILE);
495            private static EnumSet<Namespace> repositoryPathSchemes =
496                EnumSet.of(VOB,
497                           VIEW_UUID,
498                           REPLICA_UUID,
499                           USER_DB,
500                           DB_SET,
501                           LEGACYSERVER);
502            private static EnumSet<Namespace> urlPathSchemes = EnumSet.of(FILE,
503                                                                          HTTP,
504                                                                          HTTPS);
505            private static EnumSet<Namespace> pathSchemes =
506                union(EnumSet.of(WORKSPACE, NONE, DEFAULT, INVALID),
507                      filePathSchemes,
508                      urlPathSchemes,
509                      repositoryPathSchemes);
510            private static EnumSet<Namespace> escapeEncoded =
511                union(EnumSet.complementOf(union(pathSchemes, invalid)),
512                      EnumSet.of(USER_DB, DB_SET));
513            private static EnumSet<Namespace> extendedNamespaces =
514                EnumSet.of(REPO, FAST);
515    
516            /**
517             * Computes the union of a set of EnumSets
518             * 
519             * @param set Two or more EnumSet<Namespace> objects to be combined
520             *            into one.
521             * @return The logical union of the given EnumSets.
522             */
523            private static EnumSet<Namespace> union(EnumSet... set)
524            {
525                EnumSet<Namespace> result = EnumSet.noneOf(Namespace.class);
526    
527                for (EnumSet s : set)
528                    result.addAll(StpException.<EnumSet<Namespace>>unchecked_cast(s));
529    
530                return result;
531            }
532            
533            /**
534             * Determines whether this namespace is valid (not NONE or INVALID).
535             * 
536             * @return <b>true</b> if this Namespace represents a valid namespace;
537             * <b>false</b> otherwise.
538             */
539            public boolean isValid()
540            {
541                return valid.contains(this);
542            }
543    
544            /**
545             * @return <b>true</b> iff this namespace prefixes a path scheme
546             */
547            public boolean isPathScheme()
548            {
549                return pathSchemes.contains(this);
550            }
551    
552            /**
553             * @return <b>true</b> iff this namespace prefixes a file path scheme.
554             */
555            public boolean isFilePathScheme()
556            {
557                return filePathSchemes.contains(this);
558            }
559    
560    
561            /**
562             * @return <b>true</b> iff this namespace prefixes a path scheme
563             *         selector for the name of a repository (or repository-like
564             *         entity not in a repository). Said path is the value of the
565             *         Repo field rather than the Name field of an StpLocation.
566             */
567            public boolean isRepositoryPathScheme()
568            {
569                return repositoryPathSchemes.contains(this);
570            }
571    
572    
573            /**
574             * @return <b>true</b> iff this namespace prefixes a path scheme
575             *         selector expressed as a URL or URI. The complete URI,
576             *         including this prefix is contained wholly within the Name
577             *         field of the StpLocation
578             */
579            public boolean isUrlPathScheme()
580            {
581                return urlPathSchemes.contains(this);
582            }
583    
584            /**
585             * @return <b>true</b> iff this namespace requires additional segments
586             *         to complete its specification.
587             */
588            public boolean isExtendedNamespace()
589            {
590                return extendedNamespaces.contains(this);
591            }
592    
593            /**
594             * @return Whether or not the name field of a location specification
595             *         prefixed by this namespace should be %-escaped encoded.
596             */
597            public boolean isEscapeEncoded()
598            {
599                return escapeEncoded.contains(this);
600            }
601    
602            /**
603             * Creates a new Namespace object given its namespace field image.
604             * 
605             * @param symbol The identifier used in the namespace field to denote
606             *            this namespace.
607             */
608            private Namespace(String symbol)
609            {
610                m_namespaceField = symbol;
611            }
612    
613            /** A map from namespace Symbol to Namespace */
614            private static Map<String, Namespace> g_symbolToNamespaceMap =
615                new Hashtable<String, Namespace>();
616    
617            static {
618                for (Namespace n : Namespace.values())
619                    if (null != g_symbolToNamespaceMap.put(n.m_namespaceField,
620                                                           n)) {
621                        throw new IllegalArgumentException
622                        ("Duplicate Selector.Namespace symbol" /* NOI18N */);
623                    }
624            }
625    
626            /** The symbol used in a selector to denote this Namespace */
627            private String m_namespaceField;
628    
629            /** Serialization version UID */
630            private static final long serialVersionUID = -3736971155548723312L;
631        }
632    
633        /**
634         * The characters within a location specification that syntactically delimit
635         * the fields of the selector.
636         */
637        static final String FIELD_DELIMITERS = "@" /* NOI18N */;
638    
639        /**
640         * The characters within a selector field that syntactically delimit the
641         * segments of a field.
642         */
643        static final String SEGMENT_DELIMITERS = "/\\" /* NOI18N */;
644    
645        /**
646         * The characters within a selector that syntactically delimit the fields
647         * and segments embedded within the selector.
648         */
649        static final String DELIMITERS = FIELD_DELIMITERS + SEGMENT_DELIMITERS;
650    
651        /**
652         * If one of the characters of DELIMITERS is to be part of a name segment it
653         * must be protected from its syntactic interpretation by preceding it with
654         * this escape character. The escape character must also be escaped if it is
655         * to be part of a name segment.
656         */
657        static final String ESCAPE_CHAR = "%" /* NOI18N */;
658    
659        /**
660         * Overall status of this StpLocation
661         * 
662         * @return <b>true</b> if all required fields were found in the given
663         *         location specification.
664         */
665        boolean isOk();
666    
667        /**
668         * Generates an StpException object that reports the state of this
669         * StpLocation.
670         * 
671         * @return An StpException whose message reports the state of this
672         *         StpLocation. Will be <b>null</b> if this StpLocation is valid.
673         */
674        StpException status();
675    
676        /**
677         * Throws an INVALID_OBJECT_SELECTOR StpException if this StpLocation does
678         * not reflect a syntactically complete and correct location specification.
679         * 
680         * @throws StpException if any required fields are missing from the
681         *             StpLocation specification.
682         */
683        void throwIfNotOk() throws StpException;
684    
685        /**
686         * Returns whether or not this location is specified using a pathname
687         * format. Such locations specify a location as a segmented pathname
688         * following an explicit scheme prefix:
689         * <p>[<i>domain</i> .] <i>namespace</i> : <i>segmented-path</i>.
690         * <p>
691         * The segmented-path is the value of either the name field or the repo
692         * field of this StpLocation and the other field is not used and empty. The
693         * segmented path is stored in the name field unless the predicate
694         * {@link #isRepositoryPathScheme} is also <b>true</b>.
695         * <p>
696         * Included in this scheme classification are the location specifications
697         * that are not complete enough to classify more precisely; i.e. it includes
698         * the locations with the following special Namespace values.
699         * <ul>
700         * <li>NONE: The location specification did not include a scheme delimiter
701         * (":") (at least, not before the first occurrence of a character not
702         * allowed in a scheme prefix). The original input is in the name field of
703         * this StpLocation.
704         * <li>INVALID: The location specification began with a syntactically valid
705         * scheme prefix, but the spelling of the namespace subfield did not match
706         * any known namespace. The location was parsed as a path-scheme location
707         * with all text following the first ':' stored in the name field. The
708         * apparently misspelled namespace field is available from the
709         * ExtendedNamespace field of this StpLocation.
710         * <li>DEFAULT: The location specification began with a syntactically valid
711         * scheme prefix, but the namespace field was empty. The location was parsed
712         * as a path-scheme location, with all text following the first ':' stored
713         * in the name field.
714         * </ul>
715         * 
716         * @return <b>true</b> if this is a path-scheme location; <b>false</b> otherwise
717         */
718        boolean isPathScheme();
719    
720        /**
721         * Returns whether or not this location is specified using the URL path-
722         * scheme format. Such locations are formatted as standards-conforming URLs
723         * (URL-encoded). The entire URL, including the scheme-prefix of the URL,
724         * such as "http:" or "file:" is included in the name field of the
725         * StpLocation object. An optional domain field is permitted before the
726         * scheme-prefix, but it is not included in the name field. A URL path
727         * scheme is a specialized form of path scheme. The URL could designate a
728         * server, a repository, or a resource inside or outside of a repository.
729         * The URL is stored in the repo field if {@link #isRepositoryPathScheme} is
730         * <b>true</b>; otherwise it is stored in the name field.
731         * 
732         * @return <b>true</b> if this is a URL path-location; <b>false</b>
733         *         otherwise
734         */
735        boolean isUrlPathScheme();
736    
737        /**
738         * Returns whether or not this location specifies a repository using a path-
739         * scheme format. Such locations have a repository field specified as a
740         * segmented pathname (un-encoded). A repository path-scheme is a
741         * specialized form of path-scheme in which the path is found in the repo
742         * field of the StpLocation object. For all other forms of path-location the
743         * path is found in the name field of the StpLocation object.
744         * 
745         * @return <b>true</b> if this is a repository path-location; <b>false</b>
746         *         otherwise
747         */
748        boolean isRepositoryPathScheme();
749    
750        /**
751         * Returns whether or not this location is specified using the file path-
752         * scheme format. In this format, the resource location is specified in the
753         * name field of this StpLocation as a segmented pathname (using native file
754         * system encoding conventions) to a file system object, perhaps extended by
755         * a ClearCase history-mode selector. The variant of the file path location
756         * format used in the specification of this StpLocation is indicated by the
757         * value of getNamespace().
758         * <ul>
759         * <li>FILE: The "file:" URL scheme prefix was used to specify this
760         * StpLocation. Since this is also a URL path-scheme, the file-scheme prefix
761         * is included in the name field of this object. Conversion of this location
762         * to a File via {@link #getFile()} or canonical path via
763         * {@link #getCanonicalPath()} will first use the java.net.URI class to
764         * parse the file URL.
765         * <li>PNAME: This location was specified with an explicit "pname:" prefix.
766         * The "pname:" prefix is <i>not</i> included in the name field of this
767         * object; it contains only the characters following "pname:"
768         * <li>PNAME_IMPLIED: This location was not specified with an explicit
769         * "pname:" prefix but is being treated as if it were a pname. The implied
770         * "pname:" prefix is <i>not</i> included in the name field of this object
771         * nor does it appear in the string image of this StpLocation.
772         * </ul>
773         * <p>
774         * Note that this and the other predicates are purely syntactic. The user
775         * may have intended to name a file, but if it so happens that its name
776         * looks exactly like a valid object selector, it will be parsed and
777         * classified as an object selector. {@link #isObjectSelectorScheme()} will
778         * be <b>true</b> not {@link #isFilePathScheme()}. Clients wishing to
779         * interpret a location as a file path location, may always use the
780         * {@link #getFile()} or {@link #getCanonicalPath()} methods to investigate
781         * that option further. If this StpLocation isn't in the FILE or PNAME
782         * namespace, these methods will use the original input in its entirety as
783         * the intended pathname.
784         * <p>
785         * Similarly, {@link #recomposeWithNamespace(StpLocation.Namespace) 
786         * recomposeWithNamespace(Namespace.PNAME)} will "do the right thing" and
787         * force the original input into an explicit file path selector. Note,
788         * however, that in this case, the image of that StpLocation will include
789         * the "pname:" prefix.
790         * 
791         * @return <code><b>true</b></code> if this selector is most likely a
792         *         pathname to a file system object, <code><b>false</b></code> if
793         *         there is a more likely interpretation.
794         */
795        boolean isFilePathScheme();
796    
797        /**
798         * Returns whether or not this file-path scheme location uses the optional
799         * ClearCase history-mode naming syntax.
800         * 
801         * @return <b>true</b> if the name segment of this location contains
802         *         history-mode naming syntax.
803         */
804        boolean isHistoryModeScheme();
805    
806        /**
807         * Returns whether or not this location uses either a stable, fast
808         * (efficient), or user-friendly object selector scheme. Locations using the
809         * object selector format have a pre-defined namespace and separate name and
810         * repository fields.
811         * 
812         * @return <b>true</b> if this location uses the object selector format;
813         *         <b>false</b> otherwise, in which case it uses either a path
814         *         scheme.
815         */
816        boolean isObjectSelectorScheme();
817    
818        /**
819         * Returns whether or not this location uses an object selector scheme with
820         * user-friendly namespace, name, and repository fields.
821         * 
822         * @return <b>true</b> if this is an object name selector; <b>false</b>
823         *         otherwise.
824         * 
825         */
826        boolean isUserFriendlySelectorScheme();
827    
828        /**
829         * Returns whether or not this location uses an object selector scheme with
830         * a compound REPO namespace. Its name and repository fields are densely
831         * encoded for greater stability and more efficient retrieval.
832         * 
833         * @return <b>true</b> if the location uses the REPO namespace; <b> false</b>
834         *         otherwise.
835         */
836        boolean isRepoSelectorScheme();
837    
838        /**
839         * Returns whether or not this location uses an object selector scheme with
840         * a compound FAST namespace. Its name and repository fields are densely
841         * encoded for greater stability and more efficient retrieval.
842         * 
843         * @return <b>true</b> if the location uses the FAST namespace; <b> false</b>
844         *         otherwise.
845         */
846        boolean isFastSelectorScheme();
847    
848        /**
849         * Returns whether or not this location uses an object selector scheme with
850         * a compound OID namespace. Its name and repository fields are densely
851         * encoded for greater stability and more efficient retrieval.
852         * 
853         * @return <b>true</b> if the location uses the OID namespace; <b> false</b>
854         *         otherwise.
855         */
856        boolean isOidSelectorScheme();
857    
858        /**
859         * Returns the StpLocation.Namespace of this selector.
860         * <p>
861         * The special Namespace.INVALID indicates that the namespace field was
862         * present but spelled different from any namespace known to the library.
863         * <p>
864         * The special Namespace.DEFAULT indicates that the namespace field was
865         * present but empty, indicating that the default namespace ought to be
866         * used.
867         * <p>
868         * The special Namespace.NONE indicates that the namespace field was not
869         * present (i.e. there was no ':' in the specification before the first
870         * occurrence of a character not allowed in a scheme prefix), making it
871         * quite likely that this is a file selector.
872         * <p>
873         * Namespace.HTTP, Namespace.HTTPS, and Namespace.FILE indicate that the
874         * selector used the URI/URL syntax, the entirety of which is present in the
875         * name property.
876         * <p>
877         * Namespace.PNAME indicates that the selector used the PNAME namespace
878         * prefix. The file pathname following the PNAME prefix is the value of the
879         * name field.
880         * <p>
881         * See the complete list of possible namespaces in the Namespace enum
882         * specification.
883         * 
884         * @return The namespace used in this location specification as a Namespace
885         *         object. This will never be <b>null</b>.
886         */
887        Namespace getNamespace();
888    
889        /**
890         * Returns the resource type field of a location specification if it used a
891         * compound namespace.
892         * 
893         * @return The resource type segment of this StpLocation. This field is
894         *         defined only for compound namespace locations (i.e. those that
895         *         use Namespace.REPO, Namespace.FAST, or Namespace.OID). It will be
896         *         an empty string otherwise.
897         */
898        String getResourceType();
899    
900        /**
901         * An object containing additional information associated with certain
902         * Namespace enumerators.
903         */
904        interface ExtendedNamespace
905        {
906    
907            /**
908             * @return Returns the namespace.
909             */
910            Namespace getNamespace();
911    
912            /**
913             * @return Returns the resource type portion of the compound REPO
914             *         namespace field. Returns the empty string if the namespace is
915             *         not REPO, FAST, or OID.
916             */
917            String getResourceType();
918    
919            /**
920             * The image of the extended namespace field. For Namespace.REPO, FAST,
921             * or OID, this includes the resource type subfield; for
922             * Namespace.INVALID, this is the (misspelled) namespace field as
923             * entered.
924             * 
925             * @return A String containing the image of the namespace field for this
926             *         extended namespace (without the delimiting ':'). Will be
927             *         empty if the namespace is DEFAULT and <b>null</b> if the
928             *         location specification has no namespace field separate from
929             *         the name field, i.e. if the namespace is NONE, PNAME_IMPLIED,
930             *         HTTP, HTTPS, or FILE.
931             */
932            String toNamespaceField();
933    
934            /**
935             * Generates a debug image for this ExtendedNamespace object
936             * 
937             * @return Returns the value of {@link #toNamespaceField()},
938             *         substituting "&lt;null>" for <b>null</b>.
939             */
940            public String toString();
941        }
942    
943        /**
944         * Returns an ExtendedNamespace object that, for some namespaces, contains
945         * additional information about the namespace field beyond its Namespace
946         * value.
947         * 
948         * @return For a REPO, FAST, or OID namespace, the ExtendedNamespace
949         *         specifies the resource type segment that is associated with it;
950         *         for an INVALID namespace, the ExtendedNamespace object specifies
951         *         the misspelled namespace field; for other namespaces, no
952         *         additional information is available. Will not be <b>null</b>.
953         */
954        ExtendedNamespace getExtendedNamespace();
955    
956        /**
957         * Returns the object name field specified for this location. This field is
958         * relevant and meaningful in all schemes <i>except</i> the repository-path
959         * scheme. In a repository-path scheme, it will be an empty Sting. The
960         * encoding of the returned String is unchanged from the original input.
961         * 
962         * @return An empty string for a repository-path-scheme location; otherwise
963         *         the object name field of an object selector or the pathname of a
964         *         path-scheme location. Will be never be <b> null</b>, but may be
965         *         empty.
966         */
967        String getName();
968    
969        /**
970         * The number of segments in the object name.
971         * 
972         * @return The length of the Sting array returned by
973         *         {@link #getNameSegments(int) getNameSegments(Integer.MAX_VALUE)}.
974         */
975        int getNameSegmentCount();
976    
977        /**
978         * Returns the first N segments of the name field of this location
979         * specification. If the requested number of segments is greater than the
980         * number in the name field, the entire name is returned; if zero or less,
981         * an empty array is returned.
982         * <p>
983         * Constructs a String array containing the segments of the given field. The
984         * elements of the array are the character sequences that preceded each
985         * segment delimiter plus the character sequence at the end of the field not
986         * followed by a delimiter as long as it is not empty. Thus, the array is
987         * empty if the field is empty; otherwise, the array has N+1 segments, where
988         * N is the number of segment delimiters in the field not counting the last
989         * delimiter if it appears at the end of the field.
990         * <p>
991         * The following examples illustrate the way a field is segmented.
992         * 
993         * <pre>
994         *  "" ==> {}
995         *  "fob/bar" ==> {"fob", "bar"}
996         *  "fob/" ==> {"fob"}
997         *  "fob" ==> {"fob"}
998         *  "/fob" ==> {"", "fob"}
999         *  "/" ==> {""}
1000         *  "//" ==> {"", ""}
1001         *  "fob//bar" ==> {"fob", "", "bar"}
1002         *  "http://server" ==> {"http:", "", "server"}
1003         *  "http://" ==> {"http:", ""}
1004         *  "file:///" ==> {"file", "", ""}
1005         * </pre>
1006         * 
1007         * Note that a trailing segment delimiter is "lost" only if it follows a
1008         * non-empty segment. Consequently, when reconstructing the field from the
1009         * array, segment delimiters should be inserted between each array element
1010         * and a trailing delimiter should be added only if the last segment is
1011         * empty.
1012         * 
1013         * <p>
1014         * Note: The returned segments are encoded just as they were on input to the
1015         * constructor. Any escape characters present in the field on input remain
1016         * in each returned segment. Only the unescaped segment delimiters have been
1017         * removed from the input field.
1018         * 
1019         * @param nSegs the number of segments to return
1020         * 
1021         * @return a String array containing the first nSegs segments of the name
1022         *         field of this StpLocation.
1023         */
1024        String[] getNameSegments(int nSegs);
1025    
1026        /**
1027         * Returns contiguous segments of the name field of this selector. Segments
1028         * returned are in the intersection of the specified range and the actual
1029         * range of name segments. The first segment is at index zero.
1030         * 
1031         * <p>
1032         * Note: The returned segments are encoded just as they were on input to the
1033         * constructor. Any escape characters present in the field on input remain
1034         * in each returned segment. Only the unescaped segment delimiters have been
1035         * removed from the input field.
1036         * 
1037         * @param firstSeg the first segment to include
1038         * @param lastSeg the last segment to include
1039         * 
1040         * @return the requested segments of the object name. Will never be null,
1041         *         but may be empty if the specified range includes none of the
1042         *         segments of the name field.
1043         */
1044        String[] getNameSegments(int firstSeg,
1045                                 int lastSeg);
1046    
1047        /**
1048         * Returns the repository field of this location specification. This field
1049         * is irrelevant and empty in any path scheme location that does not have a
1050         * repository field. Conversely, if this location specification specified a
1051         * repository, it will be in this field.
1052         * 
1053         * @return An empty string if there was no repository field found in the
1054         *         location specification; otherwise the image of the repository
1055         *         field (without a repository field delimiter).
1056         */
1057        String getRepo();
1058    
1059        /**
1060         * The number of segments in the repository name.
1061         * 
1062         * @return The length of the String array returned by
1063         *         {@link #getRepoSegments(int) getRepoSegments(Integer.MAX_VALUE)}.
1064         */
1065        int getRepoSegmentCount();
1066    
1067        /**
1068         * Returns the first N segments of the repository field of this location. If
1069         * the requested number of segments is greater than the number in the
1070         * repository name, the entire repository name is returned; if zero or less,
1071         * an empty array is returned.
1072         * 
1073         * <p>
1074         * Note: The returned segments are encoded just as they were on input to the
1075         * constructor. Any escape characters present in the field on input remain
1076         * in each returned segment. Only the unescaped segment delimiters have been
1077         * removed from the input field.
1078         * 
1079         * @param nSegs the number of segments to return
1080         * 
1081         * @return a String containing the first nSegs segments of the repository
1082         *         name.
1083         * 
1084         * @see #getNameSegments(int) for a description of how segments are parsed
1085         *      and counted.
1086         */
1087        String[] getRepoSegments(int nSegs);
1088    
1089        /**
1090         * Returns contiguous segments of the repository name of this location.
1091         * Segments returned are in the intersection of the specified range and the
1092         * actual range of name segments. The first segment is at index zero.
1093         * 
1094         * <p>
1095         * Note: The returned segments are encoded just as they were on input to the
1096         * constructor. Any escape characters present in the field on input remain
1097         * in each returned segment. Only the unescaped segment delimiters have been
1098         * removed from the input field.
1099         * 
1100         * @param firstSeg the first segment to include
1101         * @param lastSeg the last segment to include
1102         * 
1103         * @return the requested segments of the repository name. Will never be
1104         *         null, but may be empty if the specified range includes none of
1105         *         the segments of the name.
1106         */
1107        String[] getRepoSegments(int firstSeg,
1108                                 int lastSeg);
1109    
1110        /**
1111         * Returns the domain specified or implied by the selector. In
1112         * URL-path-scheme locations this field is optional and will be NONE if no
1113         * domain information is available. In the other formats, the value NONE
1114         * denotes the default domain.
1115         * 
1116         * @return Returns the StpProvider.Domain. Will never be <b>null</b>, but
1117         *         may be {@link StpProvider.Domain#NONE NONE} or {@link
1118         *         StpProvider.Domain#INVALID INVALID}.
1119         */
1120        StpProvider.Domain getDomain();
1121    
1122        /**
1123         * Reconstitutes the location specification from its component fields.
1124         * 
1125         * @return For a valid StpLocation, a syntactically correct location
1126         *         specification string composed from the current values for the
1127         *         namespace, name, domain, and repo fields; otherwise the location
1128         *         specification as passed to the constructor.
1129         * 
1130         * @see java.lang.Object#toString()
1131         */
1132        String toString();
1133    
1134        /**
1135         * As above, but returns a location string <i>without</i> the domain
1136         * prefix.
1137         */
1138        String toStringWithoutDomain();
1139    
1140        /**
1141         * @see java.lang.Object#equals(java.lang.Object)
1142         */
1143        boolean equals(Object arg0);
1144    
1145        /**
1146         * Uses the hash code of the composed String image
1147         * 
1148         * @see java.lang.Object#hashCode()
1149         */
1150        int hashCode();
1151    
1152        /**
1153         * Constructs an StpLocation object based on the fields of this StpLocation
1154         * with optional replacements for some of the fields. A <b>null</b>
1155         * argument generally means to use the corresponding field of this
1156         * StpLocation in the new StpLocation.
1157         * <p>
1158         * NOTE: This method does not change the host StpLocation object. But
1159         * constructs and returns a new instance of StpLocation.
1160         * 
1161         * @param namespace The namespace for the new location expressed either as
1162         *            an ExtendedNamespace object, a Namespace enumeration or as a
1163         *            String containing the resource type of a REPO namespace. If
1164         *            namespace is Namespace.NONE no namespace prefix is generated
1165         *            for the selector. If namespace is <b>null</b>, the current
1166         *            value of getExtendedNamespace() is used.
1167         * @param name The name field of the new selector. If <b>null</b>, the
1168         *            current value of getName() is used.
1169         * @param domain The StpProvider.Domain for the new selector. If null, the
1170         *            current value of getDomain() is used.
1171         * @param repo The repository field for the new selector. If <b>null</b>,
1172         *            the current value of getRepo() is used. Must be <b>null</b>
1173         *            for path-path scheme locations that are not
1174         *            repository-path-schemes. If empty, no repository field will be
1175         *            generated for the selector.
1176         * 
1177         * @return A new StpLocation composed from the current namespace, name, type
1178         *         and repo fields, optionally overwritten by the given arguments.
1179         * 
1180         * @throws StpException Thrown if the given selector String is not in the
1181         *             correct form. StpReasonCode=INVALID_OBJECT_SELECTOR
1182         */
1183        StpLocation recomposeWithMods(Object namespace,
1184                                      String name,
1185                                      StpProvider.Domain domain,
1186                                      String repo) throws StpException;
1187    
1188        /**
1189         * Constructs new location based on this location but with a replacement for
1190         * its namespace field.
1191         * 
1192         * @param namespace The namespace for the new StpLocation. If namespace is
1193         *            Namespace.NONE, no namespace prefix is generated for the
1194         *            selector. If namespace is <b>null</b>, the current value of
1195         *            Namespace is used, effectively cloning this StpLocation
1196         *            object.
1197         * 
1198         * @return An StpLocation composed from the current name, domain and repo
1199         *         fields and the specified namespace argument.
1200         * 
1201         * @throws StpException if the given selector String is not in the
1202         *             correct form. StpReasonCode=INVALID_OBJECT_SELECTOR
1203         */
1204        StpLocation recomposeWithNamespace(StpLocation.Namespace namespace)
1205            throws StpException;
1206    
1207        /**
1208         * Constructs a new location based on this location with a replacement for
1209         * its name field.
1210         * 
1211         * @param name The new selector name field. If null, the current value of
1212         *            name() is used.
1213         * 
1214         * @return The selector composed from the current namespace, domain and repo
1215         *         fields and the specified name argument.
1216         * 
1217         * @throws StpException Thrown if the given selector String is not in the
1218         *             correct form. StpReasonCode=INVALID_OBJECT_SELECTOR
1219         */
1220        StpLocation recomposeWithName(String name) throws StpException;
1221    
1222        /**
1223         * Constructs a new location based on this location with a replacement for
1224         * its repository field.
1225         * 
1226         * @param repo The new repository field for the location. If <b>null</b>,
1227         *            the current value of getRepo() is used. If empty, no
1228         *            repository field will be generated for the location.
1229         * 
1230         * @return An StpLocation composed from the current namespace, name, and
1231         *         domain fields and the specified repo argument.
1232         * 
1233         * @throws StpException Thrown if the given selector String is not in the
1234         *             correct form. StpReasonCode=INVALID_OBJECT_SELECTOR
1235         */
1236        StpLocation recomposeWithRepo(String repo) throws StpException;
1237    
1238        /**
1239         * Constructs a new location based on this location with a replacement for
1240         * its domain field.
1241         * 
1242         * @param domain The new domain for the selector. If <b>null</b>, the
1243         *            current value of getDomain() is used.
1244         * 
1245         * @return An StpLocation composed from the current namespace, name, and
1246         *         repo fields and the specified domain argument.
1247         * 
1248         * @throws StpException Thrown if the given selector String is not in the
1249         *             correct form. StpReasonCode=INVALID_OBJECT_SELECTOR
1250         */
1251        StpLocation recomposeWithDomain(StpProvider.Domain domain)
1252            throws StpException;
1253    
1254        /**
1255         * Constructs an object selector with a replacement for its resource type
1256         * field, forcing the namespace to REPO.
1257         * 
1258         * @param rType The resource type for the new location. If <b>null</b>, the
1259         *            current value of getResourceType() is used.
1260         * 
1261         * @return A stable-selector scheme StpLocation composed from the current
1262         *         name, repo and domain fields and the specified resource type.
1263         * 
1264         * @throws StpException Thrown if the given selector String is not in the
1265         *             correct form. StpReasonCode=INVALID_OBJECT_SELECTOR
1266         */
1267        StpLocation recomposeWithResourceType(String rType) throws StpException;
1268    
1269        /**
1270         * Constructs an StpLocation for a pname based on the image of this
1271         * StpLocation. The StpLocation can be constructed with or without a pname
1272         * prefix and can be assigned a StpProvider.Domain.
1273         * <p>
1274         * In most cases, the entire image of this StpLocation (as returned by
1275         * toString()) becomes the value of the name field of the returned
1276         * StpLocation even if that image includes a namespace and/or a domain
1277         * prefix. The domain prefix can be elided from the name field of the new
1278         * location by using <b>null</b> for the domain argument to this method.
1279         * <p>
1280         * To convert any ill-formed selector to an implied pname, the following
1281         * logic might be used <code><pre>
1282         * if (!myLoc.isOk()) {
1283         *      // Convert to an implied pname so that it prints as it was
1284         *      // entered, but is treated internally as an OK file path selector
1285         *      myLoc = myLoc.recomposeAsPname(false, MY_DOMAIN);
1286         * }
1287         * </pre></code>
1288         * <p>
1289         * To convert any input not already formatted as a file-path-scheme location
1290         * to an explicit pname, the following logic might be used <code><pre>
1291         * if (!(myLoc.isFilePathScheme() && myLoc.isOk())) {
1292         *      myLoc = myLoc.recomposeAsPname(true, MY_DOMAIN);
1293         * }
1294         * </pre></code>
1295         * <p>
1296         * To convert all input to an implied pname, the following logic might be
1297         * used <code><pre>
1298         *  if (myLoc.getNamespace() == Namespace.PNAME) {
1299         *      // Keep the original "pname:" prefix out of the implied pname
1300         *      // Preserve any domain data from the input. 
1301         *      myLoc = myLoc.recomposeWithNamespace(Namespace.PNAME_IMPLIED);
1302         *  } else if (myLoc.getNamespace() == Namespace.FILE) {
1303         *      // Remove any domain info from the "file:" prefix, but push the
1304         *      // rest of the "file:" prefix into the pname.
1305         *      myLoc = myLoc.recomposeAsPname(false, null);
1306         *  } else {
1307         *      // All other input not using an explicit pname: or file: prefix is
1308         *      // treated as a raw pname.
1309         *      myLoc = myLoc.recomposeAsPname(false, MY_DOMAIN);
1310         *  }
1311         *  
1312         *  // Set the domain type if not already specified.
1313         *  if (myLoc.getDomain() == Domain.NONE)
1314         *      myLoc = recomposeWithType(MY_DOMAIN);
1315         * </pre></code>
1316         * 
1317         * @param withPrefix if <b>true</b>, the namespace of the returned
1318         *            StpLocation will be Namespace.PNAME; if <b>false</b>, the
1319         *            namespace will be Namespace.PNAME_IMPLIED.
1320         * @param domain The StpProvider.Domain of the returned StpLocation. If
1321         *            <b>null</b> the StpProvider.Domain of the current StpLocation
1322         *            will be used <i>and the image of that domain will be elided
1323         *            from the pname.</i>
1324         * @return An StpLocation reconfigured as a Pname instance, explicit or
1325         *         implied as requested
1326         */
1327        StpLocation recomposeAsPname(boolean withPrefix,
1328                                     StpProvider.Domain domain) throws StpException;
1329    
1330        /**
1331         * Constructs a location suitable for addressing resources of the type
1332         * indicated by the supplied proxy class by filling in unspecified fields of
1333         * this location using provider-defined or resource-type-dependent defaults.
1334         * <p>
1335         * Note, when an StpLocation object is passed to a Provider proxy factory
1336         * method this forClass is implicitly invoked using the Class of the proxy
1337         * returned by the proxy factory method. Similarly, when an StpLocation is
1338         * passed to a method of a proxy, that method implicitly invokes forClass
1339         * using a proxy class deduced from the host proxy and the operation.
1340         * <p>
1341         * Clients need to use this method only if they want to complete/verify a
1342         * location used in some other context or more tightly than can be
1343         * determined from the proxy context.
1344         * 
1345         * @param proxyClass The Class object for the proxy interface for which this
1346         *            location is to be completed.
1347         * @return An StpLocation suitable for use with a proxy of the given class.
1348         *         The result will be this location if it is already suitable and a
1349         *         new StpLocation if not; will never be <b>null</b>.
1350         * @throws WvcmException if it is not possible to complete the location from
1351         *             available defaults or if the completed location is
1352         *             inappropriate in some other (obvious) way, such as having a
1353         *             domain or namespace inconsistent with the given class.
1354         */
1355        StpLocation forClass(Class<? extends Resource> proxyClass) throws WvcmException;
1356    
1357        /**
1358         * Returns an StpLocation whose segmented name field is one segment shorter
1359         * than the name field of this StpLocation <i>provided</i> the name field
1360         * of the resulting StpLocation would be valid. All other fields of the
1361         * StpLocation are left unchanged.
1362         * <p>
1363         * NOTE: For repository-path scheme locations this method operates on the
1364         * segmented repo field rather than the name field. But in all other
1365         * respects the behavior is the same.
1366         * <p>
1367         * For object-selector scheme locations, an empty name field is valid, but
1368         * for path-scheme locations, the name/repo field is valid only if it
1369         * contains at least one segment of the original path (even if that segment
1370         * is empty). These examples illustrate the edge cases <code><pre>
1371         *      StpLocation        |    Parent        
1372         *      -------------------+---------------
1373         *      /food              | /        
1374         *      vob:/food          | vob:/      
1375         *      http://server/path | http://server 
1376         *      file://author/path | file://author 
1377         *      http://server      | &lt;null&gt; 
1378         *      file://author      | &lt;null&gt; 
1379         *      pname:path         | &lt;null&gt;      
1380         *      file:/             | &lt;null&gt;      
1381         * </pre></code>
1382         * 
1383         * @return A new StpLocation instance; will be <b>null</b> if the name
1384         *         field of this StpLocation has no segments that can be removed.
1385         */
1386        Location parent();
1387    
1388        /**
1389         * Returns an StpLocation whose name field is the name field of this
1390         * StpLocation extended by the given child segment. All other fields are the
1391         * same as the fields of this StpLocation. For repository-path-scheme
1392         * locations, the repo field is extended rather than the name field.
1393         * <p>
1394         * Unlike most of the other methods of this class, the child() method
1395         * encodes the new child segment according to the requirements of the
1396         * scheme. Thus, this method may be used to add only one segment at a time
1397         * to the StpLocation. In any scheme, any embedded segment delimiters in the
1398         * child segment will be encoded to make them part of the segment.
1399         * <p>
1400         * Even if this method successfully returns an StpLocation, there is no
1401         * guarantee that the returned location is a valid resource location. The
1402         * returned location may be invalid even if the original location was valid.
1403         * Some resources simply do not have parents even though their location
1404         * suggests that they do.
1405         * <p>
1406         * For example, <b>field:Defect/Headline@7.0.0.0/SAMPL</b> is the location
1407         * for the description of the <b>Headline</b> field of the <b>Defect</b>
1408         * record type in the sample ClearQuest database. However, its parent
1409         * location, <b>field:Defect@7.0.0.0/SAMPL</b>, is <i>not</i> a valid
1410         * location. While this may seem to address the <b>Defect</b> record type
1411         * resource, it does not. The location for the <b>Defect</b> record type
1412         * resource is, in fact, <b><u>record</u>:Defect@7.0.0.0/SAMPL</b>, which
1413         * is in a different namespace from the parent of the field description
1414         * resource.
1415         * <p>
1416         * In general, clients are discouraged from manipulating locations to
1417         * traverse the object model. They should use the properties defined for
1418         * this purpose instead. If, for example, the client wants to traverse from
1419         * a field description to the record type of that field, then it should use
1420         * the RECORD_TYPE property of the field rather than taking the parent and
1421         * changing the namespace. Note that if the field location is a
1422         * stable-selector scheme location, simply changing the namespace of the
1423         * parent will not work.
1424         * 
1425         * @param child The new segment to be appended to the name field of this
1426         *            StpLocation. To be consistent with the Location.child method,
1427         *            it is assumed that the String is not yet encoded. It will be
1428         *            encoded as a single segment before adding it to the name
1429         *            field.
1430         * 
1431         * @return A new StpLocation with an extended name field.
1432         */
1433        Location child(String child);
1434    
1435        /**
1436         * Returns the last segment of the name field of this StpLocation. (Returns
1437         * the last segment of the repo field for repository-path-scheme locations.)
1438         * Any encoding used within the last segment is removed before returning a
1439         * value. Thus it's the case that
1440         * <b>loc.equals(loc.parent().child(loc.lastSegment()))</b> as long as
1441         * <b>loc.parent()</b> is not null.
1442         * <p>
1443         * At the root of the namespace (parent() returns &lt;null>), returns either
1444         * the name of the root or the empty string if the root is unnamed. These
1445         * examples illustrate the edge cases <code><pre>
1446         *      StpLocation        | lastSegment | parent        
1447         *      -------------------+-------------+------------- 
1448         *      /food              |   food      | /   
1449         *      /                  |  &lt;empty&gt;    | &lt;null&gt;       
1450         *      pname:/food        |   food      | pname:/
1451         *      http://server/path |   path      | http://server
1452         *      file://author/path |   path      | file://author
1453         *      http://server      |  &lt;empty&gt;    | &lt;null&gt;
1454         *      file://author      |  &lt;empty&gt;    | &lt;null&gt;
1455         *      pname:path         |   path      | &lt;null&gt;
1456         *      pname:/            |  &lt;empty&gt;    | &lt;null&gt;
1457         *      pname:\            |  &lt;empty&gt;    | &lt;null&gt;
1458         *      record:food@cq:s/u |   food      | record:@cq:s/u
1459         *      record:@cq:s/u     |  &lt;empty&gt;    | &lt;null&gt;
1460         * </pre></code>
1461         * 
1462         * @return A String containing the last segment of the name field of this
1463         *         StpLocation stripped of all encodings. Will never be null, but
1464         *         may be empty if the last segment is unnamed.
1465         */
1466        String lastSegment();
1467    
1468        /**
1469         * Interprets this StpLocation as a file-path-scheme location and returns
1470         * the <i>canonical</i> pathname for the file. If this StpLocation is not a
1471         * file-path-scheme location, the original location specification used to
1472         * construct this StpLocation is used as the pathname to be canonicalized.
1473         * <p>
1474         * For a location in the FILE namespace, this method constructs a URI from
1475         * the given file-scheme URL and then constructs a java.io.File from that
1476         * URI. Whether or not this succeeds depends on the JVM. (IBM's JVM 1.4.2,
1477         * for example, requires that the authority portion be empty.)
1478         * 
1479         * @see java.io.File#getCanonicalPath()
1480         * 
1481         * @return The canonicalized pathname for this resource. Will never be
1482         *         <b>null</b>.
1483         * 
1484         * @throws StpException if IO errors are encountered while determining the
1485         *             canonical path or converting the file-scheme URL to a File.
1486         */
1487        String getCanonicalPath() throws StpException;
1488    
1489        /**
1490         * Returns a File object that references the path defined by this
1491         * StpLocation. If this StpLocation is not a file-path-scheme location, the
1492         * original location specification used to construct this StpLocation is
1493         * used as the pathname from which the java.io.File object is constructed.
1494         * <p>
1495         * For a location in the FILE namespace, this method constructs a URI from
1496         * the given URL and then constructs a java.io.File from that URI. Whether
1497         * or not this succeeds depends on the JVM. (IBM's JVM 1.4.2, for example,
1498         * requires that the authority portion be undefined.)
1499         * 
1500         * @return A File object for the path defined by this StpLocation; Will
1501         *         never be <b>null</b>.
1502         * 
1503         * @throws MalformedURLException if the selector is a file scheme URL for
1504         *             which a File cannot be constructed.
1505         * @throws StpException
1506         * @throws IllegalStateException If {@link #isFilePathScheme()} is <b> false</b>.
1507         */
1508        File getFile() throws MalformedURLException, StpException;
1509    
1510    }