001/*
002 * (c) Copyright 2010 University of Bristol
003 * All rights reserved.
004 * [See end of file]
005 */
006package net.rootdev.javardfa.uri;
007
008import java.util.LinkedList;
009import java.util.List;
010import java.util.Set;
011import javax.xml.namespace.QName;
012import javax.xml.stream.events.Attribute;
013import javax.xml.stream.events.StartElement;
014import net.rootdev.javardfa.Constants;
015import net.rootdev.javardfa.EvalContext;
016import net.rootdev.javardfa.Resolver;
017import net.rootdev.javardfa.Setting;
018
019/**
020 * This uses the RDFa 1.0 URI logic
021 *
022 * @author pldms
023 */
024public class URIExtractor10 implements URIExtractor {
025    private Set<Setting> settings;
026    private final Resolver resolver;
027
028    public URIExtractor10(Resolver resolver) {
029        this.resolver = resolver;
030    }
031
032    public void setSettings(Set<Setting> settings) {
033        this.settings = settings;
034    }
035    
036    public String getURI(StartElement element, QName attrName, EvalContext context) {
037        Attribute attr = element.getAttributeByName(attrName);
038        if (attr == null) return null;
039        
040        if (attrName.equals(Constants.href) || attrName.equals(Constants.src)) // A URI
041        {
042            if (attr.getValue().length() == 0) {
043                return context.getBase();
044            } else {
045                return resolver.resolve(context.getBase(), attr.getValue());
046            }
047        }
048        if (attrName.equals(Constants.about) || attrName.equals(Constants.resource)) // Safe CURIE or URI
049        {
050            return expandSafeCURIE(element, attr.getValue(), context);
051        }
052        if (attrName.equals(Constants.datatype)) // A CURIE
053        {
054            String val = attr.getValue();
055            if (val.length() == 0) {
056                return "";
057            }
058            else {
059                return expandCURIE(element, attr.getValue(), context);
060            }
061        }
062        throw new RuntimeException("Unexpected attribute: " + attr);
063    }
064    
065    public List<String> getURIs(StartElement element, QName attrName, EvalContext context) {
066        Attribute attr = element.getAttributeByName(attrName);
067        if (attr == null) return null;
068        
069        List<String> uris = new LinkedList<String>();
070        String[] curies = attr.getValue().split("\\s+");
071        boolean permitReserved = Constants.rel.equals(attr.getName()) ||
072                Constants.rev.equals(attr.getName());
073        for (String curie : curies) {
074            if (Constants.SpecialRels.contains(curie.toLowerCase())) {
075                if (permitReserved)
076                    uris.add("http://www.w3.org/1999/xhtml/vocab#" + curie.toLowerCase());
077            } else {
078                String uri = expandCURIE(element, curie, context);
079                if (uri != null) {
080                    uris.add(uri);
081                }
082            }
083        }
084        return uris;
085    }
086
087    public String expandCURIE(StartElement element, String value, EvalContext context) {
088        if (value.startsWith("_:")) {
089            if (!settings.contains(Setting.ManualNamespaces)) return value;
090            if (element.getNamespaceURI("_") == null) return value;
091        }
092        if (settings.contains(Setting.FormMode) && // variable
093                value.startsWith("?")) {
094            return value;
095        }
096        int offset = value.indexOf(":") + 1;
097        if (offset == 0) {
098            //throw new RuntimeException("Is this a curie? \"" + value + "\"");
099            return null;
100        }
101        String prefix = value.substring(0, offset - 1);
102
103        // Apparently these are not allowed to expand
104        if ("xml".equals(prefix) || "xmlns".equals(prefix)) return null;
105
106        String namespaceURI = prefix.length() == 0 ? "http://www.w3.org/1999/xhtml/vocab#" : element.getNamespaceURI(prefix);
107        if (namespaceURI == null) {
108            return null;
109            //throw new RuntimeException("Unknown prefix: " + prefix);
110        }
111        
112        return namespaceURI + value.substring(offset);
113    }
114
115    public String expandSafeCURIE(StartElement element, String value, EvalContext context) {
116        if (value.startsWith("[") && value.endsWith("]")) {
117            return expandCURIE(element, value.substring(1, value.length() - 1), context);
118        } else {
119            if (value.length() == 0) {
120                return context.getBase();
121            }
122
123            if (settings.contains(Setting.FormMode) &&
124                    value.startsWith("?")) {
125                return value;
126            }
127
128            return resolver.resolve(context.getBase(), value);
129        }
130    }
131
132    public String resolveURI(String uri, EvalContext context) {
133        return resolver.resolve(context.getBase(), uri);
134    }
135
136}
137
138/*
139 * (c) Copyright 2010 University of Bristol
140 * All rights reserved.
141 *
142 * Redistribution and use in source and binary forms, with or without
143 * modification, are permitted provided that the following conditions
144 * are met:
145 * 1. Redistributions of source code must retain the above copyright
146 *    notice, this list of conditions and the following disclaimer.
147 * 2. Redistributions in binary form must reproduce the above copyright
148 *    notice, this list of conditions and the following disclaimer in the
149 *    documentation and/or other materials provided with the distribution.
150 * 3. The name of the author may not be used to endorse or promote products
151 *    derived from this software without specific prior written permission.
152 *
153 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
154 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
155 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
156 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
157 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
158 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
159 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
160 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
161 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
162 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
163 */