use of org.opengis.metadata.Identifier in project sis by apache.
the class CitationsTest method testEPSG.
/**
* Special tests dedicated to the {@link Citations#EPSG} constant. This is maybe the most important
* citation declared in the {@link Citations} class, since it is declared as the authority of almost
* all Coordinate Reference System (CRS) objects typically used by SIS.
*
* <p>Apache SIS identifies the EPSG authority with {@link Identifier} {@code "IOGP:EPSG"}.</p>
*/
@Test
public void testEPSG() {
final Identifier identifier = getSingleton(EPSG.getIdentifiers());
assertEquals("EPSG", getUnicodeIdentifier(EPSG));
assertEquals("IOGP", ((ReferenceIdentifier) identifier).getCodeSpace());
assertEquals("EPSG", identifier.getCode());
}
use of org.opengis.metadata.Identifier in project sis by apache.
the class Citations method getIdentifier.
/**
* Infers an identifier from the given citation, or returns {@code null} if no identifier has been found.
* This method removes leading and trailing {@linkplain Character#isWhitespace(int) whitespaces}.
* See {@link org.apache.sis.metadata.iso.citation.Citations#getIdentifier(Citation)}
* for the public documentation of this method.
*
* <p><b>Which method to use:</b></p>
* <ul>
* <li>For information purpose (e.g. some {@code toString()} methods), use {@code getIdentifier(…, false)}.</li>
* <li>For WKT formatting, use {@code getIdentifier(…, true)} in order to preserve formatting characters.</li>
* <li>For assigning a value to a {@code codeSpace} field, use
* {@link org.apache.sis.metadata.iso.citation.Citations#getUnicodeIdentifier(Citation)}.</li>
* </ul>
*
* Use {@code getUnicodeIdentifier(…)} method when assigning values to be returned by methods like
* {@link ReferenceIdentifier#getCodeSpace()}, since those values are likely to be compared without special
* care about ignorable identifier characters. But if the intent is to format a more complex string
* like WKT or {@code toString()}, then we suggest to use {@code getIdentifier(citation, true)} instead,
* which will produce the same result but preserving the ignorable characters, which can be useful
* for formatting purpose.
*
* @param citation the citation for which to get the identifier, or {@code null}.
* @param strict {@code true} for returning a non-null value only if the identifier is a valid Unicode identifier.
* @return a non-empty identifier for the given citation without leading or trailing whitespaces,
* or {@code null} if the given citation is null or does not declare any identifier or title.
*
* @see <a href="https://issues.apache.org/jira/browse/SIS-201">SIS-201</a>
*/
public static String getIdentifier(final Citation citation, final boolean strict) {
if (citation != null) {
// Whether 'identifier' is a Unicode identifier.
boolean isUnicode = false;
// The best identifier found so far.
String identifier = null;
// Code space of the identifier, or null if none.
String codeSpace = null;
final Iterator<? extends Identifier> it = iterator(citation.getIdentifiers());
if (it != null)
while (it.hasNext()) {
final Identifier id = it.next();
if (id != null && !isDeprecated(id)) {
final String candidate = CharSequences.trimWhitespaces(id.getCode());
if (candidate != null && !candidate.isEmpty()) {
/*
* For a non-empty identifier, verify if both the code and its codespace are valid
* Unicode identifiers. If a codespace exists, then the code does not need to begin
* with a "Unicode identifier start" (it may be a "Unicode identifier part").
*/
String cs = (id instanceof ReferenceIdentifier) ? CharSequences.trimWhitespaces(((ReferenceIdentifier) id).getCodeSpace()) : null;
if (cs == null || cs.isEmpty()) {
cs = null;
isUnicode = CharSequences.isUnicodeIdentifier(candidate);
} else {
isUnicode = CharSequences.isUnicodeIdentifier(cs);
if (isUnicode)
for (int i = 0; i < candidate.length(); ) {
final int c = candidate.codePointAt(i);
if (!Character.isUnicodeIdentifierPart(c) && (strict || (c != '.' && c != '-'))) {
/*
* Above special case for '.' and '-' characters is documented
* in the public Citations.getIdentifier(Citation) method.
*/
isUnicode = false;
break;
}
i += Character.charCount(c);
}
}
/*
* If we found a Unicode identifier, we are done and we can exit the loop.
* Otherwise retain the first identifier and continue the search for Unicode identifier.
*/
if (identifier == null || isUnicode) {
identifier = candidate;
codeSpace = cs;
if (isUnicode)
break;
}
}
}
}
/*
* If no identifier has been found, fallback on the first title or alternate title.
* We search for alternate titles because ISO specification said that those titles
* are often used for abbreviations. Again we give preference to Unicode identifiers,
* which are typically alternate titles.
*/
if (identifier == null) {
// Whitepaces removed by toString(…).
identifier = toString(citation.getTitle());
if (identifier != null) {
if (identifier.isEmpty()) {
identifier = null;
} else {
isUnicode = CharSequences.isUnicodeIdentifier(identifier);
}
}
if (!isUnicode) {
final Iterator<? extends InternationalString> iterator = iterator(citation.getAlternateTitles());
if (iterator != null)
while (iterator.hasNext()) {
final String candidate = toString(iterator.next());
if (candidate != null && !candidate.isEmpty()) {
isUnicode = CharSequences.isUnicodeIdentifier(candidate);
if (identifier == null || isUnicode) {
identifier = candidate;
if (isUnicode)
break;
}
}
}
}
}
/*
* Finished searching in the identifiers, title and alternate titles. If the identifier that
* we found is not a valid Unicode identifier, we will return it only if the caller did not
* asked for strictly valid Unicode identifier.
*/
if (isUnicode || !strict) {
if (codeSpace != null && !isEPSG(codeSpace, identifier)) {
return codeSpace + (strict ? '_' : DEFAULT_SEPARATOR) + identifier;
} else {
return identifier;
}
}
}
return null;
}
use of org.opengis.metadata.Identifier in project sis by apache.
the class Citations method identifierMatches.
/**
* Returns {@code true} if the two citations have at least one identifier in common,
* ignoring case and non-alphanumeric characters. If and <em>only</em> if the citations
* do not contain any identifier, then this method fallback on titles comparison.
* See {@link org.apache.sis.metadata.iso.citation.Citations#identifierMatches(Citation, Citation)}
* for the public documentation of this method.
*
* @param c1 the first citation to compare, or {@code null}.
* @param c2 the second citation to compare, or {@code null}.
* @return {@code true} if both arguments are non-null, and at least one identifier matches.
*/
public static boolean identifierMatches(Citation c1, Citation c2) {
if (c1 != null && c2 != null) {
if (c1 == c2) {
// Optimisation for a common case.
return true;
}
/*
* If there is no identifier in both citations, fallback on title comparisons.
* If there is identifiers in only one citation, make sure that this citation
* is the second one (c2) in order to allow at least one call to
* 'identifierMatches(c1, String)'.
*/
Iterator<? extends Identifier> iterator = iterator(c2.getIdentifiers());
if (iterator == null) {
iterator = iterator(c1.getIdentifiers());
if (iterator == null) {
return titleMatches(c1, c2);
}
c1 = c2;
}
do {
final Identifier id = iterator.next();
if (id != null && identifierMatches(c1, id, id.getCode())) {
return true;
}
} while (iterator.hasNext());
}
return false;
}
use of org.opengis.metadata.Identifier in project sis by apache.
the class Validator method addViolationReport.
/**
* Adds a report for a constraint violation. If the given {@code report} is {@code null}, then this method creates
* a new {@link DefaultDomainConsistency} instance with the measure identification set to the property name.
*
* <div class="note"><b>Note:</b>
* setting {@code measureIdentification} to the property name may look like a departure from ISO intent,
* since the former should be an identification of the <em>quality measurement</em> rather then the measure itself.
* (setting {@code measureDescription} to {@code type.getDescription()} would probably be wrong for that reason).
* However {@code measureIdentification} is only an identifier, not a full description of the quality measurement
* We are not strictly forbidden to use the same identifier for both the quality measurement than the measurement
* itself. However strictly speaking, maybe we should use a different scope.</div>
*
* @param report where to add the result, or {@code null} if not yet created.
* @param type description of the property for which a constraint violation has been found.
* @param explanation explanation of the constraint violation.
* @return the {@code report}, or a new report if {@code report} was null.
*/
private AbstractElement addViolationReport(AbstractElement report, final AbstractIdentifiedType type, final InternationalString explanation) {
if (report == null) {
final GenericName name = type.getName();
report = new DefaultDomainConsistency();
// Do not invoke report.setMeasureDescription(type.getDescription()) - see above javadoc.
report.setMeasureIdentification(name instanceof Identifier ? (Identifier) name : new NamedIdentifier(name));
report.setEvaluationMethodType(EvaluationMethodType.DIRECT_INTERNAL);
quality.getReports().add(report);
}
report.getResults().add(new DefaultConformanceResult(null, explanation, false));
return report;
}
use of org.opengis.metadata.Identifier in project sis by apache.
the class ModifiableIdentifierMap method store.
/**
* Sets the identifier associated with the given authority, without processing for special cases.
*
* @param <T> the identifier type.
* @param authority the namespace with which the given identifier is to be associated.
* @param value the identifier to be associated with the given namespace.
* @return the previous identifier associated with {@code authority}, or {@code null}
* if there was no mapping of the specialized type for {@code authority}.
*/
private <T> T store(final IdentifierSpace<T> authority, final T value) {
ArgumentChecks.ensureNonNull("authority", authority);
T old = null;
final Iterator<? extends Identifier> it = identifiers.iterator();
while (it.hasNext()) {
final Identifier identifier = it.next();
if (identifier == null) {
// Opportunist cleaning, but should not happen.
it.remove();
} else if (Objects.equals(authority, identifier.getAuthority())) {
if (identifier instanceof SpecializedIdentifier<?>) {
@SuppressWarnings("unchecked") final SpecializedIdentifier<T> id = (SpecializedIdentifier<T>) identifier;
if (old == null) {
old = id.value;
}
if (value != null) {
id.value = value;
return old;
/*
* No need to suppress other occurrences of the key (if any)
* because we made a replacement in the first entry, so the
* new value will be visible by the getter methods.
*/
}
}
it.remove();
/*
* Continue the iteration in order to remove all other occurrences,
* in order to ensure that the getter methods will see the new value.
*/
}
}
if (value != null) {
identifiers.add(new SpecializedIdentifier<>(authority, value));
}
return old;
}
Aggregations