import java.io.StringReader;
import java.net.URI;
import java.util.Iterator;

import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import junit.framework.TestCase;
import junit.textui.TestRunner;

import org.w3c.dom.Element;
import org.xml.sax.InputSource;
 
public class xml_base extends TestCase {

  static String base = "http://example.com/blog/index.atom";

  // namespace resolver for "atom:"
  static class AtomNamespaceContext implements NamespaceContext {

    public String getNamespaceURI(String prefix) {
      if (prefix.equals("atom"))
        return "http://www.w3.org/2005/Atom";
      else
        return null;
    }

    public String getPrefix(String namespace) { return null; }
    public Iterator getPrefixes(String namespace) { return null; }
  }

  // Parse a document and a fully resolved "//atom:link/@href"
  public static String parse(String stream) throws Exception {
    InputSource source = new InputSource(new StringReader(stream));
    source.setSystemId(base);

    XPath xpath = XPathFactory.newInstance().newXPath();
    xpath.setNamespaceContext(new AtomNamespaceContext());
    Element link = (Element) xpath.evaluate("//atom:link", source,
      XPathConstants.NODE);

    URI base = new URI(link.getBaseURI());
    return base.resolve(link.getAttribute("href")).toString();
  }

  public static void test_no_xml_base_abs() throws Exception {
    String feed =
      "<feed xmlns='http://www.w3.org/2005/Atom'>" +
      "  <entry>" +
      "    <link href='http://example.org/archives/2005/08/123.html'/>" +
      "  </entry>" +
      "</feed>";
    assertEquals("http://example.org/archives/2005/08/123.html", parse(feed));
  }

  public static void test_no_xml_base_rel() throws Exception {
    String feed =
      "<feed xmlns='http://www.w3.org/2005/Atom'>" +
      "  <entry>" +
      "    <link href='/archives/2005/08/123.html'/>" +
      "  </entry>" +
      "</feed>";
    assertEquals("http://example.com/archives/2005/08/123.html", parse(feed));
  }

  public static void test_xml_base_on_feed_and_entry() throws Exception {
    String feed =
      "<feed xmlns='http://www.w3.org/2005/Atom' xml:base='/archives/'>" +
      "  <entry xml:base='2005/08/'>" +
      "    <link href='123.html'/>" +
      "  </entry>" +
      "</feed>";
    assertEquals("http://example.com/archives/123.html", parse(feed));
  }

  public static void test_xml_base_overridden_on_link() throws Exception {
    String feed =
      "<feed xmlns='http://www.w3.org/2005/Atom' xml:base='/archives/'>" +
      "  <entry xml:base='2005/08/'>" +
      "    <link href='123.html' xml:base='http://example.com/'/>" +
      "  </entry>" +
      "</feed>";
    assertEquals("http://example.com/123.html", parse(feed));
  }

  public static void main(String[] args) {
    TestRunner.run(xml_base.class);

    if (args.length>=1 && args[0].equals("--properties"))
      System.getProperties().list(System.out);
  }
}

