package org.pegadi.artis; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.DocumentType; import org.w3c.dom.Node; import javax.swing.text.*; import java.util.Enumeration; import java.util.Vector; public class ValidatingTextDocument extends AbstractTextDocument { public Logger log = LoggerFactory.getLogger(getClass()); public ValidatingTextDocument(Node root, StyleContext styles, DocumentType docType) { super(root, styles, docType); // TODO Auto-generated constructor stub } /** * This function updates all paragraphs to comply with the defining schema. * @param offset */ public void updateParagraphs(int offset) { log.debug("UPDATE PARAGRAPHS"); // walk through the paragraphs, put them in a list int location = 0; int counter = 0; String prevName = ""; Vector v = new Vector(); String stylename; while (location <= getLength()) { Element para = getParagraphElement(location); if (para != null) { AttributeSet attSet = para.getAttributes(); Object name = attSet.getAttribute("name"); if (name == null) { Enumeration e = attSet.getAttributeNames(); Object key, value; while (e.hasMoreElements()) { key = e.nextElement(); value = attSet.getAttribute(key); if (key.toString().equals("name")) { name = value; Vector elements = ValidationRules.getAllowedElements(counter, (String) name, prevName); if (!elements.contains(name)) { log.debug("VECTOR DOES NOT CONTAIN NAME OF THIS PARAGRAPH. => DISALLOWED PARAGRAPH."); if (elements.size() == 1) { stylename = (String)elements.get(0); } else { stylename = ValidationRules.getDefaultElement(); } Style s = getStyle(stylename); log.debug("CHANGING PARAGRAPH TO: " + stylename); setParagraphAttributes(para.getStartOffset(), para.getEndOffset() - para.getStartOffset(), s, true); //fireTextChanged(); } } } } location = para.getEndOffset(); log.debug("Element nr " + counter + " from " + para.getStartOffset() + " to "+ para.getEndOffset() + " is '" + name.toString() +"':" + name.getClass().toString()); v.add(para); prevName = (String) name; } else log.debug("Element nr " + counter + " is null."); counter++; } } /** * Insert content into the document. <code>\n</code> is treated as a new element * marker, and this method will check to see if new elements are allowed. * When they are not allowed, the <code>\n</code> will be ignored. * * @param offset The offset into the document to insert at. * @param str The string to insert. * @param a The attributes to apply to the text. * @throws BadLocationException If the offset is not valid. */ public void insertString(int offset, String str, AttributeSet a) throws BadLocationException { checkEaster(str); log.debug("inserted: '" + str + "' at offset: " + offset); if(autoCorrection && str.length() == 1){ if(getLength()==0){ spaceCaseState = SPACE_CASE_SPACE; //uppercase for the first letter in document } if(offset!=lastOffset+1 && getLength()!=0){ spaceCaseState = SPACE_CASE_INIT; //moving the kursor or pressing backspace will result in loss off uppercase-state } if(str.equals(".")||str.equals("?")||str.equals("!")){ spaceCaseState = SPACE_CASE_DOT; lastOffset = offset; } else if(str.equals(" ") && (spaceCaseState == SPACE_CASE_DOT || spaceCaseState == SPACE_CASE_SPACE )){ spaceCaseState = SPACE_CASE_SPACE; lastOffset = offset; } else if( str.equals("\n") && (spaceCaseState == SPACE_CASE_DOT || spaceCaseState == SPACE_CASE_SPACE )){ // updateParagraphs(offset); spaceCaseState = SPACE_CASE_SPACE; lastOffset = offset; } else if(spaceCaseState == SPACE_CASE_SPACE){ str = str.toUpperCase(); spaceCaseState = SPACE_CASE_INIT; } else{ spaceCaseState = SPACE_CASE_INIT; } } super.insertString(offset, str, a); //need to run updateParagraphs AFTER super(), so that the new paragraph is recognized. //@todo: check for insertion of str longer than 1 containing \n, that is: pasted text with paragraph breaks if ((str.length()) == 1 && str.equals("\n")) { int newOffset = offset + 1; // as super() is now performed, the caret was moved 1 step. (ie: caret is now on the next line/paragraph) log.debug("<enter> inserted. Need to re-validate paragraphs."); updateParagraphs(newOffset); fireUpdatePerformed(newOffset); } } /** * Returns the paragraph number of the given offset. Paragraph number starts at zero (0). * @todo: KAN DENNE ERSTATTAST MED GETELEMENTINDEX() ? * @param offset * @return */ public int getParagraphNumber(int offset) { // walk through the paragraphs, put them in a list int location = 0; int counter = 0; while (location <= offset) { Element para = getParagraphElement(location); log.debug("Element nr " + counter + " from " + para.getStartOffset() + " to "+ para.getEndOffset() ); location = para.getEndOffset(); counter++; } return counter-1; // the first paragraph is number zero. } public String getPreviousParagraphName(int offset) { log.debug("getPreviousParagraphName called with offset:" + offset); // walk through the paragraphs, put them in a list int location = 0; int counter = 0; Vector paras = new Vector(); while (location <= offset) { Element para = getParagraphElement(location); log.debug("Element nr " + counter + " from " + para.getStartOffset() + " to "+ para.getEndOffset() ); AttributeSet attSet = para.getAttributes(); Object name = attSet.getAttribute("name"); if (name == null) { Enumeration e = attSet.getAttributeNames(); Object key, value; while (e.hasMoreElements()) { key = e.nextElement(); value = attSet.getAttribute(key); if (key.toString().equals("name")) { name = value; paras.add (name); log.debug("Added: " + paras.get(counter)); } } } else { log.debug("Name was NOT null! can probably add it directly..."); paras.add(name); } location = para.getEndOffset(); counter++; } log.debug("Found " + paras.size() + " paragraphs." ); if ( (paras.size() >=2) && paras.get( paras.size()-2) != null) { log.debug("About to return: " + paras.get(paras.size()-2)); return (String) paras.get(paras.size()-2); } else return ""; } }