package org.juxtasoftware.service.importer.jxt; import java.io.IOException; import java.io.Reader; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * Given a global list of typeless revision occurrences, convert it into * a list of typed revision occurrence that can be used to generate single * exclusion entries in the xslt file. * @author loufoster * */ final class JxtRevisionExtractor extends DefaultHandler{ private Set<Integer> includedRevisions; private Integer revisionCount = 0; private Set<RevisionOccurrence> excludedRevisonsInfo = new HashSet<RevisionOccurrence>(); private Map<String, Integer> tagCounts = new HashMap<String, Integer>(); public void extract( final Reader srcReader, final List<Integer> includedRevisions ) throws SAXException, IOException { // juxta revision lists are zero based. Make them one based this.includedRevisions = new HashSet<Integer>(); for ( Integer rev : includedRevisions ) { this.includedRevisions.add( (rev+1) ); } this.tagCounts.put("add", 0); this.tagCounts.put("addSpan", 0); this.tagCounts.put("del", 0); this.tagCounts.put("delSpan", 0); Util.saxParser().parse( new InputSource( srcReader), this ); } public Set<RevisionOccurrence> getExcludedRevisions() { return this.excludedRevisonsInfo; } public int getTotalRevisionCount() { return this.revisionCount; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ( isRevision(qName) ) { // increment total revsion count and individual revision type count this.revisionCount++; Integer cnt = this.tagCounts.get(qName) + 1; this.tagCounts.put(qName, cnt); // add revisions that are not part of the inclusion list are excluded if ( isAdd(qName) ) { if ( this.includedRevisions.contains( this.revisionCount ) == false ) { this.excludedRevisonsInfo.add( new RevisionOccurrence(qName, cnt) ); } } else { // delete revsions are excluded unless they are part of the list if ( this.includedRevisions.contains( this.revisionCount ) ) { this.excludedRevisonsInfo.add( new RevisionOccurrence(qName, cnt) ); } } } } private boolean isRevision(final String qName ) { return ( isAdd(qName) || isDelete(qName) ); } private boolean isAdd(final String qName ) { return ( qName.equals("add") || qName.equals("addSpan")); } private boolean isDelete(final String qName ) { return ( qName.equals("del") || qName.equals("delSpan")); } /** * @author loufoster */ static class RevisionOccurrence { private final String tagName; private final int occurrence; public RevisionOccurrence( final String tagName, final int occurrence) { this.tagName = tagName; this.occurrence = occurrence; } public String getTagName() { return tagName; } public int getOccurrence() { return occurrence; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + occurrence; result = prime * result + ((tagName == null) ? 0 : tagName.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; RevisionOccurrence other = (RevisionOccurrence) obj; if (occurrence != other.occurrence) return false; if (tagName == null) { if (other.tagName != null) return false; } else if (!tagName.equals(other.tagName)) return false; return true; } } }