View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *  http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.any23.rdf;
    19
    20  import org.eclipse.rdf4j.model.IRI;
    21  import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
    22
    23  import java.util.Collections;
    24  import java.util.HashMap;
    25  import java.util.HashSet;
    26  import java.util.Map;
    27  import java.util.Map.Entry;
    28  import java.util.Set;
    29
    30  /**
    31   * A mapping from prefixes to namespace IRIs. Supports "volatile mappings", which will be overwritten without notice
    32   * when mappings are merged, while for normal mappings this causes an exception. This allows combining "hard" mappings
    33   * (which must be retained or something breaks) and "soft" mappings (which might be read from input RDF files and should
    34   * be retained only if they are not in conflict with the hard ones).
    35   *
    36   * @author Richard Cyganiak (richard@cyganiak.de)
    37   */
    38  public class Prefixes {
    39
    40      public static Prefixes create1(String prefix, String namespaceIRI) {
    41          Prefixeshtml#Prefixes">Prefixes result = new Prefixes();
    42          result.add(prefix, namespaceIRI);
    43          return result;
    44      }
    45
    46      public static Prefixes createFromMap(Map<String, String> prefixesToNamespaceIRIs, boolean areVolatile) {
    47          Prefixeshtml#Prefixes">Prefixes result = new Prefixes();
    48          for (Entry<String, String> entry : prefixesToNamespaceIRIs.entrySet()) {
    49              if (areVolatile) {
    50                  result.addVolatile(entry.getKey(), entry.getValue());
    51              } else {
    52                  result.add(entry.getKey(), entry.getValue());
    53              }
    54          }
    55          return result;
    56      }
    57
    58      public static Prefixes.html#Prefixes">Prefixes EMPTY = new Prefixes(Collections.<String, String> emptyMap());
    59
    60      private final Map<String, String> mappings;
    61      private final Set<String> volatilePrefixes = new HashSet<String>();
    62
    63      public Prefixes() {
    64          this(new HashMap<String, String>());
    65      }
    66
    67      public Prefixes" href="../../../../org/apache/any23/rdf/Prefixes.html#Prefixes">Prefixes(Prefixes initial) {
    68          this();
    69          add(initial);
    70      }
    71
    72      private Prefixes(Map<String, String> mappings) {
    73          this.mappings = mappings;
    74      }
    75
    76      public IRI expand(String curie) {
    77          String prefix = parsePrefix(curie);
    78          if (prefix == null || !hasPrefix(prefix)) {
    79              return null;
    80          }
    81          return SimpleValueFactory.getInstance().createIRI(getNamespaceIRIFor(prefix) + parseLocalName(curie));
    82      }
    83
    84      public String abbreviate(String uri) {
    85          for (Entry<String, String> namespace : mappings.entrySet()) {
    86              if (uri.startsWith(namespace.getValue())) {
    87                  return namespace.getKey() + ":" + uri.substring(namespace.getValue().length());
    88              }
    89          }
    90          return null;
    91      }
    92
    93      public boolean canExpand(String curie) {
    94          String prefix = parsePrefix(curie);
    95          return prefix != null && hasPrefix(prefix);
    96      }
    97
    98      public boolean canAbbreviate(String uri) {
    99          for (Entry<String, String> namespace : mappings.entrySet()) {
    100             if (uri.startsWith(namespace.getValue())) {
    101                 return true;
    102             }
    103         }
    104         return false;
    105     }
    106
    107     public String getNamespaceIRIFor(String prefix) {
    108         return mappings.get(prefix);
    109     }
    110
    111     public boolean hasNamespaceIRI(String uri) {
    112         return mappings.containsValue(uri);
    113     }
    114
    115     public boolean hasPrefix(String prefix) {
    116         return mappings.containsKey(prefix);
    117     }
    118
    119     public Set<String> allPrefixes() {
    120         return mappings.keySet();
    121     }
    122
    123     public boolean isEmpty() {
    124         return mappings.isEmpty();
    125     }
    126
    127     public void add(String prefix, String namespaceIRI) {
    128         if (isVolatile(prefix)) {
    129             volatilePrefixes.remove(prefix);
    130         } else {
    131             if (hasPrefix(prefix)) {
    132                 if (getNamespaceIRIFor(prefix).equals(namespaceIRI)) {
    133                     return; // re-assigned same prefix to same IRI, let's just ignore it
    134                 }
    135                 throw new IllegalStateException("Attempted to re-assign prefix '" + prefix + "'; clashing values '"
    136                         + getNamespaceIRIFor(prefix) + "' and '" + namespaceIRI);
    137             }
    138         }
    139         mappings.put(prefix, namespaceIRI);
    140     }
    141
    142     public void add(Prefixes other) {
    143         for (String otherPrefix : other.allPrefixes()) {
    144             if (other.isVolatile(otherPrefix)) {
    145                 addVolatile(otherPrefix, other.getNamespaceIRIFor(otherPrefix));
    146             } else {
    147                 add(otherPrefix, other.getNamespaceIRIFor(otherPrefix));
    148             }
    149         }
    150     }
    151
    152     public void removePrefix(String prefix) {
    153         mappings.remove(prefix);
    154         volatilePrefixes.remove(prefix);
    155     }
    156
    157     public Prefixes createSubset(String... prefixes) {
    158         Prefixeshtml#Prefixes">Prefixes result = new Prefixes();
    159         for (String prefix : prefixes) {
    160             if (!hasPrefix(prefix)) {
    161                 throw new IllegalArgumentException("No namespace IRI declared for prefix " + prefix);
    162             }
    163             result.add(prefix, getNamespaceIRIFor(prefix));
    164         }
    165         return result;
    166     }
    167
    168     public void addVolatile(String prefix, String namespaceIRI) {
    169         if (hasPrefix(prefix)) {
    170             return; // new prefix is volatile, so we don't overwrite the old one
    171         }
    172         mappings.put(prefix, namespaceIRI);
    173         volatilePrefixes.add(prefix);
    174     }
    175
    176     public void addVolatile(Prefixes other) {
    177         for (String otherPrefix : other.allPrefixes()) {
    178             addVolatile(otherPrefix, other.getNamespaceIRIFor(otherPrefix));
    179         }
    180     }
    181
    182     public boolean isVolatile(String prefix) {
    183         return volatilePrefixes.contains(prefix);
    184     }
    185
    186     private Map<String, String> mapUnmodifiable = null;
    187
    188     public Map<String, String> asMap() {
    189         // Optimization: Create the unmodifiable map only once, lazily
    190         if (mapUnmodifiable == null) {
    191             mapUnmodifiable = Collections.unmodifiableMap(mappings);
    192         }
    193         return mapUnmodifiable;
    194     }
    195
    196     private String parsePrefix(String curie) {
    197         int index = curie.indexOf(':');
    198         if (index == -1) {
    199             throw new IllegalArgumentException("Not a CURIE: '" + curie + "'");
    200         }
    201         return curie.substring(0, index);
    202     }
    203
    204     private String parseLocalName(String curie) {
    205         int index = curie.indexOf(':');
    206         if (index == -1) {
    207             throw new IllegalArgumentException("Not a CURIE: '" + curie + "'");
    208         }
    209         return curie.substring(index + 1);
    210     }
    211
    212 }