001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Alexey A. Ivanov
019: * @version $Revision$
020: */package javax.swing.text;
021:
022: import javax.swing.BasicSwingTestCase;
023: import javax.swing.event.DocumentEvent.ElementChange;
024: import javax.swing.event.DocumentEvent.EventType;
025: import javax.swing.text.AbstractDocument.AbstractElement;
026: import javax.swing.text.AbstractDocument.BranchElement;
027: import javax.swing.text.AbstractDocument.Content;
028: import javax.swing.text.AbstractDocument.DefaultDocumentEvent;
029: import javax.swing.text.AbstractDocument.LeafElement;
030: import junit.framework.TestCase;
031:
032: /**
033: * Tests functionality of PlainDocument class.
034: *
035: */
036: public class PlainDocumentTest extends TestCase {
037: private static final String filterNewLinesProperty = "filterNewlines";
038:
039: private static final String paragraphs = "first\nsecond\nthird\n";
040:
041: // 01234 5678901 234567 8
042: /**
043: * Shared document used in tests.
044: */
045: private PlainDocument doc;
046:
047: /**
048: * Event for text insert.
049: */
050: private DefaultDocumentEvent insert;
051:
052: /**
053: * Event for text remove.
054: */
055: private DefaultDocumentEvent remove;
056:
057: /**
058: * Root element where changes are tracked.
059: */
060: private Element root;
061:
062: /**
063: * Changes of the root element
064: */
065: private ElementChange change;
066:
067: /*
068: * @see TestCase#setUp()
069: */
070: @Override
071: protected void setUp() throws Exception {
072: super .setUp();
073: doc = new PlainDocument() {
074: private static final long serialVersionUID = 1L;
075:
076: @Override
077: protected void insertUpdate(
078: final DefaultDocumentEvent event,
079: final AttributeSet attrs) {
080: insert = event;
081: super .insertUpdate(event, attrs);
082: }
083:
084: @Override
085: protected void removeUpdate(final DefaultDocumentEvent event) {
086: remove = event;
087: super .removeUpdate(event);
088: }
089: };
090: root = doc.getDefaultRootElement();
091: }
092:
093: /**
094: * General text insertion checks.
095: * Includes checks for lineLimitAttribute property.
096: */
097: public void testInsertString01() throws BadLocationException {
098: doc.putProperty(PlainDocument.lineLimitAttribute, new Integer(
099: 10));
100: StyleContext context = StyleContext.getDefaultStyleContext();
101: AttributeSet attrs = context.addAttribute(
102: context.getEmptySet(), "key", "value");
103: final String text = "0123456789abcdefghij";
104: doc.insertString(0, text, attrs);
105: assertEquals(text, doc.getText(0, doc.getLength()));
106: assertEquals(3, doc.getDocumentProperties().size());
107: attrs = doc.getDefaultRootElement().getAttributes();
108: assertEquals(0, root.getAttributes().getAttributeCount());
109: assertEquals(1, root.getElementCount());
110: Element line1 = root.getElement(0);
111: assertTrue(line1.isLeaf());
112: assertEquals(0, line1.getElementCount());
113: assertEquals(0, line1.getAttributes().getAttributeCount());
114: }
115:
116: /**
117: * Tests handling of filterNewLine property.
118: */
119: public void testInsertString02() throws BadLocationException {
120: final String content = "one\ntwo\nthree";
121: doc.insertString(0, content, null);
122: assertNull(getNewLineProperty());
123: assertEquals(content, getText());
124: doc.remove(0, doc.getLength());
125: doc.putProperty(filterNewLinesProperty, Boolean.TRUE);
126: doc.insertString(0, content, null);
127: assertSame(Boolean.TRUE, getNewLineProperty());
128: assertEquals(content.replace('\n', ' '), getText());
129: doc.remove(0, doc.getLength());
130: doc.putProperty(filterNewLinesProperty, Boolean.FALSE);
131: doc.insertString(0, content, null);
132: assertSame(Boolean.FALSE, getNewLineProperty());
133: assertEquals(content, getText());
134: }
135:
136: /**
137: * Inserts three lines of text into empty document.
138: */
139: public void testInsertUpdate01() throws BadLocationException {
140: doc.insertString(0, "text", null);
141: assertNull(insert.getChange(root));
142: doc.insertString(0, paragraphs, null);
143: change = insert.getChange(root);
144: assertEquals(4, change.getChildrenAdded().length);
145: assertEquals(1, change.getChildrenRemoved().length);
146: assertEquals(4, root.getElementCount());
147: Element[] children = change.getChildrenAdded();
148: checkOffsets(children[0], 0, 6);
149: checkOffsets(children[1], 6, 13);
150: checkOffsets(children[2], 13, 19);
151: checkOffsets(children[3], 19, 24);
152: }
153:
154: /**
155: * Inserts text (not contains line breaks) into start of a line.
156: */
157: public void testInsertUpdate02() throws BadLocationException {
158: doc.insertString(0, paragraphs, null);
159: doc.insertString(13, "123", null);
160: change = insert.getChange(root);
161: assertEquals(2, change.getChildrenAdded().length);
162: assertEquals(2, change.getChildrenRemoved().length);
163: assertEquals(1, change.getIndex());
164: assertEquals(4, root.getElementCount());
165: Element[] children = change.getChildrenAdded();
166: checkOffsets(children[0], 6, 13);
167: checkOffsets(children[1], 13, 22);
168: children = change.getChildrenRemoved();
169: checkOffsets(children[0], 6, 16);
170: checkOffsets(children[1], 16, 22);
171: }
172:
173: /**
174: * Inserts text (does not contain line breaks) into end
175: * (just before the break) of a line and into a position in a line.
176: */
177: public void testInsertUpdate03() throws BadLocationException {
178: doc.insertString(0, paragraphs, null);
179: doc.insertString(12, "123", null);
180: assertNull(insert.getChange(root));
181: doc.insertString(10, "middle", null);
182: assertNull(insert.getChange(root));
183: }
184:
185: /**
186: * Inserts text (contains text only before line break)
187: * into a position in a line (neither start, nor end).
188: */
189: public void testInsertUpdate04() throws BadLocationException {
190: doc.insertString(0, paragraphs, null);
191: // Insert more text
192: doc.insertString(15, "two and a half\n", null);
193: change = insert.getChange(root);
194: assertEquals(2, change.getChildrenAdded().length);
195: assertEquals(1, change.getChildrenRemoved().length);
196: assertEquals(2, change.getIndex());
197: assertEquals(5, root.getElementCount());
198: Element[] children = change.getChildrenAdded();
199: checkOffsets(children[0], 13, 30);
200: checkOffsets(children[1], 30, 34);
201: children = change.getChildrenRemoved();
202: checkOffsets(children[0], 13, 34);
203: }
204:
205: /**
206: * Inserts text (contains text before and after line break)
207: * into a position in a line (neither start, nor end).
208: */
209: public void testInsertUpdate05() throws BadLocationException {
210: doc.insertString(0, paragraphs, null);
211: doc.insertString(13, "123", null);
212: // Insert more text
213: doc.insertString(16, "two and a half\n321", null);
214: change = insert.getChange(root);
215: assertEquals(2, change.getChildrenAdded().length);
216: assertEquals(1, change.getChildrenRemoved().length);
217: assertEquals(2, change.getIndex());
218: assertEquals(5, root.getElementCount());
219: Element[] children = change.getChildrenAdded();
220: checkOffsets(children[0], 13, 31);
221: checkOffsets(children[1], 31, 40);
222: children = change.getChildrenRemoved();
223: checkOffsets(children[0], 13, 40);
224: }
225:
226: /**
227: * Inserts text (contains text only after line break)
228: * into a position in a line (neither start, nor end).
229: */
230: public void testInsertUpdate06() throws BadLocationException {
231: doc.insertString(0, paragraphs, null);
232: // Insert more text
233: doc.insertString(15, "\n321", null);
234: change = insert.getChange(root);
235: assertEquals(2, change.getChildrenAdded().length);
236: assertEquals(1, change.getChildrenRemoved().length);
237: assertEquals(2, change.getIndex());
238: assertEquals(5, root.getElementCount());
239: Element[] children = change.getChildrenAdded();
240: checkOffsets(children[0], 13, 16);
241: checkOffsets(children[1], 16, 23);
242: children = change.getChildrenRemoved();
243: checkOffsets(children[0], 13, 23);
244: }
245:
246: /**
247: * Inserts text (contains text only after line break)
248: * into start a line (neither start, nor end).
249: */
250: public void testInsertUpdate07() throws BadLocationException {
251: doc.insertString(0, paragraphs, null);
252: doc.insertString(13, "\n321", null);
253: change = insert.getChange(root);
254: assertEquals(3, change.getChildrenAdded().length);
255: assertEquals(2, change.getChildrenRemoved().length);
256: assertEquals(1, change.getIndex());
257: assertEquals(5, root.getElementCount());
258: Element[] children = change.getChildrenAdded();
259: checkOffsets(children[0], 6, 13);
260: checkOffsets(children[1], 13, 14);
261: checkOffsets(children[2], 14, 23);
262: children = change.getChildrenRemoved();
263: checkOffsets(children[0], 6, 17);
264: checkOffsets(children[1], 17, 23);
265: }
266:
267: public void testInsertUpdate08() throws BadLocationException {
268: final int[] createCalled = new int[2];
269: doc = new PlainDocument() {
270: private static final long serialVersionUID = 1L;
271:
272: @Override
273: protected void insertUpdate(
274: final DefaultDocumentEvent event,
275: final AttributeSet attrs) {
276: insert = event;
277: super .insertUpdate(event, attrs);
278: }
279:
280: @Override
281: protected Element createBranchElement(final Element parent,
282: final AttributeSet attrs) {
283: ++createCalled[0];
284: return super .createBranchElement(parent, attrs);
285: }
286:
287: @Override
288: protected Element createLeafElement(final Element parent,
289: final AttributeSet as, final int start,
290: final int end) {
291: ++createCalled[1];
292: return super .createLeafElement(parent, as, start, end);
293: }
294: };
295: root = doc.getDefaultRootElement();
296: createCalled[0] = createCalled[1] = 0;
297: doc.insertString(0, "test", null);
298: assertNull(insert.getChange(root));
299: assertEquals("createBranchElement", 0, createCalled[0]);
300: assertEquals("createLeafElement", 0, createCalled[1]);
301: doc.insertString(0, "\n", null);
302: assertNotNull(insert.getChange(root));
303: assertEquals("createBranchElement", 0, createCalled[0]);
304: assertEquals("createLeafElement", 2, createCalled[1]);
305: }
306:
307: /**
308: * Removes several lines at once and then portion of text within
309: * a line (not on line boundary)
310: */
311: public void testRemoveUpdate01() throws BadLocationException {
312: doc.insertString(0, paragraphs, null);
313: // Remove "second\nthird\n" portion
314: doc.remove(6, 13);
315: change = remove.getChange(root);
316: assertEquals(1, change.getChildrenAdded().length);
317: assertEquals(3, change.getChildrenRemoved().length);
318: assertEquals(2, root.getElementCount());
319: checkOffsets(root.getElement(0), 0, 6);
320: checkOffsets(root.getElement(1), 6, 7);
321: // Remove "irs" from "first"
322: doc.remove(1, 3);
323: assertNull(remove.getChange(root));
324: assertEquals("ft\n", doc.getText(0, doc.getLength()));
325: }
326:
327: /**
328: * Removes text just after line break.
329: */
330: public void testRemoveUpdate02() throws BadLocationException {
331: doc.insertString(0, paragraphs, null);
332: // Remove "se" from "second"
333: doc.remove(6, 2);
334: assertNull(remove.getChange(root));
335: }
336:
337: /**
338: * Removes text just before line break.
339: */
340: public void testRemoveUpdate03() throws BadLocationException {
341: doc.insertString(0, paragraphs, null);
342: // Remove "st" from "first\n"
343: doc.remove(3, 2);
344: assertNull(remove.getChange(root));
345: }
346:
347: /**
348: * Test calling remove with invalid parameters.
349: */
350: public void testRemoveUpdate04() {
351: try {
352: doc.remove(3, 5);
353: fail("BadLocationException should be thrown");
354: } catch (BadLocationException e) {
355: }
356: assertNull(remove);
357: }
358:
359: public void testRemoveUpdate05() throws BadLocationException {
360: doc.insertString(0, paragraphs, null);
361: // Remove the first line break
362: doc.remove(5, 1);
363: change = remove.getChange(root);
364: assertEquals(1, change.getChildrenAdded().length);
365: assertEquals(2, change.getChildrenRemoved().length);
366: assertEquals(3, root.getElementCount());
367: assertEquals("firstsecond\nthird\n", doc.getText(0, doc
368: .getLength()));
369: // 01234567890 123456 7
370: checkOffsets(root.getElement(0), 0, 12);
371: checkOffsets(root.getElement(1), 12, 18);
372: checkOffsets(root.getElement(2), 18, 19);
373: }
374:
375: // Regression for HARMONY-1797
376: public void testRemoveUpdate06() throws Exception {
377: doc = new PlainDocument();
378: insert = doc.new DefaultDocumentEvent(3, 13, EventType.INSERT);
379:
380: doc.removeUpdate(insert); // No exception should be thrown
381: }
382:
383: /**
384: * Tests getParagraphElement when calling on empty document.
385: */
386: public void testGetParagraphElement01() {
387: checkOffsets(doc.getParagraphElement(-1), 0, 1);
388: checkOffsets(doc.getParagraphElement(0), 0, 1);
389: checkOffsets(doc.getParagraphElement(1), 0, 1);
390: checkOffsets(doc.getParagraphElement(2), 0, 1);
391: checkOffsets(doc.getParagraphElement(9), 0, 1);
392: }
393:
394: /**
395: * Tests getParagraphElement when calling on non-empty document.
396: */
397: public void testGetParagraphElement02() throws BadLocationException {
398: doc.insertString(0, paragraphs, null);
399: checkOffsets(doc.getParagraphElement(-1), 0, 6);
400: checkOffsets(doc.getParagraphElement(0), 0, 6);
401: checkOffsets(doc.getParagraphElement(2), 0, 6);
402: checkOffsets(doc.getParagraphElement(8), 6, 13);
403: checkOffsets(doc.getParagraphElement(15), 13, 19);
404: checkOffsets(doc.getParagraphElement(18), 13, 19);
405: checkOffsets(doc.getParagraphElement(19), 19, 20);
406: checkOffsets(doc.getParagraphElement(20), 19, 20);
407: checkOffsets(doc.getParagraphElement(25), 19, 20);
408: }
409:
410: public void testGetDefaultRootElement() {
411: Element root = doc.getDefaultRootElement();
412: assertTrue(root instanceof BranchElement);
413: assertSame(AbstractDocument.ParagraphElementName, root
414: .getName());
415: }
416:
417: /*
418: * Class under test for void PlainDocument(AbstractDocument.Content)
419: */
420: public void testPlainDocumentContent() {
421: doc = new PlainDocument(new GapContent(30));
422: Content content = doc.getContent();
423: assertTrue(content instanceof GapContent);
424: GapContent gapContent = (GapContent) content;
425: assertEquals(29, gapContent.getGapEnd()
426: - gapContent.getGapStart());
427: Object tabSize = doc
428: .getProperty(PlainDocument.tabSizeAttribute);
429: assertEquals(8, ((Integer) tabSize).intValue());
430: assertNull(doc.getProperty(PlainDocument.lineLimitAttribute));
431: assertNotNull(doc.getDefaultRootElement());
432: }
433:
434: /*
435: * Class under test for void PlainDocument()
436: */
437: public void testPlainDocument() {
438: doc = new PlainDocument();
439: Content content = doc.getContent();
440: assertTrue(content instanceof GapContent);
441: GapContent gapContent = (GapContent) content;
442: assertEquals(9, gapContent.getGapEnd()
443: - gapContent.getGapStart());
444: Object tabSize = doc
445: .getProperty(PlainDocument.tabSizeAttribute);
446: assertEquals(8, ((Integer) tabSize).intValue());
447: assertNull(doc.getProperty(PlainDocument.lineLimitAttribute));
448: assertNotNull(doc.getDefaultRootElement());
449: }
450:
451: /**
452: * Generic assertions upon element return by createDefaultRoot.
453: */
454: public void testCreateDefaultRoot01() throws BadLocationException {
455: Element root = doc.createDefaultRoot();
456: assertTrue(root instanceof BranchElement);
457: assertEquals(AbstractDocument.ParagraphElementName, root
458: .getName());
459: assertEquals(1, root.getElementCount());
460: checkOffsets(root.getElement(0), 0, 1);
461: doc.insertString(0, paragraphs, null);
462: root = doc.createDefaultRoot();
463: assertEquals(1, root.getElementCount());
464: if (BasicSwingTestCase.isHarmony()) {
465: checkOffsets(root.getElement(0), doc.getStartPosition()
466: .getOffset(), doc.getEndPosition().getOffset());
467: } else {
468: checkOffsets(root.getElement(0), 0, 1);
469: }
470: }
471:
472: /**
473: * Tests what will happen if <code>createDefaultRoot</code> will not
474: * return instance of <code>AbstractDocument.BranchElement</code> but
475: * something else, for example <code>AbstractDocument.LeafElement</code>.
476: */
477: public void testCreateDefaultRoot02() throws BadLocationException {
478: PlainDocument testDoc = null;
479: try {
480: testDoc = new PlainDocument() {
481: private static final long serialVersionUID = 1L;
482:
483: @Override
484: protected AbstractElement createDefaultRoot() {
485: AbstractElement root = new LeafElement(null, null,
486: 0, 1);
487: return root;
488: }
489: };
490: if (BasicSwingTestCase.isHarmony()) {
491: fail("ClassCastException must be thrown");
492: }
493: } catch (ClassCastException e) {
494: }
495: if (BasicSwingTestCase.isHarmony()) {
496: assertNull(testDoc);
497: return;
498: }
499: AbstractElement root = (AbstractElement) testDoc
500: .getDefaultRootElement();
501: assertTrue(root instanceof LeafElement);
502: assertEquals(AbstractDocument.ContentElementName, root
503: .getName());
504: assertEquals(0, root.getElementCount());
505: assertFalse(root.getAllowsChildren());
506: // Try to insert some text
507: try {
508: testDoc.insertString(0, "text", null);
509: fail("ClassCastException must be thrown");
510: } catch (ClassCastException e) {
511: }
512: }
513:
514: public void testCreateDefaultRoot03() {
515: final boolean[] createCalled = new boolean[2];
516: doc = new PlainDocument() {
517: private static final long serialVersionUID = 1L;
518:
519: @Override
520: protected Element createBranchElement(final Element parent,
521: final AttributeSet attrs) {
522: createCalled[0] = true;
523: return super .createBranchElement(parent, attrs);
524: }
525:
526: @Override
527: protected Element createLeafElement(final Element parent,
528: final AttributeSet as, final int start,
529: final int end) {
530: createCalled[1] = true;
531: return super .createLeafElement(parent, as, start, end);
532: }
533: };
534: createCalled[0] = createCalled[1] = false;
535: doc.createDefaultRoot();
536: assertTrue("createBranchElement is NOT called", createCalled[0]);
537: assertTrue("createLeafElement is NOT called", createCalled[1]);
538: }
539:
540: private Object getNewLineProperty() {
541: return doc.getProperty(filterNewLinesProperty);
542: }
543:
544: private String getText() throws BadLocationException {
545: return doc.getText(0, doc.getLength());
546: }
547:
548: private static void checkOffsets(final Element par,
549: final int start, final int end) {
550: assertEquals(start, par.getStartOffset());
551: assertEquals(end, par.getEndOffset());
552: }
553: }
|