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 "";
}
}