001: /*
002: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: * [See end of file]
004: */
005:
006: package com.hp.hpl.jena.util;
007:
008: import java.io.InputStream;
009: import java.util.*;
010:
011: import com.hp.hpl.jena.JenaRuntime;
012: import com.hp.hpl.jena.vocabulary.LocationMappingVocab;
013: import com.hp.hpl.jena.rdf.model.*;
014: import com.hp.hpl.jena.shared.JenaException;
015:
016: import org.apache.commons.logging.*;
017:
018: /**
019: * Alternative locations for URIs. Maintains two maps:
020: * single item alternatives and alternative prefixes.
021: * To suggest an alternative location, first check the single items,
022: * then check the prefixes.
023: *
024: * A LocationMapper can be configured by an RDF file. The default for this
025: * is "etc/location-mapping.n3".
026: *
027: * There is a default LocationMapper which is used by the global @link{FileManager}.
028: *
029: * @see FileManager
030: *
031: * @author Andy Seaborne
032: * @version $Id: LocationMapper.java,v 1.21 2008/01/02 12:07:44 andy_seaborne Exp $
033: */
034:
035: public class LocationMapper {
036: static Log log = LogFactory.getLog(LocationMapper.class);
037: /** The default path for searching for the location mapper */
038: public static final String DEFAULT_PATH = "file:location-mapping.rdf;file:location-mapping.n3;file:location-mapping.ttl;"
039: + "file:etc/location-mapping.rdf;file:etc/location-mapping.n3;"
040: + "file:etc/location-mapping.ttl";
041: public static final String GlobalMapperSystemProperty1 = "http://jena.hpl.hp.com/2004/08/LocationMap";
042: public static final String GlobalMapperSystemProperty2 = "LocationMap";
043:
044: static String s_globalMapperPath = null;
045:
046: Map altLocations = new HashMap();
047: Map altPrefixes = new HashMap();
048:
049: static LocationMapper theMapper = null;
050:
051: /** Get the global LocationMapper */
052: public static LocationMapper get() {
053: if (theMapper == null) {
054: theMapper = new LocationMapper();
055: if (getGlobalConfigPath() != null)
056: theMapper.initFromPath(getGlobalConfigPath(), false);
057: }
058: return theMapper;
059: }
060:
061: /** Set the global lcoation mapper. (as returned by get())
062: * If called before any call to get(), then the usual default global location mapper is not created
063: * @param globalLocationMapper
064: */
065: public static void setGlobalLocationMapper(
066: LocationMapper globalLocationMapper) {
067: theMapper = globalLocationMapper;
068: }
069:
070: /** Make a location mapper from the path settings */
071: static public LocationMapper makeGlobal() {
072: LocationMapper lMap = new LocationMapper();
073: if (getGlobalConfigPath() != null)
074: lMap.initFromPath(getGlobalConfigPath(), false);
075: return lMap;
076: }
077:
078: /** Create a LocationMapper with no mapping yet */
079: public LocationMapper() {
080: }
081:
082: /** Create a LocationMapper made like another one
083: * This is a deep copy of the location and prefix maps..*/
084: public LocationMapper(LocationMapper locMapper) {
085: altLocations.putAll(locMapper.altLocations);
086: altPrefixes.putAll(locMapper.altPrefixes);
087: }
088:
089: /** Create a LocationMapper from an existing model
090: * @see com.hp.hpl.jena.vocabulary.LocationMappingVocab
091: */
092: public LocationMapper(Model model) {
093: processConfig(model);
094: }
095:
096: /** Create a LocationMapper from a config file */
097: public LocationMapper(String config) {
098: initFromPath(config, true);
099: }
100:
101: private void initFromPath(String configPath, boolean configMustExist) {
102: if (configPath == null || configPath.length() == 0) {
103: log.warn("Null configuration");
104: return;
105: }
106:
107: // Make a file manager to look for the location mapping file
108: FileManager fm = new FileManager();
109: fm.addLocatorFile();
110: fm.addLocatorClassLoader(fm.getClass().getClassLoader());
111:
112: try {
113: String uriConfig = null;
114: InputStream in = null;
115:
116: StringTokenizer pathElems = new StringTokenizer(configPath,
117: FileManager.PATH_DELIMITER);
118: while (pathElems.hasMoreTokens()) {
119: String uri = pathElems.nextToken();
120: if (uri == null || uri.length() == 0)
121: break;
122:
123: in = fm.openNoMap(uri);
124: if (in != null) {
125: uriConfig = uri;
126: break;
127: }
128: }
129:
130: if (in == null) {
131: if (!configMustExist)
132: log.debug("Failed to find configuration: "
133: + configPath);
134: return;
135: }
136: String syntax = FileUtils.guessLang(uriConfig);
137: Model model = ModelFactory.createDefaultModel();
138: model.read(in, uriConfig, syntax);
139: processConfig(model);
140: } catch (JenaException ex) {
141: LogFactory.getLog(LocationMapper.class).warn(
142: "Error in configuration file: " + ex.getMessage());
143: }
144: }
145:
146: public String altMapping(String uri) {
147: return altMapping(uri, uri);
148: }
149:
150: /** Apply mappings: first try for an exact alternative location, then
151: * try to remap by prefix, finally, try the special case of filenames
152: * in a specific base directory.
153: * @param uri
154: * @param otherwise
155: * @return The alternative location choosen
156: */
157: public String altMapping(String uri, String otherwise) {
158: if (altLocations.containsKey(uri))
159: return (String) altLocations.get(uri);
160: String newStart = null;
161: String oldStart = null;
162: for (Iterator iter = altPrefixes.keySet().iterator(); iter
163: .hasNext();) {
164: String prefix = (String) iter.next();
165: if (uri.startsWith(prefix)) {
166: String s = (String) altPrefixes.get(prefix);
167: if (newStart == null || newStart.length() < s.length()) {
168: oldStart = prefix;
169: newStart = s;
170: }
171: }
172: }
173:
174: if (newStart != null)
175: return newStart + uri.substring(oldStart.length());
176:
177: return otherwise;
178: }
179:
180: public void addAltEntry(String uri, String alt) {
181: altLocations.put(uri, alt);
182: }
183:
184: public void addAltPrefix(String uriPrefix, String altPrefix) {
185: altPrefixes.put(uriPrefix, altPrefix);
186: }
187:
188: /** Iterate over all the entries registered */
189: public Iterator listAltEntries() {
190: return altLocations.keySet().iterator();
191: }
192:
193: /** Iterate over all the prefixes registered */
194: public Iterator listAltPrefixes() {
195: return altPrefixes.keySet().iterator();
196: }
197:
198: public void removeAltEntry(String uri) {
199: altLocations.remove(uri);
200: }
201:
202: public void removeAltPrefix(String uriPrefix) {
203: altPrefixes.remove(uriPrefix);
204: }
205:
206: public String getAltEntry(String uri) {
207: return (String) altLocations.get(uri);
208: }
209:
210: public String getAltPrefix(String uriPrefix) {
211: return (String) altPrefixes.get(uriPrefix);
212: }
213:
214: static private String getGlobalConfigPath() {
215: if (s_globalMapperPath == null)
216: s_globalMapperPath = JenaRuntime.getSystemProperty(
217: GlobalMapperSystemProperty1, null);
218: if (s_globalMapperPath == null)
219: s_globalMapperPath = JenaRuntime.getSystemProperty(
220: GlobalMapperSystemProperty2, null);
221: if (s_globalMapperPath == null)
222: s_globalMapperPath = DEFAULT_PATH;
223: return s_globalMapperPath;
224: }
225:
226: public int hashCode() {
227: int x = 0;
228:
229: for (Iterator iter = altLocations.keySet().iterator(); iter
230: .hasNext();) {
231: String k = (String) iter.next();
232: String v = (String) altLocations.get(k);
233: x = x ^ k.hashCode() ^ v.hashCode();
234: }
235: for (Iterator iter = altPrefixes.keySet().iterator(); iter
236: .hasNext();) {
237: String k = (String) iter.next();
238: String v = (String) altPrefixes.get(k);
239: x = x ^ k.hashCode() ^ v.hashCode();
240: }
241: return x;
242: }
243:
244: public boolean equals(Object obj) {
245: if (!(obj instanceof LocationMapper))
246: return false;
247: LocationMapper other = (LocationMapper) obj;
248:
249: if (altLocations.size() != other.altLocations.size())
250: return false;
251:
252: if (altPrefixes.size() != other.altPrefixes.size())
253: return false;
254:
255: for (Iterator iter = altLocations.keySet().iterator(); iter
256: .hasNext();) {
257: String k = (String) iter.next();
258: String v = (String) altLocations.get(k);
259: if (!other.altLocations.get(k).equals(v))
260: return false;
261: }
262: for (Iterator iter = altPrefixes.keySet().iterator(); iter
263: .hasNext();) {
264: String k = (String) iter.next();
265: String v = (String) altPrefixes.get(k);
266: if (!other.altPrefixes.get(k).equals(v))
267: return false;
268: }
269: return true;
270: }
271:
272: public String toString() {
273: String s = "";
274: for (Iterator iter = altLocations.keySet().iterator(); iter
275: .hasNext();) {
276: String k = (String) iter.next();
277: String v = (String) altLocations.get(k);
278: s = s + "(Loc:" + k + "=>" + v + ") ";
279: }
280:
281: for (Iterator iter = altPrefixes.keySet().iterator(); iter
282: .hasNext();) {
283: String k = (String) iter.next();
284: String v = (String) altPrefixes.get(k);
285: s = s + "(Prefix:" + k + "=>" + v + ") ";
286: }
287: return s;
288: }
289:
290: public Model toModel() {
291: Model m = ModelFactory.createDefaultModel();
292: m.setNsPrefix("lmap",
293: "http://jena.hpl.hp.com/2004/08/location-mapping#");
294: toModel(m);
295: return m;
296: }
297:
298: public void toModel(Model model) {
299:
300: for (Iterator iter = altLocations.keySet().iterator(); iter
301: .hasNext();) {
302: Resource r = model.createResource();
303: Resource e = model.createResource();
304: model.add(r, LocationMappingVocab.mapping, e);
305:
306: String k = (String) iter.next();
307: String v = (String) altLocations.get(k);
308: model.add(e, LocationMappingVocab.name, k);
309: model.add(e, LocationMappingVocab.altName, v);
310: }
311:
312: for (Iterator iter = altPrefixes.keySet().iterator(); iter
313: .hasNext();) {
314: Resource r = model.createResource();
315: Resource e = model.createResource();
316: model.add(r, LocationMappingVocab.mapping, e);
317: String k = (String) iter.next();
318: String v = (String) altPrefixes.get(k);
319: model.add(e, LocationMappingVocab.prefix, k);
320: model.add(e, LocationMappingVocab.altPrefix, v);
321: }
322: }
323:
324: public void processConfig(Model m) {
325: StmtIterator mappings = m.listStatements(null,
326: LocationMappingVocab.mapping, (RDFNode) null);
327:
328: for (; mappings.hasNext();) {
329: Statement s = mappings.nextStatement();
330: Resource mapping = s.getResource();
331:
332: if (mapping.hasProperty(LocationMappingVocab.name)) {
333: try {
334: String name = mapping.getRequiredProperty(
335: LocationMappingVocab.name).getString();
336: String altName = mapping.getRequiredProperty(
337: LocationMappingVocab.altName).getString();
338: addAltEntry(name, altName);
339: log.debug("Mapping: " + name + " => " + altName);
340: } catch (JenaException ex) {
341: log.warn("Error processing name mapping: "
342: + ex.getMessage());
343: return;
344: }
345:
346: }
347:
348: if (mapping.hasProperty(LocationMappingVocab.prefix)) {
349: try {
350: String prefix = mapping.getRequiredProperty(
351: LocationMappingVocab.prefix).getString();
352: String altPrefix = mapping.getRequiredProperty(
353: LocationMappingVocab.altPrefix).getString();
354: addAltPrefix(prefix, altPrefix);
355: log.debug("Prefix mapping: " + prefix + " => "
356: + altPrefix);
357: } catch (JenaException ex) {
358: log.warn("Error processing prefix mapping: "
359: + ex.getMessage());
360: return;
361: }
362: }
363: }
364: }
365: }
366:
367: /*
368: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
369: * All rights reserved.
370: *
371: * Redistribution and use in source and binary forms, with or without
372: * modification, are permitted provided that the following conditions
373: * are met:
374: * 1. Redistributions of source code must retain the above copyright
375: * notice, this list of conditions and the following disclaimer.
376: * 2. Redistributions in binary form must reproduce the above copyright
377: * notice, this list of conditions and the following disclaimer in the
378: * documentation and/or other materials provided with the distribution.
379: * 3. The name of the author may not be used to endorse or promote products
380: * derived from this software without specific prior written permission.
381: *
382: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
383: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
384: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
385: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
386: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
387: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
388: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
389: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
390: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
391: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392: */
|