package org.juxtasoftware.resource.heatmap; import java.util.Iterator; import java.util.List; import org.juxtasoftware.model.Note; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; /** * Inject note information into the heatmap text stream * @author loufoster * */ @Component @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class NoteInjector implements StreamInjector<Note> { private List<Note> notes; private Iterator<Note> noteItr; private Note currNote; private boolean tagStarted = false; @Override public void initialize(List<Note> data) { this.notes = data; this.noteItr = this.notes.iterator(); if ( this.noteItr.hasNext() ) { this.currNote = this.noteItr.next(); } } @Override public List<Note> getData() { return this.notes; } @Override public boolean hasContent(long pos) { if ( this.currNote == null) { return false; } if ( this.currNote.getAnchorRange().getStart() == pos && this.tagStarted == false || this.currNote.getAnchorRange().getEnd() == pos && this.tagStarted == true ) { return true; } return false; } public boolean addTrailingNotes(StringBuilder line ) { boolean added = false; while ( this.currNote != null ) { added = true; injectContentStart( line, this.currNote.getAnchorRange().getStart() ); injectContentEnd( line, this.currNote.getAnchorRange().getEnd() ); } return added; } @Override public void injectContentStart(StringBuilder line, final long currPositon) { if ( this.currNote != null && this.tagStarted == false ) { if ( this.currNote.getAnchorRange().getStart() == currPositon ) { line.append("<span class=\"note-anchor\" id=\"note-anchor-"); line.append(this.currNote.getId()).append("\">"); this.tagStarted = true; } } } @Override public void injectContentEnd(StringBuilder line, final long currPosition) { if (this.currNote != null && this.tagStarted == true) { if (this.currNote.getAnchorRange().getEnd() == currPosition) { if (this.currNote.getAnchorRange().length() == 0) { // this is a note not anchored to a range of text. // add a marker at this point to show location line.append("✻"); } line.append("</span>"); this.tagStarted = false; Note priorNote = this.currNote; this.currNote = null; if (this.noteItr.hasNext()) { this.currNote = this.noteItr.next(); if (this.currNote.getAnchorRange().getStart() < currPosition) { handleNestedNotes(line, currPosition, priorNote); } } } } } private void handleNestedNotes(StringBuilder line, long currPos, Note parentNote ) { final String mark = "⚬ "; StringBuffer content = new StringBuffer(); content.append(mark).append(parentNote.getContent()); while (true ) { boolean getNext = false; if ( this.currNote.getAnchorRange().getStart() < currPos ) { if ( this.currNote.getAnchorRange().getEnd() <= currPos ) { content.append("<br/>").append(mark).append(this.currNote.getContent()); this.noteItr.remove(); getNext = true; } else { // this is an overlapped note. can't handle it, so junk it this.noteItr.remove(); getNext = true; } } else { break; } if ( getNext ) { if ( this.noteItr.hasNext() ) { this.currNote = this.noteItr.next(); } else { this.currNote = null; break; } } else { break; } } parentNote.setContent(content.toString()); } }