001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2005, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation;
010: * version 2.1 of the License.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * This package contains documentation from OpenGIS specifications.
018: * OpenGIS consortium's work is fully acknowledged here.
019: */
020: package org.geotools.metadata.iso.citation;
021:
022: // J2SE direct dependencies
023: import java.util.Collection;
024: import java.util.Iterator;
025: import java.util.Locale;
026:
027: // OpenGIS dependencies
028: import org.opengis.metadata.citation.Citation;
029: import org.opengis.metadata.citation.OnLineFunction;
030: import org.opengis.metadata.citation.PresentationForm;
031: import org.opengis.metadata.citation.Role;
032: import org.opengis.util.InternationalString;
033: import org.opengis.referencing.crs.CRSAuthorityFactory; // For javadoc
034: import org.opengis.referencing.crs.CoordinateReferenceSystem; // For javadoc
035:
036: // Geotools dependencies
037: import org.geotools.util.SimpleInternationalString;
038:
039: /**
040: * A set of pre-defined constants and static methods working on {@linkplain Citation citations}.
041: * Pre-defined metadata constants are usually declared in implementation classes like
042: * {@link ResponsiblePartyImpl}. But citations are an exception since they are extensively
043: * referenced in the Geotools library, and handling citations requires some convenience methods.
044: * They are factored out in this {@code Citations} class for clarity.
045: * <p>
046: * Citations may be about an <cite>organisation</cite> (e.g. {@linkplain #OPEN_GIS OpenGIS}),
047: * a <cite>specification</cite> (e.g. {@linkplain #WMS}) or an <cite>authority</cite> that
048: * maintains definitions of codes (e.g. {@linkplain #EPSG}). In the later case, the citation
049: * contains an {@linkplain Citation#getIdentifiers identifier} which is the namespace of the
050: * codes maintained by the authority. For example the identifier for the {@link #EPSG} citation
051: * is {@code "EPSG"}, and EPSG codes look like {@code "EPSG:4326"}.
052: *
053: * @since 2.2
054: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/metadata/iso/citation/Citations.java $
055: * @version $Id: Citations.java 27523 2007-10-17 09:14:21Z desruisseaux $
056: * @author Martin Desruisseaux
057: * @author Jody Garnett
058: *
059: * @todo Classify the pre-defined constants using the javadoc {@code @category} tag
060: * once it will be available (targeted for J2SE 1.6).
061: */
062: public final class Citations {
063: /**
064: * Do not allows instantiation of this class.
065: */
066: private Citations() {
067: }
068:
069: ///////////////////////////////////////////////////////////////////////
070: //////// ////////
071: //////// O R G A N I S A T I O N S ////////
072: //////// ////////
073: ///////////////////////////////////////////////////////////////////////
074:
075: /**
076: * The <A HREF="http://www.opengeospatial.org">Open Geospatial consortium</A> organisation.
077: * "Open Geospatial consortium" is the new name for "OpenGIS consortium".
078: * An {@linkplain Citation#getAlternateTitles alternate title} for this citation is "OGC"
079: * (according ISO 19115, alternate titles often contain abreviations).
080: *
081: * @see ResponsiblePartyImpl#OGC
082: * @see #OPEN_GIS
083: */
084: public static final Citation OGC;
085: static {
086: final CitationImpl c = new CitationImpl(
087: ResponsiblePartyImpl.OGC);
088: c.getAlternateTitles()
089: .add(new SimpleInternationalString("OGC"));
090: // NOTE: all OGC alternate titles will be copied in OPEN_GIS as well.
091: c.getPresentationForm().add(PresentationForm.DOCUMENT_DIGITAL);
092: c.freeze();
093: OGC = c;
094: }
095:
096: /**
097: * The <A HREF="http://www.opengis.org">OpenGIS consortium</A> organisation.
098: * "OpenGIS consortium" is the old name for "Open Geospatial consortium".
099: * {@linkplain Citation#getAlternateTitles Alternate titles} for this citation are
100: * "OpenGIS" and "OGC" (according ISO 19115, alternate titles often contain abreviations).
101: *
102: * @see ResponsiblePartyImpl#OPEN_GIS
103: * @see #OGC
104: */
105: public static final Citation OPEN_GIS;
106: static {
107: final CitationImpl c = new CitationImpl(
108: ResponsiblePartyImpl.OPEN_GIS);
109: final Collection alt = c.getAlternateTitles();
110: alt.add(new SimpleInternationalString("OpenGIS"));
111: alt.addAll(OGC.getAlternateTitles());
112: c.getPresentationForm().add(PresentationForm.DOCUMENT_DIGITAL);
113: c.freeze();
114: OPEN_GIS = c;
115: }
116:
117: /**
118: * The <A HREF="http://www.esri.com">ESRI</A> organisation.
119: *
120: * @see ResponsiblePartyImpl#ESRI
121: */
122: public static final Citation ESRI;
123: static {
124: final CitationImpl c = new CitationImpl(
125: ResponsiblePartyImpl.ESRI);
126: c.addAuthority("ESRI", true);
127: c.freeze();
128: ESRI = c;
129: }
130:
131: /**
132: * The <A HREF="http://www.oracle.com">Oracle</A> organisation.
133: *
134: * @see ResponsiblePartyImpl#ORACLE
135: */
136: public static final Citation ORACLE;
137: static {
138: final CitationImpl c = new CitationImpl(
139: ResponsiblePartyImpl.ORACLE);
140: c.freeze();
141: ORACLE = c;
142: }
143:
144: /**
145: * The <A HREF="http://postgis.refractions.net">PostGIS</A> project.
146: *
147: * @see ResponsiblePartyImpl#POSTGIS
148: *
149: * @since 2.4
150: */
151: public static final Citation POSTGIS;
152: static {
153: final CitationImpl c = new CitationImpl(
154: ResponsiblePartyImpl.POSTGIS);
155: c.freeze();
156: POSTGIS = c;
157: }
158:
159: /**
160: * The <A HREF="http://www.geotools.org">Geotools</A> project.
161: *
162: * @see ResponsiblePartyImpl#GEOTOOLS
163: */
164: public static final Citation GEOTOOLS;
165: static {
166: final CitationImpl c = new CitationImpl(
167: ResponsiblePartyImpl.GEOTOOLS);
168: c.freeze();
169: GEOTOOLS = c;
170: }
171:
172: ///////////////////////////////////////////////////////////////////////
173: //////// ////////
174: //////// S P E C I F I C A T I O N S ////////
175: //////// ////////
176: ///////////////////////////////////////////////////////////////////////
177:
178: // Do not put the ...files/?artifact... link in the head sentence: it break javadoc formatting.
179: /**
180: * The Web Map Service specification. {@linkplain Citation#getAlternateTitles Alternate titles}
181: * for this citation are "WMS", "WMS 1.3.0", "OGC 04-024" and "ISO 19128". Note that the
182: * version numbers may be upgrated in future Geotools versions.
183: *
184: * @see <A HREF="http://www.opengeospatial.org/">Open Geospatial Consortium</A>
185: * @see <A HREF="http://www.opengis.org/docs/01-068r3.pdf">WMS 1.1.1 specification</A>
186: * @see <A HREF="http://portal.opengis.org/files/?artifact_id=5316">WMS 1.3.0 specification</A>
187: * @see ResponsiblePartyImpl#OGC
188: * @see OnLineResourceImpl#WMS
189: */
190: public static final Citation WMS;
191: static {
192: final CitationImpl c = new CitationImpl("Web Map Service");
193: final Collection titles = c.getAlternateTitles();
194: titles.add(new SimpleInternationalString("WMS"));
195: titles.add(new SimpleInternationalString("WMS 1.3.0"));
196: titles.add(new SimpleInternationalString("OGC 04-024"));
197: titles.add(new SimpleInternationalString("ISO 19128"));
198:
199: final Collection parties = c.getCitedResponsibleParties();
200: parties.add(ResponsiblePartyImpl.OGC);
201: parties.add(ResponsiblePartyImpl.OGC(Role.PUBLISHER,
202: OnLineResourceImpl.WMS));
203: /*
204: * The WMS specification is a model in a programming point of view, but this is not
205: * the purpose of ISO 19115 PresentationForm.MODEL_DIGITAL in my understanding. The
206: * later rather looks like the output of a numerical model (e.g. meteorological model).
207: * The WMS specification is distributed as a PDF document.
208: */
209: c.getPresentationForm().add(PresentationForm.DOCUMENT_DIGITAL);
210: c.freeze();
211: WMS = c;
212: }
213:
214: /**
215: * The <A HREF="http://www.remotesensing.org/geotiff/geotiff.html">GeoTIFF</A> specification.
216: *
217: * @see ResponsiblePartyImpl#GEOTIFF
218: */
219: public static final Citation GEOTIFF;
220: static {
221: final CitationImpl c = new CitationImpl(
222: ResponsiblePartyImpl.GEOTIFF);
223: c.getPresentationForm().add(PresentationForm.DOCUMENT_DIGITAL);
224: c.freeze();
225: GEOTIFF = c;
226: }
227:
228: /**
229: * The <A HREF="http://java.sun.com/products/java-media/jai">Java Advanced Imaging</A> library.
230: * An {@linkplain Citation#getAlternateTitles alternate title} for this citation is "JAI"
231: * (according ISO 19115, alternate titles often contain abreviations).
232: *
233: * @see ResponsiblePartyImpl#SUN_MICROSYSTEMS
234: */
235: public static final Citation JAI;
236: static {
237: final CitationImpl c = new CitationImpl("Java Advanced Imaging");
238: c.getAlternateTitles()
239: .add(new SimpleInternationalString("JAI"));
240: c.getCitedResponsibleParties().add(
241: ResponsiblePartyImpl.SUN_MICROSYSTEMS);
242: c.freeze();
243: JAI = c;
244: }
245:
246: ///////////////////////////////////////////////////////////////////////
247: //////// ////////
248: //////// C R S A U T H O R I T I E S ////////
249: //////// ////////
250: ///////////////////////////////////////////////////////////////////////
251:
252: /**
253: * The <A HREF="http://www.epsg.org">European Petroleum Survey Group</A> authority.
254: * An {@linkplain Citation#getAlternateTitles alternate title} for this citation is
255: * "EPSG" (according ISO 19115, alternate titles often contain abreviations). In
256: * addition, this citation contains the "EPSG" {@linkplain Citation#getIdentifiers identifier}
257: * for the "Authority name" {@linkplain Citation#getIdentifierTypes identifier type}.
258: * <p>
259: * This citation is used as an authority for {@linkplain CoordinateReferenceSystem coordinate
260: * reference system} identifiers. When searching an {@linkplain CRSAuthorityFactory CRS
261: * authority factory} on EPSG data, Geotools compares the {@code "EPSG"} string against the
262: * {@linkplain Citation#getIdentifiers identifiers} (or against the {@linkplain Citation#getTitle
263: * title} and {@linkplain Citation#getAlternateTitles alternate titles} if there is no identifier)
264: * using the {@link #identifierMatches(Citation,String) identifierMatches} method.
265: *
266: * @see ResponsiblePartyImpl#EPSG
267: * @see #AUTO
268: * @see #AUTO2
269: * @see #CRS
270: */
271: public static final Citation EPSG;
272: static {
273: final CitationImpl c = new CitationImpl(
274: ResponsiblePartyImpl.EPSG);
275: c.addAuthority("EPSG", true);
276: c.getPresentationForm().add(PresentationForm.TABLE_DIGITAL);
277: c.freeze();
278: EPSG = c;
279: }
280:
281: /**
282: * The <A HREF="http://www.opengis.org/docs/01-068r3.pdf">WMS 1.1.1</A> "Automatic Projections"
283: * authority. An {@linkplain Citation#getAlternateTitles alternate title} for this citation is
284: * "AUTO" (according ISO 19115, alternate titles often contain abreviations). In addition, this
285: * citation contains the "AUTO" {@linkplain Citation#getIdentifiers identifier} for the
286: * "Authority name" {@linkplain Citation#getIdentifierTypes identifier type}.
287: * <p>
288: * <strong>Warning:</strong> {@code AUTO} is different from {@link #AUTO2} used for WMS 1.3.0.
289: * <p>
290: * This citation is used as an authority for {@linkplain CoordinateReferenceSystem coordinate
291: * reference system} identifiers. When searching an {@linkplain CRSAuthorityFactory CRS
292: * authority factory} on AUTO data, Geotools compares the {@code "AUTO"} string against the
293: * {@linkplain Citation#getIdentifiers identifiers} (or against the {@linkplain Citation#getTitle
294: * title} and {@linkplain Citation#getAlternateTitles alternate titles} if there is no identifier)
295: * using the {@link #identifierMatches(Citation,String) identifierMatches} method.
296: *
297: * @see <A HREF="http://www.opengeospatial.org/">Open Geospatial Consortium</A>
298: * @see <A HREF="http://www.opengis.org/docs/01-068r3.pdf">WMS 1.1.1 specification</A>
299: * @see #WMS
300: * @see #AUTO2
301: * @see #CRS
302: * @see #EPSG
303: */
304: public static final Citation AUTO;
305: static { // Sanity check ensure that all @see tags are actually available in the metadata
306: final CitationImpl c = new CitationImpl("Automatic Projections");
307: c.addAuthority("AUTO", false);
308: /*
309: * Do not put "WMS 1.1.1" and "OGC 01-068r3" as alternative titles. They are alternative
310: * titles for the WMS specification (see the WMS constant in this class), not for the
311: * AUTO authority name.
312: */
313: final Collection parties = c.getCitedResponsibleParties();
314: parties.add(ResponsiblePartyImpl.OGC);
315: parties.add(ResponsiblePartyImpl.OGC(Role.PUBLISHER,
316: OnLineFunction.DOWNLOAD,
317: "http://www.opengis.org/docs/01-068r3.pdf"));
318: c.getPresentationForm().add(PresentationForm.DOCUMENT_DIGITAL); // See comment in WMS.
319: c.freeze();
320: AUTO = c;
321: }
322:
323: // Do not put the ...files/?artifact... link in the head sentence: it break javadoc formatting.
324: /**
325: * The WMS 1.3.0 "Automatic Projections" authority. An {@linkplain Citation#getAlternateTitles
326: * alternate title} for this citation is "AUTO2" (according ISO 19115, alternate titles often
327: * contain abreviations). In addition, this citation contains the "AUTO2"
328: * {@linkplain Citation#getIdentifiers identifier} for the "Authority name"
329: * {@linkplain Citation#getIdentifierTypes identifier type}.
330: * <p>
331: * <strong>Warning:</strong> {@code AUTO2} is different from {@link #AUTO} used for WMS 1.1.1
332: * and earlier.
333: * <p>
334: * This citation is used as an authority for {@linkplain CoordinateReferenceSystem coordinate
335: * reference system} identifiers. When searching an {@linkplain CRSAuthorityFactory CRS
336: * authority factory} on AUTO2 data, Geotools compares the {@code "AUTO2"} string against the
337: * {@linkplain Citation#getIdentifiers identifiers} (or against the {@linkplain Citation#getTitle
338: * title} and {@linkplain Citation#getAlternateTitles alternate titles} if there is no identifier)
339: * using the {@link #identifierMatches(Citation,String) identifierMatches} method.
340: *
341: * @see <A HREF="http://www.opengeospatial.org/">Open Geospatial Consortium</A>
342: * @see <A HREF="http://portal.opengis.org/files/?artifact_id=5316">WMS 1.3.0 specification</A>
343: * @see #WMS
344: * @see #AUTO
345: * @see #CRS
346: * @see #EPSG
347: */
348: public static final Citation AUTO2;
349: static {
350: final CitationImpl c = new CitationImpl("Automatic Projections");
351: c.addAuthority("AUTO2", false);
352: /*
353: * Do not put "WMS 1.3.0" and "OGC 04-024" as alternative titles. They are alternative
354: * titles for the WMS specification (see the WMS constant in this class), not for the
355: * AUTO2 authority name.
356: */
357: final Collection parties = c.getCitedResponsibleParties();
358: parties.add(ResponsiblePartyImpl.OGC);
359: parties.add(ResponsiblePartyImpl.OGC(Role.PUBLISHER,
360: OnLineResourceImpl.WMS));
361: c.getPresentationForm().add(PresentationForm.DOCUMENT_DIGITAL); // See comment in WMS.
362: c.freeze();
363: AUTO2 = c;
364: }
365:
366: // Do not put the ...files/?artifact... link in the head sentence: it break javadoc formatting.
367: /**
368: * The WMS 1.3.0 "CRS" authority. This is defined in the same document than {@link #AUTO2}.
369: *
370: * @see #WMS
371: * @see #AUTO
372: * @see #AUTO2
373: * @see #CRS
374: * @see #EPSG
375: */
376: public static final Citation CRS;
377: static {
378: final CitationImpl c = new CitationImpl("Web Map Service CRS");
379: c.addAuthority("CRS", false);
380: c.getCitedResponsibleParties().addAll(
381: AUTO2.getCitedResponsibleParties());
382: c.getPresentationForm().add(PresentationForm.DOCUMENT_DIGITAL); // See comment in WMS.
383: c.freeze();
384: CRS = c;
385: }
386:
387: /**
388: * URN in the OGC namespace. This citation contains the {@code "urn:ogc:def"} and
389: * {@code "urn:x-ogc:def"} {@linkplain Citation#getIdentifiers identifiers} for the
390: * "Authority name" {@linkplain Citation#getIdentifierTypes identifier type}.
391: *
392: * @since 2.4
393: */
394: public static final Citation URN_OGC;
395: static {
396: final CitationImpl c = new CitationImpl("URN in OGC namespace");
397: c.addAuthority("urn:ogc:def", false);
398: c.addAuthority("urn:x-ogc:def", false);
399: c.getCitedResponsibleParties().add(ResponsiblePartyImpl.OGC);
400: c.getPresentationForm().add(PresentationForm.DOCUMENT_DIGITAL);
401: c.freeze();
402: URN_OGC = c;
403: }
404:
405: /**
406: * URL in the OGC namespace. This citation contains the
407: * {@code "http://www.opengis.net"} {@linkplain Citation#getIdentifiers identifiers}
408: * for the "Authority name" {@linkplain Citation#getIdentifierTypes identifier type}.
409: *
410: * @since 2.4
411: */
412: public static final Citation HTTP_OGC;
413: static {
414: final CitationImpl c = new CitationImpl("URL in OGC namespace");
415: c.addAuthority("http://www.opengis.net", false);
416: c.getCitedResponsibleParties().add(ResponsiblePartyImpl.OGC);
417: c.getPresentationForm().add(PresentationForm.DOCUMENT_DIGITAL);
418: c.freeze();
419: HTTP_OGC = c;
420: }
421:
422: ///////////////////////////////////////////////////////////////////////
423: //////// ////////
424: //////// End of constants declarations ////////
425: //////// ////////
426: ///////////////////////////////////////////////////////////////////////
427:
428: /**
429: * List of citations declared in this class.
430: */
431: private static final Citation[] AUTHORITIES = { OGC, OPEN_GIS,
432: ESRI, ORACLE, GEOTOOLS, WMS, GEOTIFF, JAI, EPSG, AUTO,
433: AUTO2, CRS };
434:
435: /**
436: * Returns a citation of the given name. If the given name matches a {@linkplain
437: * Citation#getTitle title} or an {@linkplain Citation#getAlternateTitles alternate titles}
438: * of one of the pre-defined constants ({@link #EPSG}, {@link #GEOTIFF}, <cite>etc.</cite>),
439: * then this constant is returned. Otherwise, a new citation is created with the specified
440: * name as the title.
441: *
442: * @param title The citation title (or alternate title).
443: * @return A citation using the specified name
444: */
445: public static Citation fromName(final String title) {
446: for (int i = 0; i < AUTHORITIES.length; i++) {
447: final Citation citation = AUTHORITIES[i];
448: if (titleMatches(citation, title)) {
449: return citation;
450: }
451: }
452: return new CitationImpl(title);
453: }
454:
455: /**
456: * Returns {@code true} if at least one {@linkplain Citation#getTitle title} or
457: * {@linkplain Citation#getAlternateTitles alternate title} in {@code c1} is equals to a title
458: * or alternate title in {@code c2}. The comparaison is case-insensitive and ignores leading
459: * and trailing spaces. The titles ordering is not significant.
460: *
461: * @param c1 The first citation to compare.
462: * @param c2 the second citation to compare.
463: * @return {@code true} if at least one title or alternate title matches.
464: */
465: public static boolean titleMatches(final Citation c1,
466: final Citation c2) {
467: InternationalString candidate = c2.getTitle();
468: Iterator iterator = null;
469: do {
470: final String asString = candidate.toString(Locale.US);
471: if (titleMatches(c1, asString)) {
472: return true;
473: }
474: final String asLocalized = candidate.toString();
475: if (asLocalized != asString
476: && titleMatches(c1, asLocalized)) {
477: return true;
478: }
479: if (iterator == null) {
480: final Collection titles = c2.getAlternateTitles();
481: if (titles == null) {
482: break;
483: }
484: iterator = titles.iterator();
485: }
486: if (!iterator.hasNext()) {
487: break;
488: }
489: candidate = (InternationalString) iterator.next();
490: } while (true);
491: return false;
492: }
493:
494: /**
495: * Returns {@code true} if the {@linkplain Citation#getTitle title} or any
496: * {@linkplain Citation#getAlternateTitles alternate title} in the given citation
497: * matches the given string. The comparaison is case-insensitive and ignores leading
498: * and trailing spaces.
499: *
500: * @param citation The citation to check for.
501: * @param title The title or alternate title to compare.
502: * @return {@code true} if the title or alternate title matches the given string.
503: */
504: public static boolean titleMatches(final Citation citation,
505: String title) {
506: title = title.trim();
507: InternationalString candidate = citation.getTitle();
508: Iterator iterator = null;
509: do {
510: final String asString = candidate.toString(Locale.US);
511: if (asString.trim().equalsIgnoreCase(title)) {
512: return true;
513: }
514: final String asLocalized = candidate.toString();
515: if (asLocalized != asString
516: && asLocalized.trim().equalsIgnoreCase(title)) {
517: return true;
518: }
519: if (iterator == null) {
520: final Collection titles = citation.getAlternateTitles();
521: if (titles == null) {
522: break;
523: }
524: iterator = titles.iterator();
525: }
526: if (!iterator.hasNext()) {
527: break;
528: }
529: candidate = (InternationalString) iterator.next();
530: } while (true);
531: return false;
532: }
533:
534: /**
535: * Returns {@code true} if at least one {@linkplain Citation#getIdentifiers identifier} in
536: * {@code c1} is equals to an identifier in {@code c2}. The comparaison is case-insensitive
537: * and ignores leading and trailing spaces. The identifier ordering is not significant.
538: * <p>
539: * If (and <em>only</em> if) the citations do not contains any identifier, then this method
540: * fallback on titles comparaison using the {@link #titleMatches(Citation,Citation)
541: * titleMatches} method. This fallback exists for compatibility with client codes using
542: * citation {@linkplain Citation#getTitle titles} without identifiers.
543: *
544: * @param c1 The first citation to compare.
545: * @param c2 the second citation to compare.
546: * @return {@code true} if at least one identifier, title or alternate title matches.
547: */
548: public static boolean identifierMatches(Citation c1, Citation c2) {
549: /*
550: * If there is no identifier in both citations, fallback on title comparaisons. If there is
551: * identifiers in only one citation, make sure that this citation is the second one (c2) in
552: * order to allow at least one call to 'identifierMatches(c1, String)'.
553: */
554: Iterator iterator = c2.getIdentifiers().iterator();
555: if (!iterator.hasNext()) {
556: iterator = c1.getIdentifiers().iterator();
557: if (!iterator.hasNext()) {
558: return titleMatches(c1, c2);
559: }
560: c1 = c2;
561: c2 = null; // Just for make sure that we don't use it by accident.
562: }
563: do {
564: final String id = ((String) iterator.next()).trim();
565: if (identifierMatches(c1, id)) {
566: return true;
567: }
568: } while (iterator.hasNext());
569: return false;
570: }
571:
572: /**
573: * Returns {@code true} if any {@linkplain Citation#getIdentifiers identifiers} in the given
574: * citation matches the given string. The comparaison is case-insensitive and ignores leading
575: * and trailing spaces. If (and <em>only</em> if) the citation do not contains any identifier,
576: * then this method fallback on titles comparaison using the {@link #titleMatches(Citation,
577: * String) titleMatches} method. This fallback exists for compatibility with client codes using
578: * citation {@linkplain Citation#getTitle titles} without identifiers.
579: *
580: * @param citation The citation to check for.
581: * @param identifier The identifier to compare.
582: * @return {@code true} if the title or alternate title matches the given string.
583: */
584: public static boolean identifierMatches(final Citation citation,
585: String identifier) {
586: identifier = identifier.trim();
587: final Collection identifiers = citation.getIdentifiers();
588: for (final Iterator it = identifiers.iterator(); it.hasNext();) {
589: final String id = ((String) it.next()).trim();
590: if (identifier.equalsIgnoreCase(id)) {
591: return true;
592: }
593: }
594: if (identifiers.isEmpty()) {
595: return titleMatches(citation, identifier);
596: } else {
597: return false;
598: }
599: }
600:
601: /**
602: * Returns the shortest identifier for the specified citation, or the title if there is
603: * no identifier. This method is useful for extracting the namespace from an authority,
604: * for example {@code "EPSG"}.
605: *
606: * @since 2.4
607: */
608: public static String getIdentifier(final Citation citation) {
609: String identifier = null;
610: for (final Iterator it = citation.getIdentifiers().iterator(); it
611: .hasNext();) {
612: final String candidate = ((String) it.next()).trim();
613: final int length = candidate.length();
614: if (length != 0) {
615: if (identifier == null || length < identifier.length()) {
616: identifier = candidate;
617: }
618: }
619: }
620: if (identifier == null) {
621: identifier = String.valueOf(citation.getTitle());
622: }
623: return identifier;
624: }
625: }
|