package nl.ipo.cds.validation.gml.codelists; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.methods.GetMethod; import com.sun.syndication.feed.synd.SyndEntry; import com.sun.syndication.feed.synd.SyndFeed; import com.sun.syndication.io.FeedException; import com.sun.syndication.io.SyndFeedInput; import com.sun.syndication.io.XmlReader; public class AtomCodeListFactory extends CachingCodeListFactory { private final static String ATOM_CONTENT_TYPE = "application/atom+xml"; private final HttpClient httpClient; private final Map<String, String> codeSpaceUrlMap; private final String language; public AtomCodeListFactory() { this("en", Collections.<String, String> emptyMap()); } public AtomCodeListFactory(final String language) { this(language, Collections.<String, String> emptyMap()); } public AtomCodeListFactory(final Map<String, String> codeSpaceUrlMap) { this("en", codeSpaceUrlMap); } public AtomCodeListFactory(final String language, final Map<String, String> codeSpaceUrlMap) { this.language = language; this.codeSpaceUrlMap = new HashMap<String, String>(codeSpaceUrlMap); this.httpClient = new HttpClient(); } @Override protected CodeList doGetCodeList(final String codeSpace) throws CodeListException { final String url; if (codeSpaceUrlMap.get(codeSpace) != null && !codeSpaceUrlMap.get(codeSpace).trim().isEmpty()) { url = codeSpaceUrlMap.get(codeSpace); } else { url = codeSpace; } // Fetch the codeList: final GetMethod get = new GetMethod(url); get.addRequestHeader("Accept", ATOM_CONTENT_TYPE); get.addRequestHeader("Accept-Language", language); try { httpClient.executeMethod(get); final SyndFeedInput input = new SyndFeedInput(); final SyndFeed feed = input.build(new XmlReader(get.getResponseBodyAsStream())); return new AtomCodeList(codeSpace, feed); } catch (HttpException e) { throw new CodeListException(codeSpace, url, String.format("Unable to fetch code list: %s", url), e); } catch (IOException e) { throw new CodeListException(codeSpace, url, String.format("Unable to read code list: %s", url), e); } catch (IllegalArgumentException e) { throw new CodeListException(codeSpace, url, e); } catch (FeedException e) { throw new CodeListException(codeSpace, url, String.format("Invalid code list feed: %s", url), e); } finally { get.releaseConnection(); } } private static class AtomCodeList implements CodeList { private final String codeSpace; private final Set<String> values = new HashSet<>(); public AtomCodeList(final String codeSpace, final SyndFeed feed) { this.codeSpace = codeSpace; @SuppressWarnings("unchecked") final List<SyndEntry> entries = (List<SyndEntry>) feed.getEntries(); for (final SyndEntry entry : entries) { if (entry.getUri().startsWith(feed.getUri())) { String id = entry.getUri().substring(feed.getUri().length()); if (id.startsWith("/")) { id = id.substring(1); } values.add(id); } else { values.add(entry.getTitle()); } } } @Override public String getCodeSpace() { return codeSpace; } @Override public Set<String> getCodes() { return Collections.unmodifiableSet(values); } @Override public boolean hasCode(final String code) { return values.contains(code); } } }