package org.atomnuke.atom.io.reader.sax;
import java.net.URI;
import org.atomnuke.atom.io.ReaderResult;
import org.atomnuke.atom.model.Type;
import org.atomnuke.atom.model.builder.AuthorBuilder;
import org.atomnuke.atom.model.builder.CategoryBuilder;
import org.atomnuke.atom.model.builder.EntryBuilder;
import org.atomnuke.atom.model.builder.FeedBuilder;
import org.atomnuke.atom.model.builder.GeneratorBuilder;
import org.atomnuke.atom.model.builder.LinkBuilder;
import org.atomnuke.atom.model.builder.PersonConstructBuilder;
import org.atomnuke.atom.model.builder.DateConstructBuilder;
import org.atomnuke.atom.model.builder.IconBuilder;
import org.atomnuke.atom.model.builder.IdBuilder;
import org.atomnuke.atom.model.builder.LogoBuilder;
import org.atomnuke.atom.model.builder.RightsBuilder;
import org.atomnuke.atom.model.builder.SimpleContentBuilder;
import org.atomnuke.atom.model.builder.SubtitleBuilder;
import org.atomnuke.atom.model.builder.SummaryBuilder;
import org.atomnuke.atom.model.builder.TitleBuilder;
import org.atomnuke.atom.model.builder.TypedContentBuilder;
import org.atomnuke.atom.model.builder.UpdatedBuilder;
import org.atomnuke.atom.model.builder.ValueBuilder;
import org.atomnuke.atom.xml.AtomElement;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
*
* @author zinic
*/
public class AtomHandler extends DelegatingHandler {
protected final DocumentContextManager contextManager;
protected final SaxAtomReaderResult result;
public AtomHandler(XMLReader xmlReader) {
super(xmlReader);
contextManager = new DocumentContextManager();
result = new SaxAtomReaderResult();
}
protected AtomHandler(AtomHandler delegate) {
super(delegate);
contextManager = delegate.contextManager;
result = delegate.result;
}
protected static boolean handleCommonElement(DelegatingHandler handler, DocumentContextManager contextManager, AtomElement currentElement, Attributes attributes) throws SAXException {
switch (currentElement) {
case ID:
startSimpleContentElement(new IdBuilder(), contextManager, currentElement, attributes);
break;
case ICON:
startSimpleContentElement(new IconBuilder(), contextManager, currentElement, attributes);
break;
case LOGO:
startSimpleContentElement(new LogoBuilder(), contextManager, currentElement, attributes);
break;
case NAME:
case EMAIL:
case URI:
startFieldContentElement(contextManager, currentElement);
break;
case UPDATED:
startDateConstruct(new UpdatedBuilder(), contextManager, currentElement, attributes);
break;
case RIGHTS:
startTypedContent(new RightsBuilder(), handler, contextManager, currentElement, attributes);
break;
case TITLE:
startTypedContent(new TitleBuilder(), handler, contextManager, currentElement, attributes);
break;
case SUBTITLE:
startTypedContent(new SubtitleBuilder(), handler, contextManager, currentElement, attributes);
break;
case SUMMARY:
startTypedContent(new SummaryBuilder(), handler, contextManager, currentElement, attributes);
break;
case AUTHOR:
startPersonConstruct(new AuthorBuilder(), contextManager, currentElement, attributes);
break;
case CATEGORY:
startCategory(contextManager, attributes);
break;
case GENERATOR:
startGenerator(contextManager, attributes);
break;
case LINK:
startLink(contextManager, attributes);
break;
default:
return false;
}
return true;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
final AtomElement currentElement = AtomElement.find(localName, AtomElement.ROOT_ELEMENTS);
if (currentElement == null) {
return;
}
switch (currentElement) {
case FEED:
startFeed(this, contextManager, attributes);
break;
case ENTRY:
startEntry(this, contextManager, attributes);
break;
}
}
protected static String trimSubstring(StringBuilder sb) {
int first, last;
for (first = 0; first < sb.length(); first++) {
if (!Character.isWhitespace(sb.charAt(first))) {
break;
}
}
for (last = sb.length(); last > first; last--) {
if (!Character.isWhitespace(sb.charAt(last - 1))) {
break;
}
}
return sb.substring(first, last);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
final StringBuilder characters = new StringBuilder();
characters.append(ch, start, length);
final String trimmedString = trimSubstring(characters);
switch (contextManager.peek().getElementDef()) {
case NAME:
contextManager.peek(PersonConstructBuilder.class).builder().setName(trimmedString);
break;
case URI:
contextManager.peek(PersonConstructBuilder.class).builder().setUri(trimmedString);
break;
case EMAIL:
contextManager.peek(PersonConstructBuilder.class).builder().setEmail(trimmedString);
break;
case GENERATOR:
contextManager.peek(GeneratorBuilder.class).builder().appendValue(trimmedString);
break;
case ID:
case ICON:
case LOGO:
case PUBLISHED:
case UPDATED:
contextManager.peek(ValueBuilder.class).builder().appendValue(trimmedString);
break;
}
}
public ReaderResult getResult() {
return result;
}
/**
* Null safe.
*
* @param st
* @return
*/
protected static URI toUri(String st) {
return st == null ? null : URI.create(st);
}
/**
* Null safe.
*
* @param st
* @return
*/
protected static Integer toInteger(String st) {
return st == null ? null : Integer.parseInt(st);
}
/**
* Null safe.
*
* @param st
* @return
*/
protected static Type toType(String st) {
return st == null ? null : Type.find(st);
}
protected static void startFieldContentElement(DocumentContextManager contextManager, AtomElement element) {
final HandlerContext previous = contextManager.peek();
contextManager.push(element, previous.builder());
}
private static void startFeed(AtomHandler self, DocumentContextManager contextManager, Attributes attributes) {
final FeedBuilder feedBuilder = new FeedBuilder();
feedBuilder.setBase(toUri(attributes.getValue(AtomAttributeConstants.BASE)));
feedBuilder.setLang(attributes.getValue(AtomAttributeConstants.LANG));
contextManager.push(AtomElement.FEED, feedBuilder);
self.delegateTo(new FeedHandler(self));
}
protected static void startEntry(AtomHandler self, DocumentContextManager contextManager, Attributes attributes) {
final EntryBuilder entryBuilder = new EntryBuilder();
entryBuilder.setBase(toUri(attributes.getValue(AtomAttributeConstants.BASE)));
entryBuilder.setLang(attributes.getValue(AtomAttributeConstants.LANG));
contextManager.push(AtomElement.ENTRY, entryBuilder);
self.delegateTo(new EntryHandler(self));
}
protected static void startPersonConstruct(PersonConstructBuilder builderInstance, DocumentContextManager contextManager, AtomElement element, Attributes attributes) {
builderInstance.setBase(toUri(attributes.getValue(AtomAttributeConstants.BASE)));
builderInstance.setLang(attributes.getValue(AtomAttributeConstants.LANG));
contextManager.push(element, builderInstance);
}
protected static void startGenerator(DocumentContextManager contextManager, Attributes attributes) {
final GeneratorBuilder generatorBuilder = new GeneratorBuilder();
generatorBuilder.setBase(toUri(attributes.getValue(AtomAttributeConstants.BASE)));
generatorBuilder.setLang(attributes.getValue(AtomAttributeConstants.LANG));
generatorBuilder.setUri(attributes.getValue(AtomAttributeConstants.URI));
generatorBuilder.setVersion(attributes.getValue(AtomAttributeConstants.VERSION));
contextManager.push(AtomElement.GENERATOR, generatorBuilder);
}
protected static void startTypedContent(TypedContentBuilder typedContentBuilder, DelegatingHandler self, DocumentContextManager contextManager, AtomElement element, Attributes attributes) {
typedContentBuilder.setBase(toUri(attributes.getValue(AtomAttributeConstants.BASE)));
typedContentBuilder.setLang(attributes.getValue(AtomAttributeConstants.LANG));
typedContentBuilder.setType(toType(attributes.getValue(AtomAttributeConstants.TYPE)));
contextManager.push(element, typedContentBuilder);
self.delegateTo(new MixedContentHandler(typedContentBuilder, self));
}
protected static void startDateConstruct(DateConstructBuilder dateConstructBuilder, DocumentContextManager contextManager, AtomElement element, Attributes attributes) {
dateConstructBuilder.setBase(toUri(attributes.getValue(AtomAttributeConstants.BASE)));
dateConstructBuilder.setLang(attributes.getValue(AtomAttributeConstants.LANG));
contextManager.push(element, dateConstructBuilder);
}
protected static void startLink(DocumentContextManager contextManager, Attributes attributes) {
final LinkBuilder linkBuilder = new LinkBuilder();
linkBuilder.setBase(toUri(attributes.getValue(AtomAttributeConstants.BASE)));
linkBuilder.setLang(attributes.getValue(AtomAttributeConstants.LANG));
linkBuilder.setHref(attributes.getValue(AtomAttributeConstants.HREF));
linkBuilder.setHreflang(attributes.getValue(AtomAttributeConstants.HREFLANG));
linkBuilder.setRel(attributes.getValue(AtomAttributeConstants.REL));
linkBuilder.setTitle(attributes.getValue(AtomAttributeConstants.TITLE));
linkBuilder.setType(attributes.getValue(AtomAttributeConstants.TYPE));
linkBuilder.setLength(toInteger(attributes.getValue(AtomAttributeConstants.LENGTH)));
contextManager.push(AtomElement.LINK, linkBuilder);
}
protected static void startCategory(DocumentContextManager contextManager, Attributes attributes) {
final CategoryBuilder categoryBuilder = new CategoryBuilder();
categoryBuilder.setBase(toUri(attributes.getValue(AtomAttributeConstants.BASE)));
categoryBuilder.setLang(attributes.getValue(AtomAttributeConstants.LANG));
categoryBuilder.setScheme(attributes.getValue(AtomAttributeConstants.SCHEME));
categoryBuilder.setTerm(attributes.getValue(AtomAttributeConstants.TERM));
categoryBuilder.setLabel(attributes.getValue(AtomAttributeConstants.LABEL));
contextManager.push(AtomElement.CATEGORY, categoryBuilder);
}
protected static void startSimpleContentElement(SimpleContentBuilder simpleContentBuilder, DocumentContextManager contextManager, AtomElement element, Attributes attributes) {
simpleContentBuilder.setBase(toUri(attributes.getValue(AtomAttributeConstants.BASE)));
simpleContentBuilder.setLang(attributes.getValue(AtomAttributeConstants.LANG));
contextManager.push(element, simpleContentBuilder);
}
}