From ebc1c7588f8ce8ea5bb057911e7596b7ac9d527c Mon Sep 17 00:00:00 2001 From: Romain Deltour Date: Sun, 18 Oct 2015 10:26:48 +0200 Subject: [PATCH] Ignore explicit declarations of reserved prefixes - added a new method to `Vocab` to get the base URI of a vocabulary - In the prefix parsing utility of `VocabUtil`, check the URI associated with re-declared reserved prefix: an error is reported only if this URI is **not** the URI of the known vocabulary associated to the reserved prefix. In other words, explicit declaration of reserved prefixes is now allowed; trying to override a reserved prefix still raises an error. Fixes #585 --- .../adobe/epubcheck/vocab/AggregateVocab.java | 26 ++++++++++++++++- .../com/adobe/epubcheck/vocab/EnumVocab.java | 29 ++++++++++++------- .../adobe/epubcheck/vocab/UncheckedVocab.java | 10 +++++-- .../java/com/adobe/epubcheck/vocab/Vocab.java | 7 +++++ .../com/adobe/epubcheck/vocab/VocabUtil.java | 7 +++-- .../adobe/epubcheck/opf/OPFCheckerTest.java | 2 +- .../single/opf/invalid/prefixes-redeclare.opf | 7 +++-- 7 files changed, 69 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/adobe/epubcheck/vocab/AggregateVocab.java b/src/main/java/com/adobe/epubcheck/vocab/AggregateVocab.java index c8800f0c4..ff65946a5 100644 --- a/src/main/java/com/adobe/epubcheck/vocab/AggregateVocab.java +++ b/src/main/java/com/adobe/epubcheck/vocab/AggregateVocab.java @@ -3,13 +3,23 @@ import java.util.List; import com.google.common.base.Optional; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; public class AggregateVocab implements Vocab { private final List vocabs; - + private final String uri; + + /** + * Returns a vocabulary composed of the union of the vocabularies given as + * parameter. The given vocabularies must have the same base URI. + * + * @param vocabs + * the vocabularies to aggregate. + * @return the aggregated vocabulary. + */ public static Vocab of(Vocab... vocabs) { return new AggregateVocab(new ImmutableList.Builder().add(vocabs).build()); @@ -17,6 +27,14 @@ public static Vocab of(Vocab... vocabs) private AggregateVocab(List vocabs) { + this.uri = (!vocabs.isEmpty()) ? Strings.nullToEmpty(vocabs.get(0).getURI()) : ""; + for (Vocab vocab : vocabs) + { + if (!uri.equals(Strings.nullToEmpty(vocab.getURI()))) + { + throw new IllegalArgumentException("Aggregated vocabs must share the same base URI"); + } + } this.vocabs = vocabs; } @@ -31,4 +49,10 @@ public Optional lookup(String name) return Optional.absent(); } + @Override + public String getURI() + { + return uri; + } + } diff --git a/src/main/java/com/adobe/epubcheck/vocab/EnumVocab.java b/src/main/java/com/adobe/epubcheck/vocab/EnumVocab.java index 1b584f1ea..3a18a8454 100644 --- a/src/main/java/com/adobe/epubcheck/vocab/EnumVocab.java +++ b/src/main/java/com/adobe/epubcheck/vocab/EnumVocab.java @@ -6,6 +6,7 @@ import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.Maps.EntryTransformer; @@ -39,6 +40,7 @@ public String apply(Enum enumee) }; private final Map index; + private final String uri; /** * Creates a new vocabulary backed by the given {@link Enum} class and with @@ -70,18 +72,19 @@ public EnumVocab(final Class

clazz, final String base) */ public EnumVocab(final Class

clazz, final String base, final String prefix) { - this.index = ImmutableMap.copyOf(Maps.transformEntries( - Maps.uniqueIndex(EnumSet.allOf(clazz), ENUM_TO_NAME), - new EntryTransformer() - { + this.uri = Strings.nullToEmpty(base); + this.index = ImmutableMap + .copyOf(Maps.transformEntries(Maps.uniqueIndex(EnumSet.allOf(clazz), ENUM_TO_NAME), + new EntryTransformer() + { - @Override - public Property transformEntry(String name, P enumee) - { - return Property.newFrom(name, base, prefix, enumee); - } + @Override + public Property transformEntry(String name, P enumee) + { + return Property.newFrom(name, base, prefix, enumee); + } - })); + })); } @Override @@ -90,6 +93,12 @@ public Optional lookup(String name) return Optional.fromNullable(index.get(name)); } + @Override + public String getURI() + { + return uri; + } + /** * Returns an {@link Optional} containing the {@link Property} for the given * enum item if it is defined in this vocabulary, or {@link Optional#absent()} diff --git a/src/main/java/com/adobe/epubcheck/vocab/UncheckedVocab.java b/src/main/java/com/adobe/epubcheck/vocab/UncheckedVocab.java index 530ba5f6d..8e3a5676e 100644 --- a/src/main/java/com/adobe/epubcheck/vocab/UncheckedVocab.java +++ b/src/main/java/com/adobe/epubcheck/vocab/UncheckedVocab.java @@ -14,8 +14,8 @@ public final class UncheckedVocab implements Vocab { - private String base; - private String prefix; + private final String base; + private final String prefix; /** * Creates a new unchecked vocabulary representing properties whose URIs start @@ -44,4 +44,10 @@ public Optional lookup(String name) return Optional.of(Property.newFrom(name, base, prefix)); } + @Override + public String getURI() + { + return base; + } + } diff --git a/src/main/java/com/adobe/epubcheck/vocab/Vocab.java b/src/main/java/com/adobe/epubcheck/vocab/Vocab.java index 6394b0bca..6b8d8ef5b 100644 --- a/src/main/java/com/adobe/epubcheck/vocab/Vocab.java +++ b/src/main/java/com/adobe/epubcheck/vocab/Vocab.java @@ -20,4 +20,11 @@ public interface Vocab * in this vocabulary. */ Optional lookup(String name); + + /** + * Returns the base URI of this vocabulary. + * + * @return the base URI of this vocabulary. + */ + String getURI(); } \ No newline at end of file diff --git a/src/main/java/com/adobe/epubcheck/vocab/VocabUtil.java b/src/main/java/com/adobe/epubcheck/vocab/VocabUtil.java index 99ce854e2..1d980c590 100644 --- a/src/main/java/com/adobe/epubcheck/vocab/VocabUtil.java +++ b/src/main/java/com/adobe/epubcheck/vocab/VocabUtil.java @@ -55,8 +55,8 @@ public static Optional parseProperty(String value, Map Report report, EPUBLocation location) { - return Optional.fromNullable(Iterables.get( - parseProperties(value, vocabs, false, report, location), 0, null)); + return Optional.fromNullable( + Iterables.get(parseProperties(value, vocabs, false, report, location), 0, null)); } /** @@ -198,7 +198,8 @@ else if (forbidden.contains(uri)) } else { - if (predefined.containsKey(prefix)) + if (predefined.containsKey(prefix) + && !Strings.nullToEmpty(predefined.get(prefix).getURI()).equals(uri)) { // re-declaration of reserved prefix report.message(MessageId.OPF_007, location, prefix); diff --git a/src/test/java/com/adobe/epubcheck/opf/OPFCheckerTest.java b/src/test/java/com/adobe/epubcheck/opf/OPFCheckerTest.java index 4df78b8ea..4b773088e 100644 --- a/src/test/java/com/adobe/epubcheck/opf/OPFCheckerTest.java +++ b/src/test/java/com/adobe/epubcheck/opf/OPFCheckerTest.java @@ -487,7 +487,7 @@ public void testValidateDocumentItemNoMediaType() @Test public void testValidateRedeclaredReservedPrefixes() { - Collections.addAll(expectedWarnings, MessageId.OPF_007, MessageId.OPF_007, MessageId.OPF_007b, + Collections.addAll(expectedWarnings, MessageId.OPF_007, MessageId.OPF_007b, MessageId.OPF_007b); // should generate 2 warnings (redeclaration of reserved prefixes and // redeclaration of default vocab) diff --git a/src/test/resources/30/single/opf/invalid/prefixes-redeclare.opf b/src/test/resources/30/single/opf/invalid/prefixes-redeclare.opf index 602c37bc2..165d75eac 100644 --- a/src/test/resources/30/single/opf/invalid/prefixes-redeclare.opf +++ b/src/test/resources/30/single/opf/invalid/prefixes-redeclare.opf @@ -1,11 +1,14 @@ - + urn:uuid:550e8400-e29b-41d4-a716-4466674412314