0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package org.netbeans.modules.xml.text.structure;
0042:
0043: import java.util.List;
0044: import java.util.Vector;
0045: import javax.swing.text.AttributeSet;
0046: import javax.swing.text.BadLocationException;
0047: import org.netbeans.editor.BaseDocument;
0048: import org.netbeans.junit.NbTestCase;
0049: import org.netbeans.modules.editor.structure.api.DocumentElement;
0050: import org.netbeans.modules.editor.structure.api.DocumentElementEvent;
0051: import org.netbeans.modules.editor.structure.api.DocumentElementListener;
0052: import org.netbeans.modules.editor.structure.api.DocumentModel;
0053: import org.netbeans.modules.editor.structure.api.DocumentModelException;
0054: import org.netbeans.modules.editor.structure.api.DocumentModelListener;
0055: import org.netbeans.modules.editor.structure.api.DocumentModelStateListener;
0056: import org.netbeans.modules.editor.structure.api.DocumentModelUtils;
0057: import org.netbeans.modules.editor.structure.spi.DocumentModelProvider;
0058: import org.netbeans.modules.xml.text.syntax.XMLKit;
0059: import org.netbeans.modules.xml.text.test.TestBase;
0060:
0061: /** XML DocumentModel provider unit tests
0062: *
0063: * @author Marek Fukala
0064: */
0065: public class XMLDocumentModelTest extends TestBase {
0066:
0067: private static final int MODEL_TIMEOUT = 500; //ms
0068: BaseDocument doc = null;
0069:
0070: public XMLDocumentModelTest() {
0071: super ("xml-document-model-test");
0072: }
0073:
0074: public void setUp() throws BadLocationException {
0075: }
0076:
0077: protected void runTest() throws Throwable {
0078: System.out.println(getName());
0079: super .runTest();
0080: }
0081:
0082: //--------- test methods -----------
0083: public void testModelBasis() throws DocumentModelException,
0084: BadLocationException {
0085: //initialize documents used in tests
0086: initDoc1();
0087:
0088: //set the document content
0089: DocumentModel model = DocumentModel.getDocumentModel(doc);
0090:
0091: assertNotNull(model);
0092:
0093: assertNotNull(model.getDocument());
0094:
0095: DocumentElement root = model.getRootElement();
0096: assertNotNull(root);
0097:
0098: assertNull(root.getParentElement());
0099:
0100: List children = root.getChildren();
0101: assertEquals(2, children.size());
0102:
0103: DocumentElement rootel = root.getElement(1); //<root> element
0104: //check parent
0105: assertEquals(root, rootel.getParentElement());
0106:
0107: //check name and type
0108: assertEquals("root", rootel.getName());
0109: assertEquals(XMLDocumentModelProvider.XML_TAG, rootel.getType());
0110:
0111: //check content and offsets
0112: assertEquals(21, rootel.getStartOffset());
0113: assertEquals(55, rootel.getEndOffset());
0114:
0115: //check children count
0116: assertEquals(2, rootel.getElementCount());
0117:
0118: //test children (A)
0119: DocumentElement a = rootel.getElement(0);
0120: //check parent
0121: assertEquals(rootel, a.getParentElement());
0122:
0123: assertEquals("a", a.getName());
0124: assertEquals(XMLDocumentModelProvider.XML_TAG, a.getType());
0125: //check content and offsets
0126: assertEquals(27, a.getStartOffset());
0127: assertEquals(37, a.getEndOffset());
0128:
0129: //test children (B)
0130: DocumentElement b = rootel.getElement(1);
0131: //check parent
0132: assertEquals(rootel, b.getParentElement());
0133:
0134: assertEquals("b", b.getName());
0135: assertEquals(XMLDocumentModelProvider.XML_TAG, b.getType());
0136: //check content and offsets
0137: assertEquals(38, b.getStartOffset());
0138: assertEquals(48, b.getEndOffset());
0139:
0140: //test children of B (T)
0141: DocumentElement t = b.getElement(0);
0142: //check parent
0143: assertEquals(b, t.getParentElement());
0144:
0145: assertEquals("...", t.getName());
0146: assertEquals(XMLDocumentModelProvider.XML_CONTENT, t.getType());
0147: //check content and offsets
0148: assertEquals(41, t.getStartOffset());
0149: assertEquals(44, t.getEndOffset());
0150: }
0151:
0152: public void testAddElement() throws DocumentModelException,
0153: BadLocationException, InterruptedException {
0154: //initialize documents used in tests
0155: initDoc1();
0156: //set the document content
0157: DocumentModel model = DocumentModel.getDocumentModel(doc);
0158:
0159: DocumentElement root = model.getRootElement();
0160: final DocumentElement rootTag = root.getElement(1); //get <root> element
0161: //listen to model
0162: final Vector addedElements = new Vector();
0163: model
0164: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0165:
0166: public void documentElementAdded(DocumentElement de) {
0167: addedElements.add(de);
0168: }
0169: });
0170:
0171: //listen to element
0172: final Vector addedElements2 = new Vector();
0173: rootTag
0174: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0175:
0176: public void elementAdded(DocumentElementEvent e) {
0177: addedElements2.add(e.getChangedChild());
0178: }
0179: });
0180:
0181: assertEquals(2, rootTag.getElementCount()); //has A, B children
0182: final Object lock = new Object();
0183: model
0184: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0185: public void updateFinished() {
0186: synchronized (lock) {
0187: lock.notifyAll();
0188: }
0189: }
0190: });
0191:
0192: doc.insertString(27, "<new></new>", null);
0193: model.forceUpdate();
0194:
0195: synchronized (lock) {
0196: lock.wait(2000);
0197: }
0198:
0199: assertEquals(3, rootTag.getElementCount()); //has NEW, A, B children
0200: //check events
0201: assertEquals(1, addedElements.size());
0202: assertEquals(1, addedElements2.size());
0203:
0204: DocumentElement newElement = rootTag.getElement(0);
0205: //test children (B)
0206: assertEquals("new", newElement.getName());
0207: assertEquals(XMLDocumentModelProvider.XML_TAG, newElement
0208: .getType());
0209: //check content and offsets
0210: assertEquals(27, newElement.getStartOffset());
0211: assertEquals(37, newElement.getEndOffset());
0212:
0213: //test new element has no children
0214: assertEquals(0, newElement.getChildren().size());
0215:
0216: //test new element parent
0217: DocumentElement newElementParent = newElement
0218: .getParentElement();
0219: assertEquals(rootTag, newElementParent);
0220: }
0221:
0222: public void testRemoveEmptyTagElement()
0223: throws DocumentModelException, BadLocationException,
0224: InterruptedException {
0225: //initialize documents used in tests
0226: initDoc1();
0227: //set the document content
0228: DocumentModel model = DocumentModel.getDocumentModel(doc);
0229:
0230: DocumentElement root = model.getRootElement();
0231: DocumentElement rootTag = root.getElement(1); //get <root> element
0232: final DocumentElement aTag = rootTag.getElement(0); //get <a> element
0233: //listen to model
0234: final Vector removedElements = new Vector();
0235: model
0236: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0237:
0238: public void documentElementRemoved(
0239: DocumentElement de) {
0240: removedElements.add(de);
0241: }
0242: });
0243:
0244: //listen to element
0245: final Vector removedElements2 = new Vector();
0246: aTag
0247: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0248:
0249: public void elementRemoved(DocumentElementEvent e) {
0250: removedElements2.add(e.getChangedChild());
0251: }
0252: });
0253:
0254: assertEquals(1, aTag.getElementCount()); //has only C children
0255: final Object lock = new Object();
0256: model
0257: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0258:
0259: public void updateFinished() {
0260: synchronized (lock) {
0261: lock.notifyAll();
0262: }
0263: }
0264: });
0265:
0266: doc.remove(30, "<c/>".length());
0267: model.forceUpdate();
0268:
0269: synchronized (lock) {
0270: lock.wait(2000);
0271: }
0272:
0273: assertEquals(1, removedElements.size());
0274: assertEquals(1, removedElements2.size());
0275:
0276: assertEquals(0, aTag.getElementCount()); //has B children
0277: }
0278:
0279: public void testRemoveTagElementWithTextContent()
0280: throws DocumentModelException, BadLocationException,
0281: InterruptedException {
0282: //initialize documents used in tests
0283: initDoc1();
0284: //set the document content
0285: DocumentModel model = DocumentModel.getDocumentModel(doc);
0286:
0287: DocumentElement root = model.getRootElement();
0288: final DocumentElement rootTag = root.getElement(1); //get <root> element
0289: //listen to model
0290: final Vector removedElements = new Vector();
0291: model
0292: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0293:
0294: public void documentElementRemoved(
0295: DocumentElement de) {
0296: removedElements.add(de);
0297: }
0298: });
0299:
0300: //listen to element
0301: final Vector removedElements2 = new Vector();
0302: rootTag
0303: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0304:
0305: public void elementRemoved(DocumentElementEvent e) {
0306: removedElements2.add(e.getChangedChild());
0307: }
0308: });
0309:
0310: assertEquals(2, rootTag.getElementCount()); //has A and B children
0311: final Object lock = new Object();
0312: model
0313: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0314:
0315: public void updateFinished() {
0316: synchronized (lock) {
0317: lock.notifyAll();
0318: }
0319: }
0320: });
0321:
0322: doc.remove(38, "<b>text</b>".length());
0323: model.forceUpdate();
0324:
0325: synchronized (lock) {
0326: lock.wait(2000);
0327: }
0328:
0329: assertEquals(2, removedElements.size()); //two events - one for B and one for TEXT
0330: assertEquals(2, removedElements2.size());
0331:
0332: assertEquals(1, rootTag.getElementCount()); //now has only A child
0333: }
0334:
0335: public void testRemoveNestedElements()
0336: throws DocumentModelException, BadLocationException,
0337: InterruptedException {
0338: //initialize documents used in tests
0339: initDoc1();
0340: //set the document content
0341: DocumentModel model = DocumentModel.getDocumentModel(doc);
0342:
0343: DocumentElement root = model.getRootElement();
0344: final DocumentElement rootTag = root.getElement(1); //get <root> element
0345: //listen to model
0346: final Vector removedElements = new Vector();
0347: model
0348: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0349:
0350: public void documentElementRemoved(
0351: DocumentElement de) {
0352: removedElements.add(de);
0353: }
0354: });
0355:
0356: //listen to element
0357: final Vector removedElements2 = new Vector();
0358: rootTag
0359: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0360:
0361: public void elementRemoved(DocumentElementEvent e) {
0362: removedElements2.add(e.getChangedChild());
0363: }
0364: });
0365:
0366: assertEquals(2, rootTag.getElementCount()); //has A, B children
0367: final Object lock = new Object();
0368: model
0369: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0370:
0371: public void updateFinished() {
0372: synchronized (lock) {
0373: lock.notifyAll();
0374: }
0375: }
0376: });
0377:
0378: doc.remove(27, "<a><c/></a>".length());
0379: model.forceUpdate();
0380:
0381: synchronized (lock) {
0382: lock.wait(2000);
0383: }
0384:
0385: //#63357 - [navigator] Inconsistece when deleted tag connects other two
0386: //evaluation: empty elements of <c> and <a> stays in the structure and events are not fired!
0387: assertEquals(2, removedElements.size());
0388: assertEquals(2, removedElements2.size());
0389:
0390: assertEquals(1, rootTag.getElementCount()); //has B children
0391: }
0392:
0393: public void testRemoveAndAddEntireDocumentContent()
0394: throws DocumentModelException, BadLocationException,
0395: InterruptedException {
0396: //initialize documents used in tests
0397: initDoc1();
0398: //set the document content
0399: final DocumentModel model = DocumentModel.getDocumentModel(doc);
0400: final DocumentElement root = model.getRootElement();
0401:
0402: //listen to model
0403: final Vector removedElements = new Vector();
0404: model
0405: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0406:
0407: public void documentElementRemoved(
0408: DocumentElement de) {
0409: removedElements.add(de);
0410: }
0411: });
0412:
0413: //listen to element
0414: final Vector removedElements2 = new Vector();
0415: root
0416: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0417:
0418: public void elementRemoved(DocumentElementEvent e) {
0419: removedElements2.add(e.getChangedChild());
0420: }
0421: });
0422: final Object lock = new Object();
0423: model
0424: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0425:
0426: public void updateFinished() {
0427: model.removeDocumentModelStateListener(this );
0428: synchronized (lock) {
0429: lock.notifyAll();
0430: }
0431: }
0432: });
0433:
0434: //remove entire document content
0435: doc.remove(0, doc.getLength());
0436: model.forceUpdate();
0437:
0438: //insert the document content back
0439: synchronized (lock) {
0440: lock.wait(2000);
0441: }
0442:
0443: assertEquals(6, removedElements.size()); //all elements removed
0444: //XXX probably should be only one element removed, but because of the
0445: //elements removal mechanism, when entire document is erased and
0446: //where all empty elements (startoffset == endoffset)
0447: //are considered as children of root element the event is fired 6-times.
0448: assertEquals(6, removedElements2.size()); //<root> removed
0449: assertEquals(0, root.getElementCount()); //has not children
0450: //listen to model
0451: final Vector addedElements = new Vector();
0452: model
0453: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0454:
0455: public void documentElementAdded(DocumentElement de) {
0456: addedElements.add(de);
0457: }
0458: });
0459:
0460: //listen to element
0461: final Vector addedElements2 = new Vector();
0462: root
0463: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0464:
0465: public void elementAdded(DocumentElementEvent e) {
0466: addedElements2.add(e.getChangedChild());
0467: }
0468: });
0469:
0470: model
0471: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0472:
0473: public void updateFinished() {
0474: synchronized (lock) {
0475: lock.notifyAll();
0476: }
0477: }
0478: });
0479:
0480: doc
0481: .insertString(
0482: 0,
0483: "<?xml version='1.0'?><root><a><c/></a><b>text</b></root>",
0484: null);
0485: model.forceUpdate();
0486:
0487: synchronized (lock) {
0488: lock.wait(2000);
0489: }
0490:
0491: //check events
0492: assertEquals(6, addedElements.size()); //all elements added
0493: assertEquals(2, addedElements2.size()); //<root> and PI added
0494: assertEquals(2, root.getElementCount()); //has <root> and PI child
0495: //check PI tag
0496: DocumentElement piTag = root.getElement(0);
0497: assertNotNull(piTag);
0498:
0499: //check root tag and its children
0500: DocumentElement rootTag = root.getElement(1);
0501: assertNotNull(rootTag);
0502: //check basic properties of the root tag
0503: assertEquals("root", rootTag.getName());
0504: assertEquals(XMLDocumentModelProvider.XML_TAG, rootTag
0505: .getType());
0506:
0507: assertEquals(2, rootTag.getElementCount()); //has A and B children
0508: assertEquals(0, piTag.getElementCount()); //has no children
0509: DocumentElement aTag = rootTag.getElement(0);
0510: DocumentElement bTag = rootTag.getElement(1);
0511: assertNotNull(aTag);
0512: assertEquals("a", aTag.getName());
0513: assertNotNull(bTag);
0514: assertEquals("b", bTag.getName());
0515: assertEquals(1, aTag.getElementCount()); //has C children
0516: assertEquals(1, bTag.getElementCount()); //has text children
0517: DocumentElement cTag = aTag.getElement(0);
0518: assertNotNull(cTag);
0519: assertEquals("c", cTag.getName());
0520: assertEquals(0, cTag.getElementCount()); //has no children
0521: DocumentElement text = bTag.getElement(0);
0522: assertNotNull(text);
0523: assertEquals(XMLDocumentModelProvider.XML_CONTENT, text
0524: .getType());
0525: assertEquals(0, text.getElementCount()); //has no children
0526: }
0527:
0528: public void testReplaceEntireDocumentContent()
0529: throws DocumentModelException, BadLocationException,
0530: InterruptedException {
0531: //initialize documents used in tests
0532: initDoc1();
0533: //set the document content
0534: DocumentModel model = DocumentModel.getDocumentModel(doc);
0535:
0536: final DocumentElement root = model.getRootElement();
0537:
0538: //listen to model
0539: final Vector removedElements = new Vector();
0540: model
0541: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0542:
0543: public void documentElementRemoved(
0544: DocumentElement de) {
0545: removedElements.add(de);
0546: }
0547: });
0548:
0549: //listen to element
0550: final Vector removedElements2 = new Vector();
0551: root
0552: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0553:
0554: public void elementRemoved(DocumentElementEvent e) {
0555: removedElements2.add(e.getChangedChild());
0556: }
0557: });
0558:
0559: final Object lock = new Object();
0560: model
0561: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0562:
0563: public void updateFinished() {
0564: synchronized (lock) {
0565: lock.notifyAll();
0566: }
0567: }
0568: });
0569:
0570: //remove entire document content
0571: doc.remove(0, doc.getLength());
0572: doc.insertString(0, "xxx", null);
0573: model.forceUpdate();
0574:
0575: synchronized (lock) {
0576: lock.wait(2000);
0577: }
0578:
0579: assertEquals(6, removedElements.size()); //all elements removed
0580: //XXX probably should be only one element removed, but because of the
0581: //elements removal mechanism, when entire document is erased and
0582: //where all empty elements (startoffset == endoffset)
0583: //are considered as children of root element the event is fired 6-times.
0584: assertEquals(6, removedElements2.size()); //<root> removed
0585: assertEquals(1, root.getElementCount()); //has one text children
0586: DocumentElement text = root.getElement(0);
0587: assertNotNull(text);
0588: assertEquals(XMLDocumentModelProvider.XML_CONTENT, text
0589: .getType());
0590: assertEquals(0, text.getElementCount()); //has no children
0591: }
0592:
0593: //inserts a character into <root> tag element (e.g. <roXot>) so the element is not valid
0594: //the ROOT element should be destroyed and its children (A, B) should be moved to its parent (document root element)
0595: public void testInvalidateTagElement()
0596: throws DocumentModelException, BadLocationException,
0597: InterruptedException {
0598: //initialize documents used in tests
0599: initDoc1();
0600: //set the document content
0601: DocumentModel model = DocumentModel.getDocumentModel(doc);
0602:
0603: final DocumentElement root = model.getRootElement();
0604: final DocumentElement rootTag = root.getElement(1); //get <root> element
0605: final DocumentElement aTag = rootTag.getElement(0);
0606: final DocumentElement bTag = rootTag.getElement(1);
0607:
0608: //add-listen to model
0609: final Vector addedElements = new Vector();
0610: model
0611: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0612:
0613: public void documentElementAdded(DocumentElement de) {
0614: addedElements.add(de);
0615: }
0616: });
0617:
0618: //add-listen to element
0619: final Vector addedElements2 = new Vector();
0620: root
0621: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0622:
0623: public void elementAdded(DocumentElementEvent e) {
0624: addedElements2.add(e.getChangedChild());
0625: }
0626: });
0627:
0628: //remove-listen to model
0629: final Vector removedElements = new Vector();
0630: model
0631: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0632:
0633: public void documentElementRemoved(
0634: DocumentElement de) {
0635: removedElements.add(de);
0636: }
0637: });
0638:
0639: //remove-listen to element
0640: final Vector removedElements2 = new Vector();
0641: rootTag
0642: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0643:
0644: public void elementRemoved(DocumentElementEvent e) {
0645: // System.out.println("removed " + e.getChangedChild());
0646: removedElements2.add(e.getChangedChild());
0647: }
0648: });
0649:
0650: assertEquals(2, root.getElementCount()); //has PI and ROOT child
0651: final Object lock = new Object();
0652: model
0653: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0654:
0655: public void updateFinished() {
0656: synchronized (lock) {
0657: lock.notifyAll();
0658: }
0659: }
0660: });
0661:
0662: doc.insertString(24, "X", null);
0663: model.forceUpdate();
0664:
0665: synchronized (lock) {
0666: lock.wait(2000);
0667: }
0668:
0669: assertEquals(3, root.getElementCount()); //has PI, A, B children
0670: //check events
0671: assertEquals(0, addedElements.size());
0672: assertEquals(2, addedElements2.size());
0673:
0674: assertEquals(1, removedElements.size());
0675: assertEquals(2, removedElements2.size()); //A,B from ROOT
0676: //test children
0677: assertEquals("b", bTag.getName());
0678: assertEquals(XMLDocumentModelProvider.XML_TAG, bTag.getType());
0679: assertEquals(1, bTag.getElementCount());
0680: assertEquals(root, bTag.getParentElement());
0681:
0682: assertEquals("a", aTag.getName());
0683: assertEquals(XMLDocumentModelProvider.XML_TAG, aTag.getType());
0684: assertEquals(1, aTag.getElementCount());
0685: assertEquals(root, aTag.getParentElement());
0686:
0687: //check content and offsets
0688: assertEquals(28, aTag.getStartOffset());
0689: assertEquals(38, aTag.getEndOffset());
0690:
0691: //check if the ROOT element has been really removed
0692: try {
0693: rootTag.getParentElement(); //should throw the IAE
0694: assertTrue(
0695: "The removed element still can obtain its parent!?!?!",
0696: false);
0697: } catch (IllegalArgumentException iae) {
0698: //OK
0699: }
0700:
0701: assertEquals(0, rootTag.getChildren().size()); //has not children
0702: }
0703:
0704: public void testCreateAndUpdateCommentElement()
0705: throws DocumentModelException, BadLocationException,
0706: InterruptedException {
0707: //initialize documents used in tests
0708: initDoc1();
0709: //set the document content
0710: final DocumentModel model = DocumentModel.getDocumentModel(doc);
0711:
0712: final DocumentElement root = model.getRootElement();
0713: final DocumentElement rootTag = root.getElement(1); //get <root> element
0714: final DocumentElement aTag = rootTag.getElement(0);
0715:
0716: //add-listen to model
0717: final Vector addedElements = new Vector();
0718: model
0719: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0720:
0721: public void documentElementAdded(DocumentElement de) {
0722: addedElements.add(de);
0723: }
0724: });
0725:
0726: //add-listen to element
0727: final Vector addedElementsToATag = new Vector();
0728: aTag
0729: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0730:
0731: public void elementAdded(DocumentElementEvent e) {
0732: addedElementsToATag.add(e.getChangedChild());
0733: }
0734: });
0735:
0736: assertEquals(1, aTag.getElementCount()); //A has only C children
0737: final Object lock = new Object();
0738:
0739: model
0740: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0741:
0742: public void updateFinished() {
0743:
0744: model.removeDocumentModelStateListener(this );
0745: synchronized (lock) {
0746: lock.notifyAll();
0747: }
0748: }
0749: });
0750:
0751: doc.insertString(30, "<!-- xml comment -->", null);
0752: model.forceUpdate();
0753: //text after:
0754: // <?xml version='1.0'?><root><a><!-- xml comment --><c/></a><b>text</b></root>
0755: // 012345678901234567890123456789012345678901234567890123456789
0756: // 0 1 2 3 4 5
0757: synchronized (lock) {
0758: lock.wait(2000);
0759: }
0760:
0761: //check events
0762: assertEquals(1, addedElements.size());
0763: assertEquals(1, addedElementsToATag.size());
0764:
0765: //test a tag and its content
0766: assertEquals("a", aTag.getName());
0767: assertEquals(XMLDocumentModelProvider.XML_TAG, aTag.getType());
0768: assertEquals(2, aTag.getElementCount()); //the new commnent and C tag
0769: assertEquals(rootTag, aTag.getParentElement());
0770:
0771: //check content and offsets
0772: assertEquals(27, aTag.getStartOffset());
0773: assertEquals(57, aTag.getEndOffset());
0774:
0775: //check the comment element
0776: DocumentElement comment = aTag.getElement(0);
0777: assertEquals("comment", comment.getName());
0778: assertEquals(XMLDocumentModelProvider.XML_COMMENT, comment
0779: .getType());
0780: assertEquals(0, comment.getElementCount()); //check has not children
0781: assertEquals(aTag, comment.getParentElement());
0782: //check boundaries
0783: assertEquals(30, comment.getStartOffset());
0784: assertEquals(49, comment.getEndOffset());
0785:
0786: //test comment content update
0787: //add-listen to model
0788: final Vector modifiedEls = new Vector();
0789: model
0790: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0791:
0792: public void documentElementChanged(
0793: DocumentElement de) {
0794: modifiedEls.add(de);
0795: }
0796: });
0797: //add-listen to element
0798: final Vector commentModifications = new Vector();
0799: comment = aTag.getElement(0);
0800: assertNotNull(comment);
0801: comment
0802: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0803:
0804: public void contentChanged(DocumentElementEvent de) {
0805: commentModifications.add(de);
0806: }
0807: });
0808:
0809: model
0810: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0811:
0812: public void updateFinished() {
0813:
0814: model.removeDocumentModelStateListener(this );
0815: synchronized (lock) {
0816: lock.notifyAll();
0817: }
0818: }
0819: });
0820:
0821: doc.insertString(36, "big ", null);
0822: model.forceUpdate();
0823:
0824: synchronized (lock) {
0825: lock.wait(2000);
0826: }
0827:
0828: assertEquals(1, modifiedEls.size()); //one model change event fired
0829: assertEquals(1, commentModifications.size()); //one change event fired
0830: }
0831:
0832: public void testElementAttributes() throws DocumentModelException,
0833: BadLocationException, InterruptedException {
0834: //initialize documents used in tests
0835: initDoc2();
0836: //set the document content
0837: DocumentModel model = DocumentModel.getDocumentModel(doc);
0838:
0839: DocumentElement root = model.getRootElement();
0840: final DocumentElement rootTag = root.getElement(1); //get <root> element
0841: AttributeSet attrs = rootTag.getAttributes();
0842: assertNotNull(attrs);
0843:
0844: assertEquals(1, attrs.getAttributeCount()); //one attribute
0845: assertTrue(attrs.containsAttribute("attrname", "value"));
0846: assertEquals("value", (String) attrs.getAttribute("attrname"));
0847:
0848: //listen to model
0849: final Vector modelAttrsChanges = new Vector();
0850: model
0851: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0852:
0853: public void documentElementAttributesChanged(
0854: DocumentElement de) {
0855: modelAttrsChanges.add(de);
0856: }
0857: });
0858:
0859: //listen to element
0860: final Vector elementAttrsChanges = new Vector();
0861: rootTag
0862: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0863:
0864: public void attributesChanged(DocumentElementEvent e) {
0865: elementAttrsChanges.add(e.getChangedChild());
0866: }
0867: });
0868:
0869: final Object lock = new Object();
0870:
0871: model
0872: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0873:
0874: public void updateFinished() {
0875: synchronized (lock) {
0876: lock.notifyAll();
0877: }
0878: }
0879: });
0880:
0881: doc.insertString(39, "aaa", null);
0882: model.forceUpdate();
0883:
0884: synchronized (lock) {
0885: lock.wait(2000);
0886: }
0887:
0888: //check events
0889: assertEquals(1, modelAttrsChanges.size());
0890: assertEquals(1, elementAttrsChanges.size());
0891:
0892: //check the element
0893: attrs = rootTag.getAttributes();
0894: assertNotNull(attrs);
0895:
0896: assertEquals(1, attrs.getAttributeCount()); //one attribute
0897: assertTrue(attrs.containsAttribute("attrname", "vaaaalue"));
0898: assertEquals("vaaaalue", (String) attrs
0899: .getAttribute("attrname"));
0900: }
0901:
0902: public void testMergeTwoElementsIntoOne()
0903: throws DocumentModelException, BadLocationException,
0904: InterruptedException {
0905: //initialize documents used in tests
0906: initDoc3();
0907: //set the document content
0908: DocumentModel model = DocumentModel.getDocumentModel(doc);
0909: DocumentElement root = model.getRootElement();
0910:
0911: DocumentElement rootTag = root.getElement(1); //get <wood> element
0912: final DocumentElement wood1 = rootTag.getElement(0);
0913: final DocumentElement wood2 = rootTag.getElement(1);
0914:
0915: assertEquals("tree", wood1.getName());
0916: assertEquals("tree", wood2.getName());
0917:
0918: //listen to model
0919: final Vector modelChanges = new Vector();
0920: model
0921: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0922:
0923: public void documentElementRemoved(
0924: DocumentElement de) {
0925: modelChanges.add(de);
0926: }
0927: });
0928:
0929: //listen to element
0930: final Vector elementChanges = new Vector();
0931: rootTag
0932: .addDocumentElementListener(new DocumentElementListenerAdapter() {
0933:
0934: public void elementRemoved(DocumentElementEvent e) {
0935: elementChanges.add(e.getChangedChild());
0936: }
0937: });
0938:
0939: final Object lock = new Object();
0940: model
0941: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
0942:
0943: public void updateFinished() {
0944: synchronized (lock) {
0945: lock.notifyAll();
0946: }
0947: }
0948: });
0949:
0950: doc.remove(40, "/><tree id=\"2\"".length());
0951: model.forceUpdate();
0952:
0953: synchronized (lock) {
0954: lock.wait(2000);
0955: }
0956:
0957: //check events
0958: assertEquals(1, modelChanges.size());
0959: assertEquals(wood2, modelChanges.get(0));
0960: assertEquals(1, elementChanges.size());
0961: assertEquals(wood2, elementChanges.get(0));
0962:
0963: //check the element
0964: AttributeSet attrs = wood1.getAttributes();
0965: assertNotNull(attrs);
0966:
0967: assertEquals(1, attrs.getAttributeCount()); //one attribute
0968: assertTrue(attrs.containsAttribute("id", "1"));
0969: }
0970:
0971: public void testRemoveTwoElementsWithSameName()
0972: throws DocumentModelException, BadLocationException,
0973: InterruptedException {
0974: //initialize documents used in tests
0975: initDoc3();
0976: //set the document content
0977: DocumentModel model = DocumentModel.getDocumentModel(doc);
0978: DocumentElement root = model.getRootElement();
0979:
0980: final DocumentElement rootTag = root.getElement(1); //get <wood> element
0981: DocumentElement wood1 = rootTag.getElement(0);
0982: DocumentElement wood2 = rootTag.getElement(1);
0983:
0984: assertEquals("tree", wood1.getName());
0985: assertEquals("tree", wood2.getName());
0986:
0987: //listen to model
0988: final Vector modelChanges = new Vector();
0989: model
0990: .addDocumentModelListener(new DocumentModelListenerAdapter() {
0991:
0992: public void documentElementRemoved(
0993: DocumentElement de) {
0994: System.out.println("removed " + de);
0995: modelChanges.add(de);
0996: }
0997: });
0998:
0999: //listen to element
1000: final Vector elementChanges = new Vector();
1001: rootTag
1002: .addDocumentElementListener(new DocumentElementListenerAdapter() {
1003:
1004: public void elementRemoved(DocumentElementEvent e) {
1005: System.out.println("removed "
1006: + e.getChangedChild());
1007: elementChanges.add(e.getChangedChild());
1008: }
1009: });
1010:
1011: final Object lock = new Object();
1012: model
1013: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
1014:
1015: public void updateFinished() {
1016: synchronized (lock) {
1017: lock.notifyAll();
1018: }
1019: }
1020: });
1021:
1022: doc.remove(27, "<tree id=\"1\"/><tree id=\"2\"/>".length());
1023: model.forceUpdate();
1024:
1025: synchronized (lock) {
1026: lock.wait(2000);
1027: }
1028:
1029: //check events
1030: assertEquals(2, elementChanges.size()); //two elements removed
1031: assertEquals(2, modelChanges.size()); //two elements removed
1032: assertEquals(0, rootTag.getElementCount());
1033: }
1034:
1035: public void testDoTwoModificationsOnVariousPlaces()
1036: throws DocumentModelException, BadLocationException,
1037: InterruptedException {
1038: //initialize documents used in tests
1039: initDoc1();
1040: //set the document content
1041: DocumentModel model = DocumentModel.getDocumentModel(doc);
1042: DocumentElement root = model.getRootElement();
1043:
1044: DocumentElement rootTag = root.getElement(1); //get root
1045: final DocumentElement aTag = rootTag.getElement(0); //a tag
1046: final DocumentElement bTag = rootTag.getElement(1); //b tag
1047: //listen to model
1048: final Vector modelChanges = new Vector();
1049: model
1050: .addDocumentModelListener(new DocumentModelListenerAdapter() {
1051:
1052: public void documentElementAdded(DocumentElement de) {
1053: modelChanges.add(de);
1054: }
1055: });
1056:
1057: //listen to element
1058: final Vector aChanges = new Vector();
1059: aTag
1060: .addDocumentElementListener(new DocumentElementListenerAdapter() {
1061:
1062: public void elementAdded(DocumentElementEvent e) {
1063: aChanges.add(e.getChangedChild());
1064: }
1065: });
1066:
1067: final Vector bChanges = new Vector();
1068: bTag
1069: .addDocumentElementListener(new DocumentElementListenerAdapter() {
1070:
1071: public void elementAdded(DocumentElementEvent e) {
1072: bChanges.add(e.getChangedChild());
1073: }
1074: });
1075:
1076: final Object lock = new Object();
1077: model
1078: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
1079:
1080: public void updateFinished() {
1081: synchronized (lock) {
1082: lock.notifyAll();
1083: }
1084: }
1085: });
1086:
1087: doc.insertString(30, "<tag1></tag1>", null);
1088: doc.insertString(41 + "<tag1></tag1>".length(),
1089: "<tag2></tag2>", null);
1090:
1091: model.forceUpdate();
1092:
1093: synchronized (lock) {
1094: lock.wait(2000);
1095: }
1096:
1097: //check events
1098: assertEquals(2, modelChanges.size());
1099:
1100: assertEquals(1, aChanges.size());
1101: assertEquals(1, bChanges.size());
1102:
1103: DocumentElement tag1 = aTag.getElement(0);
1104: assertNotNull(tag1);
1105: assertEquals("tag1", tag1.getName());
1106:
1107: DocumentElement tag2 = bTag.getElement(0);
1108: assertNotNull(tag2);
1109: assertEquals("tag2", tag2.getName());
1110: }
1111:
1112: public void testRemoveDocumentContentPartToTheEndOfTheFile()
1113: throws DocumentModelException, BadLocationException,
1114: InterruptedException {
1115: //initialize documents used in tests
1116: initDoc1();
1117: //set the document content
1118: DocumentModel model = DocumentModel.getDocumentModel(doc);
1119: final DocumentElement root = model.getRootElement();
1120:
1121: //listen to model
1122: final Vector modelChanges = new Vector();
1123: model
1124: .addDocumentModelListener(new DocumentModelListenerAdapter() {
1125:
1126: public void documentElementRemoved(
1127: DocumentElement de) {
1128: System.out.println("removed " + de);
1129: modelChanges.add(de);
1130: }
1131: });
1132:
1133: //listen to element
1134: final Vector elementChanges = new Vector();
1135: root
1136: .addDocumentElementListener(new DocumentElementListenerAdapter() {
1137:
1138: public void elementRemoved(DocumentElementEvent e) {
1139: System.out.println("removed "
1140: + e.getChangedChild());
1141: elementChanges.add(e.getChangedChild());
1142: }
1143: });
1144:
1145: final Object lock = new Object();
1146: model
1147: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
1148:
1149: public void updateFinished() {
1150: synchronized (lock) {
1151: lock.notifyAll();
1152: }
1153: }
1154: });
1155:
1156: doc.remove(21, doc.getLength() - 21);
1157: model.forceUpdate();
1158:
1159: synchronized (lock) {
1160: lock.wait(2000);
1161: }
1162:
1163: //check events
1164: //the only <root> element should be removed from the main ROOT document element
1165: //but due to a design flaw in the document model the original elements strucure cannot be
1166: //determined after a removal of a document part so all removed elements are considered
1167: //as children of the most top element which contains their start and end offsets.
1168: //this problem is filtered out in the treenodes so the navigator works correctly.
1169: assertEquals(5, elementChanges.size()); //<root> should be removed
1170: assertEquals(5, modelChanges.size()); //ROOT, A,B,C, text should be removed
1171: assertEquals(1, root.getElementCount()); //has only <?xml...?> element
1172: }
1173:
1174: public void testRemoveElementAttributes()
1175: throws DocumentModelException, BadLocationException,
1176: InterruptedException {
1177: //initialize documents used in tests
1178: initDoc2();
1179: //set the document content
1180: DocumentModel model = DocumentModel.getDocumentModel(doc);
1181:
1182: DocumentElement root = model.getRootElement();
1183: final DocumentElement rootTag = root.getElement(1); //get <root> element
1184: AttributeSet attrs = rootTag.getAttributes();
1185: assertNotNull(attrs);
1186:
1187: assertEquals(1, attrs.getAttributeCount()); //one attribute
1188: assertTrue(attrs.containsAttribute("attrname", "value"));
1189: assertEquals("value", (String) attrs.getAttribute("attrname"));
1190:
1191: //listen to model
1192: final Vector modelAttrsChanges = new Vector();
1193: model
1194: .addDocumentModelListener(new DocumentModelListenerAdapter() {
1195:
1196: public void documentElementAttributesChanged(
1197: DocumentElement de) {
1198: modelAttrsChanges.add(de);
1199: }
1200: });
1201:
1202: //listen to element
1203: final Vector elementAttrsChanges = new Vector();
1204: rootTag
1205: .addDocumentElementListener(new DocumentElementListenerAdapter() {
1206:
1207: public void attributesChanged(DocumentElementEvent e) {
1208: elementAttrsChanges.add(e.getChangedChild());
1209: }
1210: });
1211:
1212: final Object lock = new Object();
1213: model
1214: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
1215:
1216: public void updateFinished() {
1217: synchronized (lock) {
1218: lock.notifyAll();
1219: }
1220: }
1221: });
1222:
1223: doc.remove(26, " attrname=\"value\"".length());
1224: model.forceUpdate();
1225:
1226: synchronized (lock) {
1227: lock.wait(2000);
1228: }
1229:
1230: //check events
1231: assertEquals(1, modelAttrsChanges.size());
1232: assertEquals(1, elementAttrsChanges.size());
1233:
1234: //check the element
1235: attrs = rootTag.getAttributes();
1236: assertNotNull(attrs);
1237: assertEquals(0, attrs.getAttributeCount()); //one attribute
1238: }
1239:
1240: public void testChangeTreeFromElementsWithSameName()
1241: throws DocumentModelException, BadLocationException,
1242: InterruptedException {
1243: //initialize documents used in tests
1244: initDoc4();
1245: //set the document content
1246: final DocumentModel model = DocumentModel.getDocumentModel(doc);
1247: final DocumentElement root = model.getRootElement();
1248:
1249: assertEquals(2, root.getElementCount()); //has <?xml ...?> and <tree id="1"> elements
1250: final DocumentElement tree1 = root.getElement(1); //get <tree id="1"> element
1251: assertEquals(1, tree1.getElementCount()); //has <tree id="2"> element
1252: final DocumentElement tree2 = tree1.getElement(0); //<tree id="2"> element
1253: assertEquals(2, tree2.getElementCount()); //has <tree id="3"> and <tree id="4"> elements
1254: final DocumentElement tree3 = tree2.getElement(0); //<tree id="3"> element
1255: final DocumentElement tree4 = tree2.getElement(1); //<tree id="4"> element
1256: assertEquals("tree", tree3.getName());
1257: assertEquals("tree", tree4.getName());
1258:
1259: //listen to model
1260: final Vector modelChanges = new Vector();
1261: model
1262: .addDocumentModelListener(new DocumentModelListenerAdapter() {
1263:
1264: public void documentElementRemoved(
1265: DocumentElement de) {
1266: System.out.println("removed " + de);
1267: modelChanges.add(de);
1268: }
1269: });
1270:
1271: //listen to element
1272: final Vector tree1Removes = new Vector();
1273: final Vector tree1Adds = new Vector();
1274: tree1
1275: .addDocumentElementListener(new DocumentElementListenerAdapter() {
1276:
1277: public void elementRemoved(DocumentElementEvent e) {
1278: System.out.println("removed "
1279: + e.getChangedChild());
1280: tree1Removes.add(e.getChangedChild());
1281: }
1282:
1283: public void elementAdded(DocumentElementEvent e) {
1284: System.out.println("added "
1285: + e.getChangedChild());
1286: tree1Adds.add(e.getChangedChild());
1287: }
1288: });
1289:
1290: final Object lock = new Object();
1291:
1292: model
1293: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
1294:
1295: public void updateFinished() {
1296: synchronized (lock) {
1297: lock.notifyAll();
1298: }
1299: }
1300: });
1301:
1302: doc.insertString(36, "BIG", null);
1303: model.forceUpdate();
1304:
1305: synchronized (lock) {
1306: lock.wait(2000);
1307: }
1308:
1309: //check events
1310: // tree2 removed from model
1311: assertEquals(1, modelChanges.size());
1312: assertEquals(tree2, modelChanges.get(0));
1313:
1314: //tree2 removed from tree1
1315: assertEquals(1, tree1Removes.size());
1316: assertEquals(tree2, tree1Removes.get(0));
1317:
1318: //tree3 and tree4 added to tree1
1319: assertEquals(2, tree1Adds.size());
1320: assertEquals(tree1Adds.get(0), tree3);
1321: assertEquals(tree1Adds.get(1), tree4);
1322: assertEquals(tree1.getElement(0), tree3);
1323: assertEquals(tree1.getElement(1), tree4);
1324:
1325: //OK lets return back to the original state
1326: //listen to model
1327: final Vector modelChanges2 = new Vector();
1328: model
1329: .addDocumentModelListener(new DocumentModelListenerAdapter() {
1330:
1331: public void documentElementAdded(DocumentElement de) {
1332: System.out.println("added " + de);
1333: modelChanges2.add(de);
1334: }
1335: });
1336:
1337: tree1Adds.clear();
1338: tree1Removes.clear();
1339:
1340: doc.remove(36, "BIG".length());
1341: model.forceUpdate();
1342:
1343: synchronized (lock) {
1344: lock.wait(2000);
1345: }
1346:
1347: //check events
1348: // tree2 added to the model
1349: assertEquals(1, modelChanges.size());
1350: //tree2 added to tree1
1351: assertEquals(1, tree1Adds.size());
1352: //tree3 and 4 removed from tree1
1353: assertEquals(2, tree1Removes.size());
1354:
1355: //so now tree1 has only one children - tree2
1356: assertEquals(1, tree1.getElementCount());
1357:
1358: //and tree2 has tree3 and tree4
1359: assertEquals(2, tree2.getElementCount());
1360:
1361: assertEquals(tree3, tree2.getElement(0));
1362: assertEquals(tree4, tree2.getElement(1));
1363:
1364: assertEquals(2, root.getElementCount()); //has <?xml ...?> and <tree id="1"> elements
1365: }
1366:
1367: public void testRemoveElementsInText()
1368: throws DocumentModelException, BadLocationException,
1369: InterruptedException {
1370: //initialize documents used in tests
1371: initDoc5();
1372: //set the document content
1373: DocumentModel model = DocumentModel.getDocumentModel(doc);
1374:
1375: DocumentElement root = model.getRootElement();
1376: final DocumentElement rootTag = root.getElement(2); //get <root> element (first is PI, second whitespaces)
1377: //listen to model
1378: final Vector removedElements = new Vector();
1379: model
1380: .addDocumentModelListener(new DocumentModelListenerAdapter() {
1381:
1382: public void documentElementRemoved(
1383: DocumentElement de) {
1384: removedElements.add(de);
1385: }
1386: });
1387:
1388: //listen to element
1389: final Vector removedElements2 = new Vector();
1390: rootTag
1391: .addDocumentElementListener(new DocumentElementListenerAdapter() {
1392:
1393: public void elementRemoved(DocumentElementEvent e) {
1394: removedElements2.add(e.getChangedChild());
1395: }
1396: });
1397:
1398: final Object lock = new Object();
1399:
1400: model
1401: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
1402:
1403: public void updateFinished() {
1404:
1405: synchronized (lock) {
1406: lock.notifyAll();
1407: }
1408: }
1409: });
1410:
1411: doc.remove(31, " <a> <c/> </a> ".length());
1412: model.forceUpdate();
1413:
1414: synchronized (lock) {
1415: lock.wait(2000);
1416: }
1417:
1418: assertEquals(6, removedElements.size()); //remove A, C + WHs
1419: assertEquals(6, removedElements2.size());
1420:
1421: assertEquals(3, rootTag.getElementCount()); //has B children and 2 WS children
1422: }
1423:
1424: public void testEditElementWithOneCharContent_71596()
1425: throws DocumentModelException, BadLocationException,
1426: InterruptedException {
1427: //initialize documents used in tests
1428: initDoc6();
1429: //set the document content
1430: DocumentModel model = DocumentModel.getDocumentModel(doc);
1431: DocumentElement root = model.getRootElement();
1432:
1433: final DocumentElement rootTag = root.getElement(0); //get <root> element
1434: assertNotNull(rootTag.getName());
1435:
1436: //listen to model
1437: final Vector modelChanges = new Vector();
1438: model
1439: .addDocumentModelListener(new DocumentModelListenerAdapter() {
1440:
1441: public void documentElementAdded(DocumentElement de) {
1442: modelChanges.add(de);
1443: }
1444: });
1445:
1446: //listen to element
1447: final Vector elementChanges = new Vector();
1448: rootTag
1449: .addDocumentElementListener(new DocumentElementListenerAdapter() {
1450:
1451: public void elementAdded(DocumentElementEvent e) {
1452: elementChanges.add(e.getChangedChild());
1453: }
1454: });
1455:
1456: final Object lock = new Object();
1457: model
1458: .addDocumentModelStateListener(new DocumentModelStateListenerAdapter() {
1459:
1460: public void updateFinished() {
1461: synchronized (lock) {
1462: lock.notifyAll();
1463: }
1464: }
1465: });
1466:
1467: doc.insertString(5, " ", null);
1468: model.forceUpdate();
1469:
1470: synchronized (lock) {
1471: lock.wait(2000);
1472: }
1473:
1474: assertEquals(1, rootTag.getElementCount());
1475:
1476: //check events
1477: assertEquals(0, modelChanges.size());
1478: assertEquals(0, elementChanges.size());
1479: }
1480:
1481: public void testModelLocking() throws DocumentModelException,
1482: BadLocationException, InterruptedException {
1483: //initialize documents used in tests
1484: initDoc1();
1485:
1486: final Semaphore semaphore = new Semaphore();
1487: Runnable r = new Runnable() {
1488:
1489: public void run() {
1490: //set the document content
1491: try {
1492: DocumentModel model = DocumentModel
1493: .getDocumentModel(doc);
1494: //get the document element
1495: DocumentElement root = model.getRootElement();
1496: //make the document dirty
1497: doc.insertString(0, " ", null);
1498: //force the model to resort the children
1499: root.getChildren();
1500:
1501: semaphore.state = true;
1502: synchronized (semaphore) {
1503: semaphore.notifyAll();
1504: }
1505: } catch (Throwable t) {
1506: t.printStackTrace();
1507: t.printStackTrace(getLog());
1508: }
1509: }
1510: };
1511:
1512: Thread t = new Thread(r);
1513: t.start();
1514:
1515: try {
1516: synchronized (semaphore) {
1517: semaphore.wait(5000);
1518: }
1519: } catch (InterruptedException ioe) {
1520: ;
1521: }
1522:
1523: assertTrue(
1524: "The DocumentElement.getChildren() locked up! (model.writeLock() called under model.readLock())",
1525: semaphore.state);
1526: }
1527:
1528: public void testDocumentModelStateListener()
1529: throws DocumentModelException, BadLocationException,
1530: InterruptedException {
1531: //initialize documents used in tests
1532: initDoc6();
1533: //set the document content
1534: DocumentModel model = DocumentModel.getDocumentModel(doc);
1535:
1536: model
1537: .addDocumentModelStateListener(new DocumentModelStateListener() {
1538:
1539: private int state = 0;
1540:
1541: public void sourceChanged() {
1542: assertEquals(state, 0);
1543: state = 1;
1544: }
1545:
1546: public void scanningStarted() {
1547: assertEquals(state, 1);
1548: state = 2;
1549: }
1550:
1551: public void updateStarted() {
1552: assertEquals(state, 2);
1553: state = 3;
1554: }
1555:
1556: public void updateFinished() {
1557: assertEquals(state, 3);
1558: }
1559: });
1560:
1561: doc.insertString(0, " ", null);
1562: model.forceUpdate();
1563: }
1564:
1565: //Jirka Kovalsky's test - not completed yet hence commented out
1566: /*public void testEncapsulateValue_73131() throws DocumentModelException, BadLocationException, InterruptedException {
1567: BaseDocument doc = new BaseDocument(XMLKit.class, false);
1568: doc.putProperty("mimeType", "text/xml");
1569: doc.insertString(0, "<root>X</root>", null);
1570: DocumentModel model = DocumentModel.getDocumentModel(doc);
1571: assertNotNull(model);
1572: assertNotNull(model.getDocument());
1573: DocumentElement root = model.getRootElement();
1574: System.out.println(doc.getText(0, doc.getLength()));
1575: Thread.sleep(MODEL_TIMEOUT * 2); //wait for the model update (started after 500ms)
1576: DocumentModelUtils.dumpElementStructure(root);
1577: doc.insertString(5, " id=1\"", null);
1578: Thread.sleep(MODEL_TIMEOUT * 2); //wait for the model update (started after 500ms)
1579: System.out.println(doc.getText(0, doc.getLength()));
1580: DocumentModelUtils.dumpElementStructure(root);
1581: // <root id=1">X</root>
1582: // 01234567890123456789
1583: doc.insertString(9, "\"", null);
1584: Thread.sleep(MODEL_TIMEOUT * 2); //wait for the model update (started after 500ms)
1585: System.out.println(doc.getText(0, doc.getLength()));
1586: DocumentModelUtils.dumpElementStructure(root);
1587: DocumentElement rootTag = root.getElement(0); //get <root> element
1588: assertEquals(1, rootTag.getElementCount()); // check that root has one element (X)
1589: }*/
1590: private void initDoc1() throws BadLocationException {
1591: /*
1592: supposed structure:
1593: ROOT
1594: |
1595: +--<?xml version='1.0'?>
1596: +--<root>
1597: |
1598: +--<a>
1599: | |
1600: | +---<c>
1601: |
1602: +--<b>
1603: |
1604: +----text
1605: */
1606: doc = new BaseDocument(XMLKit.class, false);
1607: doc.putProperty("mimeType", "text/xml");
1608:
1609: doc
1610: .insertString(
1611: 0,
1612: "<?xml version='1.0'?><root><a><c/></a><b>text</b></root>",
1613: null);
1614: // 012345678901234567890123456789012345678901234567890123456789
1615: // 0 1 2 3 4 5
1616: }
1617:
1618: private void initDoc2() throws BadLocationException {
1619: /*
1620: supposed structure:
1621: ROOT
1622: |
1623: +--<?xml version='1.0'?>
1624: +--<root attrname="value">
1625: |
1626: +---text
1627: */
1628: doc = new BaseDocument(XMLKit.class, false);
1629: doc.putProperty("mimeType", "text/xml");
1630:
1631: doc
1632: .insertString(
1633: 0,
1634: "<?xml version='1.0'?><root attrname=\"value\">text</root>",
1635: null);
1636: // 012345678901234567890123456789012345678901234567890123456789
1637: // 0 1 2 3 4 5
1638: }
1639:
1640: private void initDoc3() throws BadLocationException {
1641: /*
1642: supposed structure:
1643: ROOT
1644: |
1645: +--<?xml version='1.0'?>
1646: +--<wood>
1647: |
1648: +---<tree id="1">
1649: +---<tree id="2">
1650: */
1651: doc = new BaseDocument(XMLKit.class, false);
1652: doc.putProperty("mimeType", "text/xml");
1653:
1654: doc
1655: .insertString(
1656: 0,
1657: "<?xml version=\"1.0\"?><wood><tree id=\"1\"/><tree id=\"2\"/></wood>",
1658: null);
1659: // 01234567890123 4567 89012345678901234567 89 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1660: // 0 1 2 3 4 5 6 7 8
1661: }
1662:
1663: private void initDoc4() throws BadLocationException {
1664: /*
1665: supposed structure:
1666: ROOT
1667: |
1668: +--<?xml version='1.0'?>
1669: +--<tree id="1">
1670: |
1671: +---<tree id="2">
1672: |
1673: +-- <tree id="3"> |
1674: +-- <tree id="4">
1675: */
1676: doc = new BaseDocument(XMLKit.class, false);
1677: doc.putProperty("mimeType", "text/xml");
1678:
1679: doc
1680: .insertString(
1681: 0,
1682: "<?xml version=\"1.0\"?><tree id=\"1\"><tree id=\"2\"><tree id=\"3\"></tree><tree id=\"4\"></tree></tree></tree>",
1683: null);
1684: // 01234567890123 4567 89012345678901234567 89 01234567890123456789012345678901234567890123456789012345678901234567890123456789
1685: // 0 1 2 3 4 5 6 7 8
1686: }
1687:
1688: private void initDoc5() throws BadLocationException {
1689: /*
1690: supposed structure:
1691: ROOT
1692: |
1693: +--<?xml version='1.0'?>
1694: +--<root>
1695: |
1696: +--<a>
1697: | |
1698: | +---<c>
1699: |
1700: +--<b>
1701: |
1702: +----text
1703: */
1704: doc = new BaseDocument(XMLKit.class, false);
1705: doc.putProperty("mimeType", "text/xml");
1706:
1707: doc
1708: .insertString(
1709: 0,
1710: "<?xml version='1.0'?> <root> <a> <c/> </a> <b>text</b> </root>",
1711: null);
1712: // 012345678901234567890123456789012345678901234567890123456789
1713: // 0 1 2 3 4 5
1714: }
1715:
1716: private void initDoc6() throws BadLocationException {
1717: /*
1718: supposed structure:
1719: ROOT
1720: |
1721: +--<root>X</root>
1722: */
1723: doc = new BaseDocument(XMLKit.class, false);
1724: doc.putProperty("mimeType", "text/xml");
1725:
1726: doc.insertString(0, "<root>X</root>", null);
1727: // 0123456789012345
1728: // 0 1
1729: }
1730:
1731: private static class DocumentModelListenerAdapter implements
1732: DocumentModelListener {
1733:
1734: public void documentElementAdded(DocumentElement de) {
1735: }
1736:
1737: public void documentElementAttributesChanged(DocumentElement de) {
1738: }
1739:
1740: public void documentElementChanged(DocumentElement de) {
1741: }
1742:
1743: public void documentElementRemoved(DocumentElement de) {
1744: }
1745: }
1746:
1747: private static class DocumentModelStateListenerAdapter implements
1748: DocumentModelStateListener {
1749:
1750: public void sourceChanged() {
1751: }
1752:
1753: public void scanningStarted() {
1754: }
1755:
1756: public void updateStarted() {
1757: }
1758:
1759: public void updateFinished() {
1760: }
1761: }
1762:
1763: private static class DocumentElementListenerAdapter implements
1764: DocumentElementListener {
1765:
1766: public void attributesChanged(DocumentElementEvent e) {
1767: }
1768:
1769: public void childrenReordered(DocumentElementEvent e) {
1770: }
1771:
1772: public void contentChanged(DocumentElementEvent e) {
1773: }
1774:
1775: public void elementAdded(DocumentElementEvent e) {
1776: }
1777:
1778: public void elementRemoved(DocumentElementEvent e) {
1779: }
1780: }
1781:
1782: private static class Semaphore {
1783:
1784: public boolean state = false;
1785: }
1786: }
|