This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 56339
Collapse All | Expand All

(-)editor/arch/arch-editor-util.xml (+865 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" "../../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
3
  <!ENTITY api-questions SYSTEM "../../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
4
]>
5
6
<api-answers
7
  question-version="1.25"
8
  module="editor/util"
9
  author="mmetelka@netbeans.org"
10
>
11
12
  &api-questions;
13
14
15
<!--
16
        <question id="arch-what" when="init">
17
            What is this project good for?
18
            <hint>
19
            Please provide here a few lines describing the project, 
20
            what problem it should solve, provide links to documentation, 
21
            specifications, etc.
22
            </hint>
23
        </question>
24
-->
25
<answer id="arch-what">
26
Editor Utilities module contains useful utility classes and methods used
27
by other editor related modules.
28
</answer>
29
30
31
32
<!--
33
        <question id="arch-overall" when="init">
34
            Describe the overall architecture. 
35
            <hint>
36
            What will be API for 
37
            <a href="http://openide.netbeans.org/tutorial/api-design.html#design.apiandspi">
38
                clients and what support API</a>? 
39
            What parts will be pluggable?
40
            How will plug-ins be registered? Please use <code>&lt;api type="export"/&gt;</code>
41
            to describe your general APIs.
42
            If possible please provide 
43
            simple diagrams. 
44
            </hint>
45
        </question>
46
-->
47
<answer id="arch-overall">
48
The module defines <api name="EditorUtilitiesAPI" group="java" type="export" category="friend"/>.
49
<br/>
50
The present clients are editor/lib and editor/fold modules.
51
</answer>
52
53
54
55
<!--
56
        <question id="arch-quality" when="init">
57
            How will the <a href="http://www.netbeans.org/community/guidelines/q-evangelism.html">quality</a>
58
            of your code be tested and 
59
            how are future regressions going to be prevented?
60
            <hint>
61
            What kind of testing do
62
            you want to use? How much functionality, in which areas,
63
            should be covered by the tests? 
64
            </hint>
65
        </question>
66
-->
67
<answer id="arch-quality">
68
Unit tests are present to verify proper functionality of the contained classes.
69
</answer>
70
71
72
73
<!--
74
        <question id="arch-time" when="init">
75
            What are the time estimates of the work?
76
            <hint>
77
            Please express your estimates of how long the design, implementation,
78
            stabilization are likely to last. How many people will be needed to
79
            implement this and what is the expected milestone by which the work should be 
80
            ready?
81
            </hint>
82
        </question>
83
-->
84
<answer id="arch-time">
85
The module is continuously developed and improved as necessary.
86
</answer>
87
88
89
90
<!--
91
        <question id="arch-usecases" when="init">
92
            Describe the main <a href="http://openide.netbeans.org/tutorial/api-design.html#usecase">
93
            use cases</a> of the new API. Who will use it under
94
            what circumstances? What kind of code would typically need to be written
95
            to use the module?
96
        </question>
97
-->
98
<answer id="arch-usecases">
99
100
<h3>
101
GapList
102
</h3>
103
104
<p>
105
The GapList class is a <code>java.util.List</code> implementation
106
similar to <code>java.util.ArrayList</code> but containing a gap in its underlying 
107
array. After a first modification at a particular index
108
the subsequent modifications around that index are cheap.
109
<br/>
110
The class is suitable for storage of any elements related to editing
111
such as positions, elements, views etc.
112
</p>
113
114
<h3>
115
PriorityMutex
116
</h3>
117
118
<p>
119
The PriorityMutex is a simple mutex implementation
120
allowing to find out that a priority thread (by default Event Dispatch Thread)
121
is waiting to enter the mutex.
122
<br/>
123
It's used e.g. in editor's view hierarchy or in editor fold hierarchy.
124
</p>
125
126
<h3>
127
GapBranchElement
128
</h3>
129
130
<p>
131
GapList-based element implementation suitable for line elements
132
and any other branch element types.
133
</p>
134
135
136
</answer>
137
138
139
140
<!--
141
        <question id="compat-i18n" when="impl">
142
            Is your module correctly internationalized?
143
            <hint>
144
            Correct internationalization means that it obeys instructions 
145
            at <a href="http://www.netbeans.org/download/dev/javadoc/OpenAPIs/org/openide/doc-files/i18n-branding.html">
146
            NetBeans I18N pages</a>.
147
            </hint>
148
        </question>
149
-->
150
<answer id="compat-i18n">
151
Yes.
152
</answer>
153
154
155
156
<!--
157
        <question id="compat-standards" when="init">
158
            Does the module implement or define any standards? Is the 
159
            implementation exact or does it deviate somehow?
160
        </question>
161
-->
162
<answer id="compat-standards">
163
Compatible with standards.
164
</answer>
165
166
167
168
<!--
169
        <question id="compat-version" when="impl">
170
            Can your module coexist with earlier and future
171
            versions of itself? Can you correctly read all old settings? Will future
172
            versions be able to read your current settings? Can you read
173
            or politely ignore settings stored by a future version?
174
            
175
            <hint>
176
            Very helpful for reading settings is to store version number
177
            there, so future versions can decide whether how to read/convert
178
            the settings and older versions can ignore the new ones.
179
            </hint>
180
        </question>
181
-->
182
<answer id="compat-version">
183
Yes.
184
</answer>
185
186
187
188
<!--
189
        <question id="dep-jre" when="final">
190
            Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
191
            <hint>
192
            It is expected that if your module runs on 1.x that it will run 
193
            on 1.x+1 if no, state that please. Also describe here cases where
194
            you run different code on different versions of JRE and why.
195
            </hint>
196
        </question>
197
-->
198
<answer id="dep-jre">
199
JDK1.4 and higher can be used.
200
</answer>
201
202
203
204
<!--
205
        <question id="dep-jrejdk" when="final">
206
            Do you require the JDK or is the JRE enough?
207
        </question>
208
-->
209
<answer id="dep-jrejdk">
210
JRE is sufficient.
211
</answer>
212
213
214
215
<!--
216
        <question id="dep-nb" when="init">
217
            What other NetBeans projects and modules does this one depend on?
218
            <hint>
219
            If you want, describe such projects as imported APIs using
220
            the <code>&lt;api name="identification" type="import or export" category="stable" url="where is the description" /&gt;</code>
221
            </hint>
222
        </question>
223
-->
224
<answer id="dep-nb">
225
The module does not depend on other NetBeans projects.
226
</answer>
227
228
229
230
<!--
231
        <question id="dep-non-nb" when="init">
232
            What other projects outside NetBeans does this one depend on?
233
            
234
            <hint>
235
            Some non-NetBeans projects are packaged as NetBeans modules
236
            (see <a href="http://libs.netbeans.org/">libraries</a>) and
237
            it is preferred to use this approach when more modules may
238
            depend on such third-party library.
239
            </hint>
240
        </question>
241
-->
242
<answer id="dep-non-nb">
243
No other projects.
244
</answer>
245
246
247
248
<!--
249
        <question id="dep-platform" when="init">
250
            On which platforms does your module run? Does it run in the same
251
            way on each?
252
            <hint>
253
            If your module is using JNI or deals with special differences of
254
            OSes like filesystems, etc. please describe here what they are.
255
            </hint>
256
        </question>
257
-->
258
<answer id="dep-platform">
259
All platforms.
260
</answer>
261
262
263
264
<!--
265
        <question id="deploy-dependencies" when="final">
266
            What do other modules need to do to declare a dependency on this one?
267
            <hint>
268
                Provide a sample of the actual lines you would add to a module manifest
269
                to declare a dependency, for example using OpenIDE-Module-Module-Dependencies
270
                or OpenIDE-Module-Requires. You may use the magic token @SPECIFICATION-VERSION@
271
                to represent the current specification version of the module.
272
            </hint>
273
        </question>
274
-->
275
<answer id="deploy-dependencies">
276
<pre>
277
OpenIDE-Module-Module-Dependencies: org.netbeans.modules.editor.util/1 &gt; @SPECIFICATION-VERSION@
278
</pre>
279
</answer>
280
281
282
283
<!--
284
        <question id="deploy-jar" when="impl">
285
            Do you deploy just module JAR file(s) or other files as well?
286
            <hint>
287
            If your module consists of just one module JAR file, just confirm that.
288
            If it uses more than one JAR, describe where they are located, how
289
            they refer to each other. 
290
            If it consist of module JAR(s) and other files, please describe
291
            what is their purpose, why other files are necessary. Please 
292
            make sure that installation/uninstallation leaves the system 
293
            in state as it was before installation.
294
            </hint>
295
        </question>
296
-->
297
<answer id="deploy-jar">
298
No additional files.
299
</answer>
300
301
302
303
<!--
304
        <question id="deploy-nbm" when="impl">
305
            Can you deploy an NBM via the Update Center?
306
            <hint>
307
            If not why?
308
            </hint>
309
        </question>
310
-->
311
<answer id="deploy-nbm">
312
Yes.
313
</answer>
314
315
316
317
<!--
318
        <question id="deploy-packages" when="init">
319
            Are packages of your module made inaccessible by not declaring them
320
            public?
321
            
322
            <hint>
323
            NetBeans module system allows restriction of access rights to
324
            public classes of your module from other modules. This prevents
325
            unwanted dependencies of others on your code and should be used
326
            whenever possible (<a href="http://www.netbeans.org/download/javadoc/OpenAPIs/org/openide/doc-files/upgrade.html#3.4-public-packages">
327
            public packages
328
            </a>). If you do not restrict access to your classes you are
329
            making it too easy for other people to misuse your implementation
330
            details, that is why you should have good reason for not 
331
            restricting package access.
332
            </hint>
333
        </question>
334
-->
335
<answer id="deploy-packages">
336
Yes, where appropriate.
337
</answer>
338
339
340
341
<!--
342
        <question id="deploy-shared" when="final">
343
            Do you need to be installed in the shared location only, or in the user directory only,
344
            or can your module be installed anywhere?
345
            <hint>
346
            Installation location shall not matter, if it does explain why.
347
            Consider also whether <code>InstalledFileLocator</code> can help.
348
            </hint>
349
        </question>
350
-->
351
<answer id="deploy-shared">
352
Anywhere.
353
</answer>
354
355
356
357
<!--
358
        <question id="exec-classloader" when="impl">
359
            Does your code create its own class loader(s)?
360
            <hint>
361
            A bit unusual. Please explain why and what for.
362
            </hint>
363
        </question>
364
-->
365
<answer id="exec-classloader">
366
No.
367
</answer>
368
369
370
371
<!--
372
        <question id="exec-component" when="impl">
373
            Is execution of your code influenced by any (string) property
374
            of any of your components?
375
            
376
            <hint>
377
            Often <code>JComponent.getClientProperty</code>, <code>Action.getValue</code>
378
            or <code>PropertyDescriptor.getValue</code>, etc. are used to influence
379
            a behavior of some code. This of course forms an interface that should
380
            be documented. Also if one depends on some interface that an object
381
            implements (<code>component instanceof Runnable</code>) that forms an
382
            API as well.
383
            </hint>
384
        </question>
385
-->
386
<answer id="exec-component">
387
No.
388
</answer>
389
390
391
392
<!--
393
        <question id="exec-introspection" when="impl">
394
            Does your module use any kind of runtime type information (<code>instanceof</code>,
395
            work with <code>java.lang.Class</code>, etc.)?
396
            <hint>
397
            Check for cases when you have an object of type A and you also
398
            expect it to (possibly) be of type B and do some special action. That
399
            should be documented. The same applies on operations in meta-level
400
            (Class.isInstance(...), Class.isAssignableFrom(...), etc.).
401
            </hint>
402
        </question>
403
-->
404
<answer id="exec-introspection">
405
No.
406
</answer>
407
408
409
410
<!--
411
        <question id="exec-privateaccess" when="final">
412
            Are you aware of any other parts of the system calling some of 
413
            your methods by reflection?
414
            <hint>
415
            If so, describe the "contract" as an API. Likely private or friend one, but
416
            still API and consider rewrite of it.
417
            </hint>
418
        </question>
419
-->
420
<answer id="exec-privateaccess">
421
No.
422
</answer>
423
424
425
426
<!--
427
        <question id="exec-process" when="impl">
428
            Do you execute an external process from your module? How do you ensure
429
            that the result is the same on different platforms? Do you parse output?
430
            Do you depend on result code?
431
            <hint>
432
            If you feed an input, parse the output please declare that as an API.
433
            </hint>
434
        </question>
435
-->
436
<answer id="exec-process">
437
No.
438
</answer>
439
440
441
442
<!--
443
        <question id="exec-property" when="impl">
444
            Is execution of your code influenced by any environment or
445
            Java system (<code>System.getProperty</code>) property?
446
            
447
            <hint>
448
            If there is a property that can change the behavior of your 
449
            code, somebody will likely use it. You should describe what it does 
450
            and the <a href="http://openide.netbeans.org/tutorial/api-design.html#life">stability category</a>
451
            of this API. You may use
452
            <pre>
453
                &lt;api type="export" group="property" name="id" category="private" url="http://..."&gt;
454
                    description of the property, where it is used, what it influence, etc.
455
                &lt;/api&gt;            
456
            </pre>
457
            </hint>
458
        </question>
459
-->
460
<answer id="exec-property">
461
No.
462
</answer>
463
464
465
466
<!--
467
        <question id="exec-reflection" when="impl">
468
            Does your code use Java Reflection to execute other code?
469
            <hint>
470
            This usually indicates a missing or insufficient API in the other
471
            part of the system. If the other side is not aware of your dependency
472
            this contract can be easily broken.
473
            </hint>
474
        </question>
475
-->
476
<answer id="exec-reflection">
477
No.
478
</answer>
479
480
481
482
<!--
483
        <question id="exec-threading" when="impl">
484
            What threading models, if any, does your module adhere to?
485
            <hint>
486
                If your module calls foreign APIs which have a specific threading model,
487
                indicate how you comply with the requirements for multithreaded access
488
                (synchronization, mutexes, etc.) applicable to those APIs.
489
                If your module defines any APIs, or has complex internal structures
490
                that might be used from multiple threads, declare how you protect
491
                data against concurrent access, race conditions, deadlocks, etc.,
492
                and whether such rules are enforced by runtime warnings, errors, assertions, etc.
493
                Examples: a class might be non-thread-safe (like Java Collections); might
494
                be fully thread-safe (internal locking); might require access through a mutex
495
                (and may or may not automatically acquire that mutex on behalf of a client method);
496
                might be able to run only in the event queue; etc.
497
                Also describe when any events are fired: synchronously, asynchronously, etc.
498
                Ideas: <a href="http://core.netbeans.org/proposals/threading/index.html#recommendations">Threading Recommendations</a> (in progress)
499
            </hint>
500
        </question>
501
-->
502
<answer id="exec-threading">
503
No special threading models used.
504
</answer>
505
506
507
508
<!--
509
        <question id="format-clipboard" when="impl">
510
            Which data flavors (if any) does your code read from or insert to
511
            the clipboard (by access to clipboard on means calling methods on <code>java.awt.datatransfer.Transferable</code>?
512
            
513
            <hint>
514
            Often Node's deal with clipboard by usage of <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
515
            Check your code for overriding these methods.
516
            </hint>
517
        </question>
518
-->
519
<answer id="format-clipboard">
520
No clipboard support.
521
</answer>
522
523
524
525
<!--
526
        <question id="format-dnd" when="impl">
527
            Which protocols (if any) does your code understand during Drag &amp; Drop?
528
            <hint>
529
            Often Node's deal with clipboard by usage of <code>Node.drag, Node.getDropType</code>. 
530
            Check your code for overriding these methods. Btw. if they are not overridden, they
531
            by default delegate to <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
532
            </hint>
533
        </question>
534
-->
535
<answer id="format-dnd">
536
No D&amp;D.
537
</answer>
538
539
540
541
<!--
542
        <question id="format-types" when="impl">
543
            Which protocols and file formats (if any) does your module read or write on disk,
544
            or transmit or receive over the network?
545
        </question>
546
-->
547
<answer id="format-types">
548
No files read or written to the disk.
549
</answer>
550
551
552
553
<!--
554
        <question id="lookup-lookup" when="init">
555
            Does your module use <code>org.openide.util.Lookup</code>
556
            or any similar technology to find any components to communicate with? Which ones?
557
            
558
            <hint>
559
            Please describe the interfaces you are searching for, where 
560
            are defined, whether you are searching for just one or more of them,
561
            if the order is important, etc. Also classify the stability of such
562
            API contract.
563
            </hint>
564
        </question>
565
-->
566
<answer id="lookup-lookup">
567
No
568
</answer>
569
570
571
572
<!--
573
        <question id="lookup-register" when="final">
574
            Do you register anything into lookup for other code to find?
575
            <hint>
576
            Do you register using layer file or using <code>META-INF/services</code>?
577
            Who is supposed to find your component?
578
            </hint>
579
        </question>
580
-->
581
<answer id="lookup-register">
582
No.
583
</answer>
584
585
586
587
<!--
588
        <question id="lookup-remove" when="final">
589
            Do you remove entries of other modules from lookup?
590
            <hint>
591
            Why? Of course, that is possible, but it can be dangerous. Is the module
592
            your are masking resource from aware of what you are doing?
593
            </hint>
594
        </question>
595
-->
596
<answer id="lookup-remove">
597
No.
598
</answer>
599
600
601
602
<!--
603
        <question id="perf-exit" when="final">
604
            Does your module run any code on exit?
605
        </question>
606
-->
607
<answer id="perf-exit">
608
No.
609
</answer>
610
611
612
613
<!--
614
        <question id="perf-huge_dialogs" when="final">
615
            Does your module contain any dialogs or wizards with a large number of
616
            GUI controls such as combo boxes, lists, trees, or text areas?
617
        </question>
618
-->
619
<answer id="perf-huge_dialogs">
620
No.
621
</answer>
622
623
624
625
<!--
626
        <question id="perf-limit" when="init">
627
            Are there any hard-coded or practical limits in the number or size of
628
            elements your code can handle?
629
        </question>
630
-->
631
<answer id="perf-limit">
632
No practical limits.
633
</answer>
634
635
636
637
<!--
638
        <question id="perf-mem" when="final">
639
            How much memory does your component consume? Estimate
640
            with a relation to the number of windows, etc.
641
        </question>
642
-->
643
<answer id="perf-mem">
644
Mostly utility classes and methods. Sizeof() tests created where necessary.
645
</answer>
646
647
648
649
<!--
650
        <question id="perf-menus" when="final">
651
            Does your module use dynamically updated context menus, or
652
            context-sensitive actions with complicated enablement logic?
653
        </question>
654
-->
655
<answer id="perf-menus">
656
No.
657
</answer>
658
659
660
661
<!--
662
        <question id="perf-progress" when="final">
663
            Does your module execute any long-running tasks?
664
            
665
            <hint>Long running tasks should never block 
666
            AWT thread as it badly hurts the UI
667
            <a href="http://performance.netbeans.org/responsiveness/issues.html">
668
            responsiveness</a>.
669
            Tasks like connecting over
670
            network, computing huge amount of data, compilation
671
            be done asynchronously (for example
672
            using <code>RequestProcessor</code>), definitively it should 
673
            not block AWT thread.
674
            </hint>
675
        </question>
676
-->
677
<answer id="perf-progress">
678
No.
679
</answer>
680
681
682
683
<!--
684
        <question id="perf-scale" when="init">
685
            Which external criteria influence the performance of your
686
            program (size of file in editor, number of files in menu, 
687
            in source directory, etc.) and how well your code scales?
688
            <hint>
689
            Please include some estimates, there are other more detailed 
690
            questions to answer in later phases of implementation. 
691
            </hint>
692
        </question>
693
-->
694
<answer id="perf-scale">
695
No external criteria.
696
</answer>
697
698
699
700
<!--
701
        <question id="perf-spi" when="init">
702
            How the performance of the plugged in code will be enforced?
703
            <hint>
704
            If you allow foreign code to be plugged into your own module, how
705
            do you enforce that it will behave correctly and quickly and will not
706
            negatively influence the performance of your own module?
707
            </hint>
708
        </question>
709
-->
710
<answer id="perf-spi">
711
No plugged code.
712
</answer>
713
714
715
716
<!--
717
        <question id="perf-startup" when="final">
718
            Does your module run any code on startup?
719
        </question>
720
-->
721
<answer id="perf-startup">
722
No.
723
</answer>
724
725
726
727
<!--
728
        <question id="perf-wakeup" when="final">
729
            Does any piece of your code wake up periodically and do something
730
            even when the system is otherwise idle (no user interaction)?
731
        </question>
732
-->
733
<answer id="perf-wakeup">
734
No.
735
</answer>
736
737
738
739
<!--
740
        <question id="resources-file" when="final">
741
            Does your module use <code>java.io.File</code> directly?
742
            
743
            <hint>
744
            NetBeans provide a logical wrapper over plain files called 
745
            <code>org.openide.filesystems.FileObject</code> that
746
            provides uniform access to such resources and is the preferred
747
            way that should be used. But of course there can be situations when
748
            this is not suitable.
749
            </hint>
750
        </question>
751
-->
752
<answer id="resources-file">
753
No.
754
</answer>
755
756
757
758
<!--
759
        <question id="resources-layer" when="final">
760
            Does your module provide own layer? Does it create any files or
761
            folders in it? What it is trying to communicate by that and with which 
762
            components?
763
            
764
            <hint>
765
            NetBeans allows automatic and declarative installation of resources 
766
            by module layers. Module register files into appropriate places
767
            and other components use that information to perform their task
768
            (build menu, toolbar, window layout, list of templates, set of
769
            options, etc.). 
770
            </hint>
771
        </question>
772
-->
773
<answer id="resources-layer">
774
No.
775
</answer>
776
777
778
779
<!--
780
        <question id="resources-mask" when="final">
781
            Does your module mask/hide/override any resources provided by other modules in
782
            their layers?
783
            
784
            <hint>
785
            If you mask a file provided by another module, you probably depend
786
            on that and do not want the other module to (for example) change
787
            the file's name. That module shall thus make that file available as an API
788
            of some stability category.
789
            </hint>
790
        </question>
791
-->
792
<answer id="resources-mask">
793
No.
794
</answer>
795
796
797
798
<!--
799
        <question id="resources-read" when="final">
800
            Does your module read any resources from layers? For what purpose?
801
            
802
            <hint>
803
            As this is some kind of intermodule dependency, it is a kind of API.
804
            Please describe it and classify according to 
805
            <a href="http://openide.netbeans.org/tutorial/api-design.html#categories">
806
            common stability categories</a>.
807
            </hint>
808
        </question>
809
-->
810
<answer id="resources-read">
811
No.
812
</answer>
813
814
815
816
<!--
817
        <question id="security-grant" when="final">
818
            Does your code grant addition rights to some code?
819
            <hint>Avoid using a classloder that adds some extra
820
            permissions to loaded code unless realy necessary.
821
            Also note that your API implementation
822
            can also expose unneeded permissions to enemy code by
823
            AccessController.doPrilileged() calls.</hint>
824
        </question>
825
-->
826
<answer id="security-grant">
827
No.
828
</answer>
829
830
831
832
<!--
833
        <question id="security-policy" when="final">
834
            Does your functionality require standard policy file modification?
835
            <hint>Your code may pass control to third party code not
836
            coming from trusted domain. It covers code downloaded over
837
            network or code coming from libraries that are not bundled
838
            with NetBeans. Which permissions it needs to grant to which domain?</hint>
839
        </question>
840
-->
841
<answer id="security-policy">
842
No.
843
</answer>
844
845
846
847
<!--
848
        <question id="exec-ant-tasks" when="impl">
849
            Do you define or register any ant tasks that other can use?
850
            
851
            <hint>
852
            If you provide an ant task that users can use, you need to be very
853
            careful about its syntax and behaviour, as it most likely forms an
854
	          API for end users and as there is a lot of end users, their reaction
855
            when such API gets broken can be pretty strong.
856
            </hint>
857
        </question>
858
-->
859
<answer id="exec-ant-tasks">
860
No.
861
</answer>
862
863
</api-answers>
864
865
(-)editor/arch/arch-editor.xml (-7 / +19 lines)
Lines 16-22 Link Here
16
]>
16
]>
17
17
18
<api-answers
18
<api-answers
19
  question-version="1.24"
19
  question-version="1.25"
20
  module="EditorModule"
20
  module="EditorModule"
21
  author="mmetelka@netbeans.org"
21
  author="mmetelka@netbeans.org"
22
>
22
>
Lines 1058-1066 Link Here
1058
    No.
1058
    No.
1059
</answer>
1059
</answer>
1060
1060
1061
<!-- Copy this above the </api-answers> tag! -->
1062
1063
1064
1061
1065
<!--
1062
<!--
1066
        <question id="exec-introspection">
1063
        <question id="exec-introspection">
Lines 1255-1263 Link Here
1255
No answer
1252
No answer
1256
</answer>
1253
</answer>
1257
1254
1258
<!-- Copy this above the </api-answers> tag! -->
1259
1260
1261
1255
1262
<!--
1256
<!--
1263
        <question id="security-grant" when="final">
1257
        <question id="security-grant" when="final">
Lines 1289-1294 Link Here
1289
 <answer id="security-policy">
1283
 <answer id="security-policy">
1290
  <p>
1284
  <p>
1291
   XXX no answer for security-policy
1285
   XXX no answer for security-policy
1286
  </p>
1287
 </answer>
1288
1289
<!--
1290
        <question id="exec-ant-tasks" when="impl">
1291
            Do you define or register any ant tasks that other can use?
1292
            
1293
            <hint>
1294
            If you provide an ant task that users can use, you need to be very
1295
            careful about its syntax and behaviour, as it most likely forms an
1296
	          API for end users and as there is a lot of end users, their reaction
1297
            when such API gets broken can be pretty strong.
1298
            </hint>
1299
        </question>
1300
-->
1301
 <answer id="exec-ant-tasks">
1302
  <p>
1303
  No.
1292
  </p>
1304
  </p>
1293
 </answer>
1305
 </answer>
1294
1306
(-)editor/arch/build.xml (+2 lines)
Lines 28-36 Link Here
28
28
29
  <target name="answer" description="Generates HTML file with answers to architecture questions" >
29
  <target name="answer" description="Generates HTML file with answers to architecture questions" >
30
    <arch answers="arch-editor.xml" output="${arch.outputdir}/arch-editor.html" />
30
    <arch answers="arch-editor.xml" output="${arch.outputdir}/arch-editor.html" />
31
    <arch answers="arch-editor-util.xml" output="${arch.outputdir}/arch-editor-util.html" />
31
  </target>
32
  </target>
32
33
33
  <target name="clean">
34
  <target name="clean">
34
    <delete file="${arch.outputdir}/arch-editor.html" />
35
    <delete file="${arch.outputdir}/arch-editor.html" />
36
    <delete file="${arch.outputdir}/arch-editor-util.html" />
35
  </target>    
37
  </target>    
36
</project>
38
</project>
(-)editor/fold/src/org/netbeans/modules/editor/fold/FoldChildren.java (-1 / +1 lines)
Lines 15-21 Link Here
15
15
16
import org.netbeans.api.editor.fold.Fold;
16
import org.netbeans.api.editor.fold.Fold;
17
import org.netbeans.modules.editor.fold.ApiPackageAccessor;
17
import org.netbeans.modules.editor.fold.ApiPackageAccessor;
18
import org.netbeans.modules.editor.util.GapList;
18
import org.netbeans.lib.editor.util.GapList;
19
19
20
//import org.netbeans.spi.lexer.util.GapObjectArray;
20
//import org.netbeans.spi.lexer.util.GapObjectArray;
21
21
(-)editor/fold/src/org/netbeans/modules/editor/fold/FoldHierarchyExecution.java (-1 / +1 lines)
Lines 39-45 Link Here
39
import org.netbeans.spi.editor.fold.FoldManager;
39
import org.netbeans.spi.editor.fold.FoldManager;
40
import org.netbeans.spi.editor.fold.FoldManagerFactory;
40
import org.netbeans.spi.editor.fold.FoldManagerFactory;
41
import org.netbeans.spi.editor.fold.FoldOperation;
41
import org.netbeans.spi.editor.fold.FoldOperation;
42
import org.netbeans.modules.editor.util.PriorityMutex;
42
import org.netbeans.lib.editor.util.PriorityMutex;
43
import org.openide.ErrorManager;
43
import org.openide.ErrorManager;
44
44
45
/**
45
/**
(-)editor/libsrc/org/netbeans/editor/LineRootElement.java (-1 / +1 lines)
Lines 23-29 Link Here
23
import javax.swing.text.BadLocationException;
23
import javax.swing.text.BadLocationException;
24
import javax.swing.text.Segment;
24
import javax.swing.text.Segment;
25
import javax.swing.text.StyleContext;
25
import javax.swing.text.StyleContext;
26
import org.netbeans.modules.editor.util.element.GapBranchElement;
26
import org.netbeans.lib.editor.util.swing.GapBranchElement;
27
import org.openide.ErrorManager;
27
import org.openide.ErrorManager;
28
28
29
/**
29
/**
(-)editor/libsrc/org/netbeans/editor/view/spi/LockView.java (-1 / +1 lines)
Lines 25-31 Link Here
25
import javax.swing.text.Position;
25
import javax.swing.text.Position;
26
import javax.swing.text.View;
26
import javax.swing.text.View;
27
import javax.swing.text.ViewFactory;
27
import javax.swing.text.ViewFactory;
28
import org.netbeans.modules.editor.util.PriorityMutex;
28
import org.netbeans.lib.editor.util.PriorityMutex;
29
29
30
/**
30
/**
31
 * View that allow to lock the view hierarchy.
31
 * View that allow to lock the view hierarchy.
(-)editor/libsrc/org/netbeans/lib/editor/view/GapBoxView.java (-1 / +1 lines)
Lines 36-42 Link Here
36
import org.netbeans.editor.view.spi.ViewLayoutQueue;
36
import org.netbeans.editor.view.spi.ViewLayoutQueue;
37
import org.netbeans.editor.view.spi.ViewLayoutState;
37
import org.netbeans.editor.view.spi.ViewLayoutState;
38
import org.netbeans.editor.view.spi.ViewUtilities;
38
import org.netbeans.editor.view.spi.ViewUtilities;
39
import org.netbeans.modules.editor.util.element.ElementUtilities;
39
import org.netbeans.lib.editor.util.swing.ElementUtilities;
40
40
41
//import org.netbeans.spi.lexer.util.GapObjectArray;
41
//import org.netbeans.spi.lexer.util.GapObjectArray;
42
42
(-)editor/util/manifest.mf (-2 / +2 lines)
Lines 1-5 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.editor.util/1
2
OpenIDE-Module: org.netbeans.modules.editor.util/1
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/editor/util/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/lib/editor/util/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.2
4
OpenIDE-Module-Specification-Version: 1.3
5
5
(-)editor/util/api/apichanges.xml (+140 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?><!-- -*- sgml-indent-step: 2 -*- -->
2
<!--
3
   -                 Sun Public License Notice
4
   - 
5
   - The contents of this file are subject to the Sun Public License
6
   - Version 1.0 (the "License"). You may not use this file except in
7
   - compliance with the License. A copy of the License is available at
8
   - http://www.sun.com/
9
   - 
10
   - The Original Code is NetBeans. The Initial Developer of the Original
11
   - Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
12
   - Microsystems, Inc. All Rights Reserved.
13
  -->
14
<?xml-stylesheet type="text/xml" href="../../../nbbuild/javadoctools/apichanges.xsl"?>
15
<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../../../nbbuild/javadoctools/apichanges.dtd">
16
17
<!--
18
19
INFO FOR PEOPLE ADDING CHANGES:
20
21
Check the DTD (apichanges.dtd) for details on the syntax. You do not
22
need to regenerate the HTML, as this is part of Javadoc generation; just
23
change the XML. Rough syntax of a change (several parts optional):
24
25
<change>
26
    <api name="compiler"/>
27
    <summary>Some brief description here, can use <b>XHTML</b></summary>
28
    <version major="1" minor="99"/>
29
    <date day="13" month="6" year="2001"/>
30
    <author login="jrhacker"/>
31
    <compatibility addition="yes"/>
32
    <description>
33
        The main description of the change here.
34
        Again can use full <b>XHTML</b> as needed.
35
    </description>
36
    <class package="org.openide.compiler" name="DoWhatIWantCompiler"/>
37
    <issue number="14309"/>
38
</change>
39
40
Also permitted elements: <package>, <branch>. <version> is API spec
41
version, recommended for all new changes. <compatibility> should say
42
if things were added/modified/deprecated/etc. and give all information
43
related to upgrading old code. List affected top-level classes and
44
link to issue numbers if applicable. See the DTD for more details.
45
46
Changes need not be in any particular order, they are sorted in various
47
ways by the stylesheet anyway.
48
49
Dates are assumed to mean "on the trunk". If you *also* make the same
50
change on a stabilization branch, use the <branch> tag to indicate this
51
and explain why the change was made on a branch in the <description>.
52
53
Please only change this file on the trunk! Rather: you can change it
54
on branches if you want, but these changes will be ignored; only the
55
trunk version of this file is important.
56
57
Deprecations do not count as incompatible, assuming that code using the
58
deprecated calls continues to see their documented behavior. But do
59
specify deprecation="yes" in <compatibility>.
60
61
This file is not a replacement for Javadoc: it is intended to list changes,
62
not describe the complete current behavior, for which ordinary documentation
63
is the proper place.
64
65
-->
66
67
<apichanges>
68
69
  <!-- First, a list of API names you may use: -->
70
  <apidefs>
71
    <!-- Probably should not be used much: -->
72
    <apidef name="util">Editor Utilities API</apidef>
73
  </apidefs>
74
75
<!-- ACTUAL CHANGES BEGIN HERE: -->
76
77
  <changes>
78
     <change>
79
      <summary>Repackaged to org.netbeans.lib.editor.util package</summary>
80
        <version major="1" minor="3"/>
81
        <date day="13" month="3" year="2005"/>
82
        <author login="jtulach"/>
83
        <compatibility addition="yes" binary="incompatible" semantic="incompatible" />
84
        <description>
85
        <p>
86
            The present classes were repackaged from org.netbeans.modules.editor.util
87
            into org.netbeans.lib.editor.util package to fulfil the editor module
88
            split proposal <a href="http://www.netbeans.org/issues/show_bug.cgi?id=51486">#51486</a>
89
            according to which the editor classes independent of the NB IDE
90
            should be placed under org.netbeans.lib package.
91
        </p>
92
        </description>
93
        <issue number="56339"/>
94
    </change>
95
96
  </changes>
97
98
  <!-- Now the surrounding HTML text and document structure: -->
99
100
  <htmlcontents>
101
<!--
102
103
                            NO NO NO NO NO!
104
105
         ==============>    DO NOT EDIT ME!  <======================
106
107
          AUTOMATICALLY GENERATED FROM APICHANGES.XML, DO NOT EDIT
108
109
                SEE editor/util/api/apichanges.xml
110
111
-->
112
    <head>
113
      <title>Change History for the Editor Utilities API</title>
114
      <link rel="stylesheet" href="prose.css" type="text/css"/>
115
    </head>
116
    <body>
117
118
<p class="overviewlink"><a href="overview-summary.html">Overview</a></p>
119
120
<h1>Introduction</h1>
121
122
<p>This document lists changes made to the <a href="http://editor.netbeans.org/">Editor Utilities
123
API</a>. Please ask on the <code>dev@openide.netbeans.org</code> mailing list
124
if you have any questions about the details of a
125
change, or are wondering how to convert existing code to be compatible.</p>
126
127
<p>Most module authors should start by reading the <a
128
href="@OPENIDE@org/openide/doc-files/upgrade.html">Upgrade
129
Guide</a> for the current release.</p>
130
131
<!-- The actual lists of changes, as summaries and details: -->
132
133
      <hr/><standard-changelists module-code-name="org.netbeans.modules.editor.util"/>
134
135
      <hr/><p>@FOOTER@</p>
136
137
    </body>
138
  </htmlcontents>
139
140
</apichanges>
(-)editor/util/nbproject/project.properties (+2 lines)
Lines 12-14 Link Here
12
#javadoc.arch=${basedir}/arch/arch-editor-util.xml
12
#javadoc.arch=${basedir}/arch/arch-editor-util.xml
13
javadoc.name=EditorUtilities
13
javadoc.name=EditorUtilities
14
javadoc.title=Editor Utilities
14
javadoc.title=Editor Utilities
15
javadoc.arch=${basedir}/../arch/arch-editor-util.xml
16
javadoc.apichanges=${basedir}/api/apichanges.xml
(-)editor/util/nbproject/project.xml (-2 / +2 lines)
Lines 29-36 Link Here
29
                </dependency>
29
                </dependency>
30
            </module-dependencies>
30
            </module-dependencies>
31
            <public-packages>
31
            <public-packages>
32
                <package>org.netbeans.modules.editor.util</package>
32
                <package>org.netbeans.lib.editor.util</package>
33
                <package>org.netbeans.modules.editor.util.element</package>
33
                <package>org.netbeans.lib.editor.util.swing</package>
34
            </public-packages>
34
            </public-packages>
35
        </data>
35
        </data>
36
    </configuration>
36
    </configuration>
(-)editor/util/src/org/netbeans/lib/editor/util/Bundle.properties (+16 lines)
Added Link Here
1
#                 Sun Public License Notice
2
# 
3
# The contents of this file are subject to the Sun Public License
4
# Version 1.0 (the "License"). You may not use this file except in
5
# compliance with the License. A copy of the License is available at
6
# http://www.sun.com/
7
# 
8
# The Original Code is NetBeans. The Initial Developer of the Original
9
# Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
10
# Microsystems, Inc. All Rights Reserved.
11
12
OpenIDE-Module-Name=Editor Utilities
13
OpenIDE-Module-Display-Category=Editing
14
OpenIDE-Module-Short-Description=Contains various support classes for editor related modules
15
OpenIDE-Module-Long-Description=Editor Utilities module contains various utility classes and methods for functionality related to editing
16
(-)editor/util/src/org/netbeans/lib/editor/util/GapList.java (+785 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.lib.editor.util;
15
16
import java.util.AbstractList;
17
import java.util.Collection;
18
import java.util.RandomAccess;
19
20
/**
21
 * List implementation that stores items in an array
22
 * with a gap.
23
 *
24
 * @author Miloslav Metelka
25
 * @version 1.00
26
 */
27
28
public class GapList extends AbstractList
29
implements RandomAccess, Cloneable, java.io.Serializable {
30
    
31
    private static final Object[] EMPTY_ELEMENT_ARRAY = new Object[0];
32
    
33
    /**
34
     * The array buffer into which the elements are stored.
35
     * <br>
36
     * The elements are stored in the whole array except
37
     * the indexes starting at <code>gapStart</code>
38
     * till <code>gapStart + gapLength - 1</code>.
39
     */
40
    private transient Object elementData[];
41
    
42
    /**
43
     * The start of the gap in the elementData array.
44
     */
45
    private int gapStart;
46
    
47
    /**
48
     * Length of the gap in the elementData array starting at gapStart.
49
     */
50
    private int gapLength;
51
    
52
    /**
53
     * Constructs an empty list with the specified initial capacity.
54
     *
55
     * @param   initialCapacity   the initial capacity of the list.
56
     * @exception IllegalArgumentException if the specified initial capacity
57
     *            is negative
58
     */
59
    public GapList(int initialCapacity) {
60
        if (initialCapacity < 0) {
61
            throw new IllegalArgumentException("Illegal Capacity: " // NOI18N
62
                + initialCapacity);
63
        }
64
        this.elementData = new Object[initialCapacity];
65
        this.gapLength = initialCapacity;
66
    }
67
    
68
    /**
69
     * Constructs an empty list.
70
     */
71
    public GapList() {
72
        elementData = EMPTY_ELEMENT_ARRAY;
73
    }
74
    
75
    /**
76
     * Constructs a list containing the elements of the specified
77
     * collection, in the order they are returned by the collection's
78
     * iterator.  The <tt>GapList</tt> instance has an initial capacity of
79
     * 110% the size of the specified collection.
80
     *
81
     * @param c the collection whose elements are to be placed into this list.
82
     * @throws NullPointerException if the specified collection is null.
83
     */
84
    public GapList(Collection c) {
85
        int size = c.size();
86
        // Allow 10% room for growth
87
        elementData = new Object[
88
        (int)Math.min((size*110L)/100,Integer.MAX_VALUE)];
89
        c.toArray(elementData);
90
        this.gapStart = size;
91
        this.gapLength = elementData.length - size;
92
    }
93
    
94
    /**
95
     * Trims the capacity of this <tt>GapList</tt> instance to be the
96
     * list's current size.  An application can use this operation to minimize
97
     * the storage of an <tt>GapList</tt> instance.
98
     */
99
    public void trimToSize() {
100
        modCount++;
101
        if (gapLength > 0) {
102
            int newLength = elementData.length - gapLength;
103
            Object[] newElementData = new Object[newLength];
104
            copyAllData(newElementData);
105
            elementData = newElementData;
106
            // Leave gapStart as is
107
            gapLength = 0;
108
        }
109
    }
110
    
111
    /**
112
     * Increases the capacity of this <tt>GapList</tt> instance, if
113
     * necessary, to ensure  that it can hold at least the number of elements
114
     * specified by the minimum capacity argument.
115
     *
116
     * @param   minCapacity   the desired minimum capacity.
117
     */
118
    public void ensureCapacity(int minCapacity) {
119
        modCount++; // expected to always increment modCount - see add() operations
120
        int oldCapacity = elementData.length;
121
        if (minCapacity > oldCapacity) {
122
            int newCapacity = (oldCapacity * 3)/2 + 1;
123
            if (newCapacity < minCapacity) {
124
                newCapacity = minCapacity;
125
            }
126
            int gapEnd = gapStart + gapLength;
127
            int afterGapLength = (oldCapacity - gapEnd);
128
            // Must ensure the gap will not be logically moved
129
            // (would have to call movedAbove/BeforeGapUpdate() methods)
130
            int newGapEnd = newCapacity - afterGapLength;
131
            Object[] newElementData = new Object[newCapacity];
132
            System.arraycopy(elementData, 0, newElementData, 0, gapStart);
133
            System.arraycopy(elementData, gapEnd, newElementData, newGapEnd, afterGapLength);
134
            elementData = newElementData;
135
            gapLength = newGapEnd - gapStart;
136
        }
137
    }
138
    
139
    /**
140
     * Returns the number of elements in this list.
141
     *
142
     * @return  the number of elements in this list.
143
     */
144
    public int size() {
145
        return elementData.length - gapLength;
146
    }
147
    
148
    /**
149
     * Tests if this list has no elements.
150
     *
151
     * @return  <tt>true</tt> if this list has no elements;
152
     *          <tt>false</tt> otherwise.
153
     */
154
    public boolean isEmpty() {
155
        return (elementData.length == gapLength);
156
    }
157
    
158
    /**
159
     * Returns <tt>true</tt> if this list contains the specified element.
160
     *
161
     * @param elem element whose presence in this List is to be tested.
162
     * @return  <code>true</code> if the specified element is present;
163
     *		<code>false</code> otherwise.
164
     */
165
    public boolean contains(Object elem) {
166
        return indexOf(elem) >= 0;
167
    }
168
    
169
    /**
170
     * Searches for the first occurence of the given argument, testing
171
     * for equality using the <tt>equals</tt> method.
172
     *
173
     * @param   elem   an object.
174
     * @return  the index of the first occurrence of the argument in this
175
     *          list; returns <tt>-1</tt> if the object is not found.
176
     * @see     Object#equals(Object)
177
     */
178
    public int indexOf(Object elem) {
179
        if (elem == null) {
180
            int i = 0;
181
            while (i < gapStart) {
182
                if (elementData[i] == null) {
183
                    return i;
184
                }
185
                i++;
186
            }
187
            i += gapLength;
188
            int elementDataLength = elementData.length;
189
            while (i < elementDataLength) {
190
                if (elementData[i] == null) {
191
                    return i;
192
                }
193
                i++;
194
            }
195
            
196
        } else { // elem not null
197
            int i = 0;
198
            while (i < gapStart) {
199
                if (elem.equals(elementData[i])) {
200
                    return i;
201
                }
202
                i++;
203
            }
204
            i += gapLength;
205
            int elementDataLength = elementData.length;
206
            while (i < elementDataLength) {
207
                if (elem.equals(elementData[i])) {
208
                    return i;
209
                }
210
                i++;
211
            }
212
        }
213
        
214
        return -1;
215
    }
216
    
217
    /**
218
     * Returns the index of the last occurrence of the specified object in
219
     * this list.
220
     *
221
     * @param   elem   the desired element.
222
     * @return  the index of the last occurrence of the specified object in
223
     *          this list; returns -1 if the object is not found.
224
     */
225
    public int lastIndexOf(Object elem) {
226
        if (elem == null) {
227
            int i = elementData.length - 1;
228
            int gapEnd = gapStart + gapLength;
229
            while (i >= gapEnd) {
230
                if (elementData[i] == null) {
231
                    return i;
232
                }
233
                i--;
234
            }
235
            i -= gapLength;
236
            while (i >= 0) {
237
                if (elementData[i] == null) {
238
                    return i;
239
                }
240
                i--;
241
            }
242
            
243
        } else { // elem not null
244
            int i = elementData.length - 1;
245
            int gapEnd = gapStart + gapLength;
246
            while (i >= gapEnd) {
247
                if (elem.equals(elementData[i])) {
248
                    return i;
249
                }
250
                i--;
251
            }
252
            i -= gapLength;
253
            while (i >= 0) {
254
                if (elem.equals(elementData[i])) {
255
                    return i;
256
                }
257
                i--;
258
            }
259
        }
260
        
261
        return -1;
262
    }
263
    
264
    /**
265
     * Returns a shallow copy of this <tt>GapList</tt> instance.  (The
266
     * elements themselves are not copied.)
267
     *
268
     * @return  a clone of this <tt>GapList</tt> instance.
269
     */
270
    public Object clone() {
271
        try {
272
            GapList clonedList = (GapList)super.clone();
273
            int size = size();
274
            Object[] clonedElementData = new Object[size];
275
            copyAllData(clonedElementData);
276
            clonedList.elementData = clonedElementData;
277
            // Will retain gapStart - would have to call moved*() otherwise
278
            clonedList.gapStart = size;
279
            clonedList.resetModCount();
280
            return clonedList;
281
282
        } catch (CloneNotSupportedException e) {
283
            // this shouldn't happen, since we are Cloneable
284
            throw new InternalError();
285
        }
286
    }
287
    
288
    public void copyItems(int srcStartIndex, int srcEndIndex,
289
    Object[] dest, int destIndex) {
290
        
291
        if (srcStartIndex < 0 || srcEndIndex < srcStartIndex || srcEndIndex > size()) {
292
            throw new IndexOutOfBoundsException("srcStartIndex=" + srcStartIndex // NOI18N
293
            + ", srcEndIndex=" + srcEndIndex + ", size()=" + size()); // NOI18N
294
        }
295
        
296
        if (srcEndIndex < gapStart) { // fully below gap
297
            System.arraycopy(elementData, srcStartIndex,
298
            dest, destIndex, srcEndIndex - srcStartIndex);
299
            
300
        } else { // above gap or spans the gap
301
            if (srcStartIndex >= gapStart) { // fully above gap
302
                System.arraycopy(elementData, srcStartIndex + gapLength, dest, destIndex,
303
                srcEndIndex - srcStartIndex);
304
                
305
            } else { // spans gap
306
                int beforeGap = gapStart - srcStartIndex;
307
                System.arraycopy(elementData, srcStartIndex, dest, destIndex, beforeGap);
308
                System.arraycopy(elementData, gapStart + gapLength, dest, destIndex + beforeGap,
309
                srcEndIndex - srcStartIndex - beforeGap);
310
            }
311
        }
312
    }
313
    
314
    /**
315
     * Returns an array containing all of the elements in this list
316
     * in the correct order.
317
     *
318
     * @return an array containing all of the elements in this list
319
     * 	       in the correct order.
320
     */
321
    public Object[] toArray() {
322
        int size = size();
323
        Object[] result = new Object[size];
324
        copyAllData(result);
325
        return result;
326
    }
327
    
328
    /**
329
     * Returns an array containing all of the elements in this list in the
330
     * correct order; the runtime type of the returned array is that of the
331
     * specified array.  If the list fits in the specified array, it is
332
     * returned therein.  Otherwise, a new array is allocated with the runtime
333
     * type of the specified array and the size of this list.<p>
334
     *
335
     * If the list fits in the specified array with room to spare (i.e., the
336
     * array has more elements than the list), the element in the array
337
     * immediately following the end of the collection is set to
338
     * <tt>null</tt>.  This is useful in determining the length of the list
339
     * <i>only</i> if the caller knows that the list does not contain any
340
     * <tt>null</tt> elements.
341
     *
342
     * @param a the array into which the elements of the list are to
343
     *		be stored, if it is big enough; otherwise, a new array of the
344
     * 		same runtime type is allocated for this purpose.
345
     * @return an array containing the elements of the list.
346
     * @throws ArrayStoreException if the runtime type of a is not a supertype
347
     *         of the runtime type of every element in this list.
348
     */
349
    public Object[] toArray(Object a[]) {
350
        int size = size();
351
        if (a.length < size) {
352
            a = (Object[])java.lang.reflect.Array.newInstance(
353
                a.getClass().getComponentType(), size);
354
        }
355
        copyAllData(a);
356
        if (a.length > size)
357
            a[size] = null;
358
        
359
        return a;
360
    }
361
    
362
    // Positional Access Operations
363
    
364
    /**
365
     * Returns the element at the specified position in this list.
366
     *
367
     * @param  index index of element to return.
368
     * @return the element at the specified position in this list.
369
     * @throws    IndexOutOfBoundsException if index is out of range <tt>(index
370
     * 		  &lt; 0 || index &gt;= size())</tt>.
371
     */
372
    public Object get(int index) {
373
        // rangeCheck(index) not necessary - would fail with AIOOBE anyway
374
        return elementData[(index < gapStart) ? index : (index + gapLength)];
375
    }
376
    
377
    /**
378
     * Replaces the element at the specified position in this list with
379
     * the specified element.
380
     *
381
     * @param index index of element to replace.
382
     * @param element element to be stored at the specified position.
383
     * @return the element previously at the specified position.
384
     * @throws    IndexOutOfBoundsException if index out of range
385
     *		  <tt>(index &lt; 0 || index &gt;= size())</tt>.
386
     */
387
    public Object set(int index, Object element) {
388
        // rangeCheck(index) not necessary - would fail with AIOOBE anyway
389
        if (index >= gapStart) {
390
            index += gapLength;
391
        }
392
        Object oldValue = elementData[index];
393
        elementData[index] = element;
394
        return oldValue;
395
    }
396
    
397
    /**
398
     * Appends the specified element to the end of this list.
399
     *
400
     * @param o element to be appended to this list.
401
     * @return <tt>true</tt> (as per the general contract of Collection.add).
402
     */
403
    public boolean add(Object o) {
404
        add(size(), o);
405
        return true;
406
    }
407
    
408
    /**
409
     * Inserts the specified element at the specified position in this
410
     * list. Shifts the element currently at that position (if any) and
411
     * any subsequent elements to the right (adds one to their indices).
412
     *
413
     * @param index index at which the specified element is to be inserted.
414
     * @param element element to be inserted.
415
     * @throws    IndexOutOfBoundsException if index is out of range
416
     *		  <tt>(index &lt; 0 || index &gt; size())</tt>.
417
     */
418
    public void add(int index, Object element) {
419
        int size = size();
420
        if (index > size || index < 0) {
421
            throw new IndexOutOfBoundsException(
422
                "Index: " + index + ", Size: " + size); // NOI18N
423
        }
424
425
        ensureCapacity(size + 1);  // Increments modCount!!
426
        moveGap(index);
427
428
        elementData[gapStart++] = element;
429
        gapLength--;
430
    }
431
    
432
    /**
433
     * Appends all of the elements in the specified Collection to the end of
434
     * this list, in the order that they are returned by the
435
     * specified Collection's Iterator.  The behavior of this operation is
436
     * undefined if the specified Collection is modified while the operation
437
     * is in progress.  (This implies that the behavior of this call is
438
     * undefined if the specified Collection is this list, and this
439
     * list is nonempty.)
440
     *
441
     * @param c the elements to be inserted into this list.
442
     * @return <tt>true</tt> if this list changed as a result of the call.
443
     * @throws    NullPointerException if the specified collection is null.
444
     */
445
    public boolean addAll(Collection c) {
446
        return addAll(size(), c);
447
    }
448
    
449
    /**
450
     * Inserts all of the elements in the specified Collection into this
451
     * list, starting at the specified position.  Shifts the element
452
     * currently at that position (if any) and any subsequent elements to
453
     * the right (increases their indices).  The new elements will appear
454
     * in the list in the order that they are returned by the
455
     * specified Collection's iterator.
456
     *
457
     * @param index index at which to insert first element
458
     *		    from the specified collection.
459
     * @param c elements to be inserted into this list.
460
     * @return <tt>true</tt> if this list changed as a result of the call.
461
     * @throws    IndexOutOfBoundsException if index out of range <tt>(index
462
     *		  &lt; 0 || index &gt; size())</tt>.
463
     * @throws    NullPointerException if the specified Collection is null.
464
     */
465
    public boolean addAll(int index, Collection c) {
466
        return addArray(index, c.toArray());
467
    }
468
469
    /*
470
     * Inserts all elements from the given array into this list, starting
471
     * at the given index.
472
     *
473
     * @param index index at which to insert first element from the array.
474
     * @param elements array of elements to insert.
475
     */
476
    public boolean addArray(int index, Object[] elements) {
477
        return addArray(index, elements, 0, elements.length);
478
    }
479
480
    /**
481
     * Inserts elements from the given array into this list, starting
482
     * at the given index.
483
     *
484
     * @param index index at which to insert first element.
485
     * @param elements array of elements from which to insert elements.
486
     * @param off offset in the elements pointing to first element to copy.
487
     * @param len number of elements to copy from the elements array.
488
     */
489
    public boolean addArray(int index, Object[] elements, int off, int len) {
490
        int size = size();
491
        if (index > size || index < 0) {
492
            throw new IndexOutOfBoundsException(
493
                "Index: " + index + ", Size: " + size); // NOI18N
494
        }
495
        
496
        ensureCapacity(size + len);  // Increments modCount
497
        
498
        moveGap(index);
499
        System.arraycopy(elements, off, elementData, gapStart, len);
500
        gapStart += len;
501
        gapLength -= len;
502
503
        return (len != 0);
504
    }
505
    
506
    
507
    
508
    /**
509
     * Removes all of the elements from this list.  The list will
510
     * be empty after this call returns.
511
     */
512
    public void clear() {
513
        removeRange(0, size());
514
    }
515
    
516
    /**
517
     * Removes the element at the specified position in this list.
518
     * Shifts any subsequent elements to the left (subtracts one from their
519
     * indices).
520
     *
521
     * @param index the index of the element to removed.
522
     * @return the element that was removed from the list.
523
     * @throws    IndexOutOfBoundsException if index out of range <tt>(index
524
     * 		  &lt; 0 || index &gt;= size())</tt>.
525
     */
526
    public Object remove(int index) {
527
        int size = size();
528
        if (index >= size || index < 0) {
529
            throw new IndexOutOfBoundsException(
530
                "remove(): Index: " + index + ", Size: " + size); // NOI18N
531
        }
532
533
        modCount++;
534
        moveGap(index + 1); // if previous were adds() - this should be no-op
535
        Object oldValue = elementData[index];
536
        removeUpdate(index, elementData, index, index + 1);
537
        elementData[index] = null;
538
        gapStart--;
539
        gapLength++;
540
        
541
        return oldValue;
542
    }
543
544
    /**
545
     * Removes elements at the given index.
546
     *
547
     * @param index index of the first element to be removed.
548
     * @param count number of elements to remove.
549
     */
550
    public void remove(int index, int count) {
551
        int toIndex = index + count;
552
        if (index < 0 || toIndex < index || toIndex > size()) {
553
            throw new IndexOutOfBoundsException("index=" + index // NOI18N
554
            + ", count=" + count + ", size()=" + size()); // NOI18N
555
        }
556
        removeRange(index, toIndex);
557
    }
558
    
559
    /**
560
     * Removes from this List all of the elements whose index is between
561
     * fromIndex, inclusive and toIndex, exclusive.  Shifts any succeeding
562
     * elements to the left (reduces their index).
563
     * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
564
     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
565
     *
566
     * @param fromIndex index of first element to be removed.
567
     * @param toIndex index after last element to be removed.
568
     */
569
    protected void removeRange(int fromIndex, int toIndex) {
570
        modCount++;
571
        if (fromIndex == toIndex) {
572
            return;
573
        }
574
        
575
        int removeCount = toIndex - fromIndex;
576
        if (fromIndex >= gapStart) { // completely over gap
577
            // Move gap to the start of the removed area
578
            // (this should be the minimum necessary count of elements moved)
579
            moveGap(fromIndex);
580
            
581
            // Allow GC of removed items
582
            fromIndex += gapLength; // begining of abandoned area
583
            toIndex += gapLength;
584
            removeUpdate(fromIndex - gapLength, elementData, fromIndex, toIndex);
585
            while (fromIndex < toIndex) {
586
                elementData[fromIndex] = null;
587
                fromIndex++;
588
            }
589
            
590
        } else { // completely below gap or spans the gap
591
            if (toIndex <= gapStart) {
592
                // Move gap to the end of the removed area
593
                // (this should be the minimum necessary count of elements moved)
594
                moveGap(toIndex);
595
                gapStart = fromIndex;
596
                // Call removeUpdate() for items that will be physically removed soon
597
                removeUpdate(fromIndex, elementData, fromIndex, toIndex);
598
                
599
            } else { // spans gap: gapStart > fromIndex but gapStart - fromIndex < removeCount
600
                removeUpdate(fromIndex, elementData, fromIndex, gapStart);
601
                // Allow GC of removed items
602
                for (int clearIndex = fromIndex; clearIndex < gapStart; clearIndex++) {
603
                    elementData[clearIndex] = null;
604
                }
605
                
606
                fromIndex = gapStart + gapLength; // part above the gap
607
                gapStart = toIndex - removeCount; // original value of fromIndex
608
                toIndex += gapLength;
609
                removeUpdate(gapStart, elementData, fromIndex, toIndex);
610
            }
611
            
612
            // Allow GC of removed items
613
            while (fromIndex < toIndex) {
614
                elementData[fromIndex++] = null;
615
            }
616
            
617
        }
618
        
619
        gapLength += removeCount;
620
    }
621
    
622
    /**
623
     * Called prior physical removing of the data from the list.
624
     * <br>
625
     * The implementation can possibly update the elements in the removed area.
626
     * <br>
627
     * After this method finishes the whole removed area will be
628
     * <code>null</code>-ed.
629
     *
630
     * @param index index in the list of the first item being removed.
631
     * @param data array of objects from which the data are being removed.
632
     *  The next two parameters define the indexes at which the elements
633
     *  can be updated.
634
     *  <br>
635
     *  Absolutely no changes should be done outside of
636
     *  <code>&lt;startOff, endOff)</code> area.
637
     * @param startOff offset in the data array of the first element that
638
     *  will be removed.
639
     * @param endOff offset in the data array following the last item that will
640
     *  be removed.
641
     */
642
    protected void removeUpdate(int index, Object[] data, int startOff, int endOff) {
643
    }
644
645
    /*
646
    protected void movedAboveGapUpdate(Object[] array, int index, int count) {
647
    }
648
    
649
    protected void movedBelowGapUpdate(Object[] array, int index, int count) {
650
    }
651
    */
652
    
653
    private void moveGap(int index) {
654
        if (index == gapStart) {
655
            return; // do nothing
656
        }
657
658
        if (index < gapStart) { // move gap down
659
            int moveSize = gapStart - index;
660
            System.arraycopy(elementData, index, elementData,
661
            gapStart + gapLength - moveSize, moveSize);
662
            clearEmpty(index, Math.min(moveSize, gapLength));
663
            gapStart = index;
664
            // movedAboveGapUpdate(elementData, gapStart + gapLength, moveSize);
665
            
666
        } else { // above gap
667
            int gapEnd = gapStart + gapLength;
668
            int moveSize = index - gapStart;
669
            System.arraycopy(elementData, gapEnd, elementData, gapStart, moveSize);
670
            if (index < gapEnd) {
671
                clearEmpty(gapEnd, moveSize);
672
            } else {
673
                clearEmpty(index, gapLength);
674
            }
675
            // movedBelowGapUpdate(elementData, gapStart, moveSize);
676
            gapStart += moveSize;
677
        }
678
    }
679
    
680
    private void copyAllData(Object[] toArray) {
681
        if (gapLength != 0) {
682
            int gapEnd = gapStart + gapLength;
683
            System.arraycopy(elementData, 0, toArray, 0, gapStart);
684
            System.arraycopy(elementData, gapEnd, toArray, gapStart,
685
                elementData.length - gapEnd);
686
        } else { // no gap => single copy of everything
687
            System.arraycopy(elementData, 0, toArray, 0, elementData.length);
688
        }
689
    }
690
    
691
    private void clearEmpty(int index, int length) {
692
        while (--length >= 0) {
693
            elementData[index++] = null; // allow GC
694
        }
695
    }
696
    
697
    private void resetModCount() {
698
        modCount = 0;
699
    }
700
    
701
    /**
702
     * Save the state of the <tt>GapList</tt> instance to a stream (that
703
     * is, serialize it).
704
     *
705
     * @serialData The length of the array backing the <tt>GapList</tt>
706
     *             instance is emitted (int), followed by all of its elements
707
     *             (each an <tt>Object</tt>) in the proper order.
708
     */
709
    private void writeObject(java.io.ObjectOutputStream s)
710
    throws java.io.IOException{
711
        // Write out element count, and any hidden stuff
712
        s.defaultWriteObject();
713
        
714
        // Write out array length
715
        s.writeInt(elementData.length);
716
        
717
        // Write out all elements in the proper order.
718
        int i = 0;
719
        while (i < gapStart) {
720
            s.writeObject(elementData[i]);
721
            i++;
722
        }
723
        i += gapLength;
724
        int elementDataLength = elementData.length;
725
        while (i < elementDataLength) {
726
            s.writeObject(elementData[i]);
727
            i++;
728
        }
729
    }
730
    
731
    /**
732
     * Reconstitute the <tt>GapList</tt> instance from a stream (that is,
733
     * deserialize it).
734
     */
735
    private void readObject(java.io.ObjectInputStream s)
736
    throws java.io.IOException, ClassNotFoundException {
737
        // Read in size, and any hidden stuff
738
        s.defaultReadObject();
739
        
740
        // Read in array length and allocate array
741
        int arrayLength = s.readInt();
742
        elementData = new Object[arrayLength];
743
        
744
        // Read in all elements in the proper order.
745
        int i = 0;
746
        while (i < gapStart) {
747
            elementData[i] = s.readObject();
748
            i++;
749
        }
750
        i += gapLength;
751
        int elementDataLength = elementData.length;
752
        while (i < elementDataLength) {
753
            elementData[i] = s.readObject();
754
            i++;
755
        }
756
    }
757
    
758
    /**
759
     * Internal consistency check.
760
     */
761
    void consistencyCheck() {
762
        if (gapStart < 0 || gapLength < 0
763
            || gapStart + gapLength > elementData.length
764
        ) {
765
            consistencyError("Inconsistent gap"); // NOI18N
766
        }
767
        
768
        // Check whether the whole gap contains only nulls
769
        for (int i = gapStart + gapLength - 1; i >= gapStart; i--) {
770
            if (elementData[i] != null) {
771
                consistencyError("Non-null value at raw-index i"); // NOI18N
772
            }
773
        }
774
    }
775
    
776
    private void consistencyError(String s) {
777
        throw new IllegalStateException(s + ": " + toStringInternals()); // NOI18N
778
    }
779
    
780
    String toStringInternals() {
781
        return "elementData.length=" + elementData.length // NOI18N
782
            + ", gapStart=" + gapStart + ", gapLength=" + gapLength; // NOI18N
783
    }
784
    
785
}
(-)editor/util/src/org/netbeans/lib/editor/util/PriorityMutex.java (+147 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.lib.editor.util;
15
16
/**
17
 * Mutex that allows only one thread to proceed
18
 * other threads must wait until that one finishes.
19
 * <br>
20
 * The thread that "holds" the mutex (has the mutex access granted)
21
 * may reenter the mutex arbitrary number of times
22
 * (just increasing a "depth" of the locking).
23
 * <br>
24
 * If the priority thread enters waiting on the mutex
25
 * then it will get serviced first once the current thread
26
 * leaves the mutex.
27
 *
28
 * @author Miloslav Metelka
29
 * @version 1.00
30
 */
31
32
public class PriorityMutex {
33
34
    private Thread lockThread;
35
36
    private int lockDepth;
37
    
38
    private Thread waitingPriorityThread;
39
    
40
    /**
41
     * Acquire the ownership of the mutex.
42
     *
43
     * <p>
44
     * The following pattern should always be used:
45
     * <pre>
46
     *   mutex.lock();
47
     *   try {
48
     *       ...
49
     *   } finally {
50
     *       mutex.unlock();
51
     *   }
52
     * </pre>
53
     */
54
    public synchronized void lock() {
55
        Thread thread = Thread.currentThread();
56
        if (thread != lockThread) { // not nested locking
57
            // Will wait if either there is another thread already holding the lock
58
            // or if there is a priority thread waiting but it's not this thread
59
            while (lockThread != null
60
                || (waitingPriorityThread != null && waitingPriorityThread != thread)
61
            ) {
62
                try {
63
                    if (waitingPriorityThread == null && isPriorityThread()) {
64
                        waitingPriorityThread = thread;
65
                    }
66
67
                    wait();
68
69
                } catch (InterruptedException e) {
70
                    waitingPriorityThread = null;
71
                }
72
            }
73
74
            lockThread = thread;
75
76
            if (thread == waitingPriorityThread) {
77
                waitingPriorityThread = null; // it's now allowed to enter
78
            }
79
        }
80
81
        lockDepth++;
82
    }
83
    
84
    /**
85
     * Release the ownership of the mutex.
86
     *
87
     * @see lock()
88
     */
89
    public synchronized void unlock() {
90
        if (Thread.currentThread() != lockThread) {
91
            throw new IllegalStateException("Not locker"); // NOI18N
92
        }
93
94
        if (--lockDepth == 0) {
95
            lockThread = null;
96
97
            notifyAll(); // must all to surely notify waitingPriorityThread too
98
        }
99
    }
100
    
101
    /**
102
     * Can be called by the thread
103
     * that acquired the mutex to check whether there
104
     * is a priority thread (such as AWT event-notification thread)
105
     * waiting.
106
     * <br>
107
     * If there is a priority thread waiting the non-priority thread
108
     * should attempt to stop its work as soon and release the ownership
109
     * of the mutex.
110
     * <br>
111
     * The method must *not* be called without first taking the ownership
112
     * of the mutex (it is intentionally not synchronized).
113
     */
114
    public boolean isPriorityThreadWaiting() {
115
        return (waitingPriorityThread != null);
116
    }
117
    
118
    /**
119
     * Return a thread that acquired this mutex.
120
     * <br>
121
     * This method is intended for diagnostic purposes only.
122
     *
123
     * @return thread that currently acquired lock the mutex
124
        or <code>null</code>
125
     *  if there is currently no thread holding that acquired this mutex.
126
     */
127
    public final synchronized Thread getLockThread() {
128
        return lockThread;
129
    }
130
131
    /**
132
     * Return true if the current thread that is entering this method
133
     * is a priority thread
134
     * and should be allowed to enter as soon as possible.
135
     *
136
     * <p>
137
     * The default implementation assumes that
138
     * {@link javax.swing.SwingUtilities#isEventDispatchThread()}
139
     * is a priority thread.
140
     *
141
     * @return true if the entering thread is a priority thread.
142
     */
143
    protected boolean isPriorityThread() {
144
        return javax.swing.SwingUtilities.isEventDispatchThread();
145
    }
146
147
}
(-)editor/util/src/org/netbeans/lib/editor/util/swing/ElementUtilities.java (+39 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.lib.editor.util.swing;
15
16
import javax.swing.text.Element;
17
18
/**
19
 * Various utility methods related to elements.
20
 *
21
 * @author Miloslav Metelka
22
 * @version 1.00
23
 */
24
25
public final class ElementUtilities {
26
    
27
    private ElementUtilities() {
28
        // No instances
29
    }
30
    
31
    public static void updateOffsetRange(Element[] elements, int[] offsetRange) {
32
        int elementsLength = elements.length;
33
        if (elementsLength > 0) {
34
            offsetRange[0] = Math.min(offsetRange[0], elements[0].getStartOffset());
35
            offsetRange[1] = Math.max(offsetRange[1], elements[elementsLength - 1].getEndOffset());
36
        }
37
    }
38
39
}
(-)editor/util/src/org/netbeans/lib/editor/util/swing/GapBranchElement.java (+245 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 * 
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 * 
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.lib.editor.util.swing;
15
16
import javax.swing.text.Element;
17
import javax.swing.event.DocumentEvent;
18
import javax.swing.undo.AbstractUndoableEdit;
19
import javax.swing.undo.CannotUndoException;
20
import javax.swing.undo.CannotRedoException;
21
import org.netbeans.lib.editor.util.GapList;
22
23
/**
24
 * Branch element that uses gap list to maintain its child elements.
25
 *
26
 * @author Miloslav Metelka
27
 * @version 1.00
28
 */
29
30
public abstract class GapBranchElement implements Element {
31
    
32
    protected static final Element[] EMPTY_ELEMENT_ARRAY = new Element[0];
33
34
    private GapList children;
35
    
36
    public GapBranchElement() {
37
        children = new GapList();
38
    }
39
    
40
    public int getElementCount() {
41
        return children.size();
42
    }
43
    
44
    public Element getElement(int index) {
45
        return (Element)children.get(index);
46
    }
47
    
48
    public void copyElements(int srcBegin, int srcEnd, Element dst[], int dstBegin) {
49
        children.copyItems(srcBegin, srcEnd, dst, dstBegin);
50
    }
51
52
    /**
53
     * Gets the child element index closest to the given offset.
54
     * The offset is specified relative to the beginning of the
55
     * document.  Returns <code>-1</code> if the
56
     * <code>Element</code> is a leaf, otherwise returns
57
     * the index of the <code>Element</code> that best represents
58
     * the given location.  Returns <code>0</code> if the location
59
     * is less than the start offset. Returns
60
     * <code>getElementCount() - 1</code> if the location is
61
     * greater than or equal to the end offset.
62
     *
63
     * <p>
64
     * This implementation is in sync with the original
65
     * <code>Element.getElementIndex()</code> specification
66
     * but it differs
67
     * from <code>AbstractDocument.BranchElement.getElementIndex()</code>
68
     * which returns 0 in case it does not have any children.
69
     * <br>
70
     * This implementation returns -1 in that case because in fact
71
     * the element act as a leaf element in such case.
72
     * <br>
73
     * Nonetheless there should be no difference in functionality
74
     * if this implementation is used for line elements
75
     * because there is always at least one line element even
76
     * for empty doc because of the extra '\n' after the end
77
     * of the AbstractDocument-based implementations.
78
     *
79
     * @param offset the specified offset >= 0
80
     * @return the element index >= 0
81
     */
82
    public int getElementIndex(int offset) {
83
        int low = 0;
84
        int high = getElementCount() - 1;
85
        
86
        if (high == -1) { // no children => return -1
87
            return -1;
88
        }
89
        
90
        while (low <= high) {
91
            int mid = (low + high) / 2;
92
            int elemStartOffset = getElement(mid).getStartOffset();
93
            
94
            if (elemStartOffset < offset) {
95
                low = mid + 1;
96
            } else if (elemStartOffset > offset) {
97
                high = mid - 1;
98
            } else { // element starts at offset
99
                return mid;
100
            }
101
        }
102
103
        if (high < 0) { // if offset < getElement(0).getStartOffset()
104
            high = 0;
105
        }
106
        return high;
107
    }
108
109
    public boolean isLeaf() {
110
        return false;
111
    }
112
    
113
    protected void replace(int index, int removeCount, Element[] addedElems) {
114
        if (removeCount > 0) {
115
            children.remove(index, removeCount);
116
        }
117
        if (addedElems != null) {
118
            children.addArray(index, addedElems);
119
        }
120
    }
121
    
122
    /** Get info about <CODE>DocMarks</CODE>. */
123
    public String toString() {
124
        return children.toString();
125
    }
126
127
    public class Edit extends AbstractUndoableEdit
128
    implements DocumentEvent.ElementChange {
129
        
130
        private int index;
131
        
132
        private Element[] childrenAdded;
133
        
134
        private Element[] childrenRemoved;
135
       
136
        public Edit(int index, Element[] childrenRemoved, Element[] childrenAdded) {
137
            this.index = index;
138
            this.childrenRemoved = childrenRemoved;
139
            this.childrenAdded = childrenAdded;
140
        }
141
        
142
	public Element getElement() {
143
            return GapBranchElement.this;
144
        }
145
146
	public int getIndex() {
147
            return index;
148
        }
149
150
        public Element[] getChildrenRemoved() {
151
            return childrenRemoved;
152
        }
153
154
        public Element[] getChildrenAdded() {
155
            return childrenAdded;
156
        }
157
158
        public void undo() throws CannotUndoException {
159
            super.undo();
160
161
            replace(index, childrenAdded.length, childrenRemoved);
162
163
            // Switch childrenAdded with childrenRemoved
164
            Element[] tmp = childrenRemoved;
165
            childrenRemoved = childrenAdded;
166
            childrenAdded = tmp;
167
        }
168
        
169
        public void redo() throws CannotRedoException {
170
            super.redo();
171
172
            // Switch childrenAdded with childrenRemoved
173
            Element[] tmp = childrenRemoved;
174
            childrenRemoved = childrenAdded;
175
            childrenAdded = tmp;
176
177
            replace(index, childrenRemoved.length, childrenAdded);
178
        }
179
        
180
    }
181
182
    /**
183
     * Extension of {@link GapBranchElement}
184
     * that overrides {@link #getElementIndex(int)}
185
     * which remembers the last returned element index.
186
     */
187
    public abstract class LastIndex {
188
        
189
        private int lastReturnedElementIndex;
190
    
191
        /**
192
         * Implementation that remembers the last returned element index
193
         * and checks the element at the last index when next called.
194
         * <br>
195
         * This may improve performance if there are typically many repetitive calls
196
         * with offset values hitting the last returned element index.
197
         */
198
        public int getElementIndex(int offset) {
199
            int low = 0;
200
            int high = getElementCount() - 1;
201
202
            if (high == -1) { // no children => return -1
203
                return -1;
204
            }
205
206
            int lastIndex = lastReturnedElementIndex; // make copy to be thread-safe
207
            if (lastIndex >= low && lastIndex <= high) {
208
                Element lastElem = getElement(lastIndex);
209
                int lastElemStartOffset = lastElem.getStartOffset();
210
                if (offset >= lastElemStartOffset) {
211
                    int lastElemEndOffset = lastElem.getEndOffset();
212
                    if (offset < lastElemEndOffset) { // hit
213
                        return lastIndex;
214
                    } else { // above
215
                        low = lastIndex + 1;
216
                    }
217
                } else { // below lastIndex
218
                    high = lastIndex - 1;
219
                }
220
            }
221
222
            while (low <= high) {
223
                int mid = (low + high) / 2;
224
                int elemStartOffset = ((Element)children.get(mid)).getStartOffset();
225
226
                if (elemStartOffset < offset) {
227
                    low = mid + 1;
228
                } else if (elemStartOffset > offset) {
229
                    high = mid - 1;
230
                } else { // element starts at offset
231
                    lastReturnedElementIndex = mid;
232
                    return mid;
233
                }
234
            }
235
236
            if (high < 0) {
237
                high = 0;
238
            }
239
            lastReturnedElementIndex = high;
240
            return high;
241
        }
242
        
243
    }
244
245
}
(-)editor/util/src/org/netbeans/modules/editor/util/Bundle.properties (-16 lines)
Removed Link Here
1
#                 Sun Public License Notice
2
# 
3
# The contents of this file are subject to the Sun Public License
4
# Version 1.0 (the "License"). You may not use this file except in
5
# compliance with the License. A copy of the License is available at
6
# http://www.sun.com/
7
# 
8
# The Original Code is NetBeans. The Initial Developer of the Original
9
# Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
10
# Microsystems, Inc. All Rights Reserved.
11
12
OpenIDE-Module-Name=Editor Utilities
13
OpenIDE-Module-Display-Category=Editing
14
OpenIDE-Module-Short-Description=Contains various support classes for editor related modules
15
OpenIDE-Module-Long-Description=Editor Utilities module contains various utility classes and methods for functionality related to editing
16
(-)editor/util/src/org/netbeans/modules/editor/util/GapList.java (-785 lines)
Removed Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.modules.editor.util;
15
16
import java.util.AbstractList;
17
import java.util.Collection;
18
import java.util.RandomAccess;
19
20
/**
21
 * List implementation that stores items in an array
22
 * with a gap.
23
 *
24
 * @author Miloslav Metelka
25
 * @version 1.00
26
 */
27
28
public class GapList extends AbstractList
29
implements RandomAccess, Cloneable, java.io.Serializable {
30
    
31
    private static final Object[] EMPTY_ELEMENT_ARRAY = new Object[0];
32
    
33
    /**
34
     * The array buffer into which the elements are stored.
35
     * <br>
36
     * The elements are stored in the whole array except
37
     * the indexes starting at <code>gapStart</code>
38
     * till <code>gapStart + gapLength - 1</code>.
39
     */
40
    private transient Object elementData[];
41
    
42
    /**
43
     * The start of the gap in the elementData array.
44
     */
45
    private int gapStart;
46
    
47
    /**
48
     * Length of the gap in the elementData array starting at gapStart.
49
     */
50
    private int gapLength;
51
    
52
    /**
53
     * Constructs an empty list with the specified initial capacity.
54
     *
55
     * @param   initialCapacity   the initial capacity of the list.
56
     * @exception IllegalArgumentException if the specified initial capacity
57
     *            is negative
58
     */
59
    public GapList(int initialCapacity) {
60
        if (initialCapacity < 0) {
61
            throw new IllegalArgumentException("Illegal Capacity: " // NOI18N
62
                + initialCapacity);
63
        }
64
        this.elementData = new Object[initialCapacity];
65
        this.gapLength = initialCapacity;
66
    }
67
    
68
    /**
69
     * Constructs an empty list.
70
     */
71
    public GapList() {
72
        elementData = EMPTY_ELEMENT_ARRAY;
73
    }
74
    
75
    /**
76
     * Constructs a list containing the elements of the specified
77
     * collection, in the order they are returned by the collection's
78
     * iterator.  The <tt>GapList</tt> instance has an initial capacity of
79
     * 110% the size of the specified collection.
80
     *
81
     * @param c the collection whose elements are to be placed into this list.
82
     * @throws NullPointerException if the specified collection is null.
83
     */
84
    public GapList(Collection c) {
85
        int size = c.size();
86
        // Allow 10% room for growth
87
        elementData = new Object[
88
        (int)Math.min((size*110L)/100,Integer.MAX_VALUE)];
89
        c.toArray(elementData);
90
        this.gapStart = size;
91
        this.gapLength = elementData.length - size;
92
    }
93
    
94
    /**
95
     * Trims the capacity of this <tt>GapList</tt> instance to be the
96
     * list's current size.  An application can use this operation to minimize
97
     * the storage of an <tt>GapList</tt> instance.
98
     */
99
    public void trimToSize() {
100
        modCount++;
101
        if (gapLength > 0) {
102
            int newLength = elementData.length - gapLength;
103
            Object[] newElementData = new Object[newLength];
104
            copyAllData(newElementData);
105
            elementData = newElementData;
106
            // Leave gapStart as is
107
            gapLength = 0;
108
        }
109
    }
110
    
111
    /**
112
     * Increases the capacity of this <tt>GapList</tt> instance, if
113
     * necessary, to ensure  that it can hold at least the number of elements
114
     * specified by the minimum capacity argument.
115
     *
116
     * @param   minCapacity   the desired minimum capacity.
117
     */
118
    public void ensureCapacity(int minCapacity) {
119
        modCount++; // expected to always increment modCount - see add() operations
120
        int oldCapacity = elementData.length;
121
        if (minCapacity > oldCapacity) {
122
            int newCapacity = (oldCapacity * 3)/2 + 1;
123
            if (newCapacity < minCapacity) {
124
                newCapacity = minCapacity;
125
            }
126
            int gapEnd = gapStart + gapLength;
127
            int afterGapLength = (oldCapacity - gapEnd);
128
            // Must ensure the gap will not be logically moved
129
            // (would have to call movedAbove/BeforeGapUpdate() methods)
130
            int newGapEnd = newCapacity - afterGapLength;
131
            Object[] newElementData = new Object[newCapacity];
132
            System.arraycopy(elementData, 0, newElementData, 0, gapStart);
133
            System.arraycopy(elementData, gapEnd, newElementData, newGapEnd, afterGapLength);
134
            elementData = newElementData;
135
            gapLength = newGapEnd - gapStart;
136
        }
137
    }
138
    
139
    /**
140
     * Returns the number of elements in this list.
141
     *
142
     * @return  the number of elements in this list.
143
     */
144
    public int size() {
145
        return elementData.length - gapLength;
146
    }
147
    
148
    /**
149
     * Tests if this list has no elements.
150
     *
151
     * @return  <tt>true</tt> if this list has no elements;
152
     *          <tt>false</tt> otherwise.
153
     */
154
    public boolean isEmpty() {
155
        return (elementData.length == gapLength);
156
    }
157
    
158
    /**
159
     * Returns <tt>true</tt> if this list contains the specified element.
160
     *
161
     * @param elem element whose presence in this List is to be tested.
162
     * @return  <code>true</code> if the specified element is present;
163
     *		<code>false</code> otherwise.
164
     */
165
    public boolean contains(Object elem) {
166
        return indexOf(elem) >= 0;
167
    }
168
    
169
    /**
170
     * Searches for the first occurence of the given argument, testing
171
     * for equality using the <tt>equals</tt> method.
172
     *
173
     * @param   elem   an object.
174
     * @return  the index of the first occurrence of the argument in this
175
     *          list; returns <tt>-1</tt> if the object is not found.
176
     * @see     Object#equals(Object)
177
     */
178
    public int indexOf(Object elem) {
179
        if (elem == null) {
180
            int i = 0;
181
            while (i < gapStart) {
182
                if (elementData[i] == null) {
183
                    return i;
184
                }
185
                i++;
186
            }
187
            i += gapLength;
188
            int elementDataLength = elementData.length;
189
            while (i < elementDataLength) {
190
                if (elementData[i] == null) {
191
                    return i;
192
                }
193
                i++;
194
            }
195
            
196
        } else { // elem not null
197
            int i = 0;
198
            while (i < gapStart) {
199
                if (elem.equals(elementData[i])) {
200
                    return i;
201
                }
202
                i++;
203
            }
204
            i += gapLength;
205
            int elementDataLength = elementData.length;
206
            while (i < elementDataLength) {
207
                if (elem.equals(elementData[i])) {
208
                    return i;
209
                }
210
                i++;
211
            }
212
        }
213
        
214
        return -1;
215
    }
216
    
217
    /**
218
     * Returns the index of the last occurrence of the specified object in
219
     * this list.
220
     *
221
     * @param   elem   the desired element.
222
     * @return  the index of the last occurrence of the specified object in
223
     *          this list; returns -1 if the object is not found.
224
     */
225
    public int lastIndexOf(Object elem) {
226
        if (elem == null) {
227
            int i = elementData.length - 1;
228
            int gapEnd = gapStart + gapLength;
229
            while (i >= gapEnd) {
230
                if (elementData[i] == null) {
231
                    return i;
232
                }
233
                i--;
234
            }
235
            i -= gapLength;
236
            while (i >= 0) {
237
                if (elementData[i] == null) {
238
                    return i;
239
                }
240
                i--;
241
            }
242
            
243
        } else { // elem not null
244
            int i = elementData.length - 1;
245
            int gapEnd = gapStart + gapLength;
246
            while (i >= gapEnd) {
247
                if (elem.equals(elementData[i])) {
248
                    return i;
249
                }
250
                i--;
251
            }
252
            i -= gapLength;
253
            while (i >= 0) {
254
                if (elem.equals(elementData[i])) {
255
                    return i;
256
                }
257
                i--;
258
            }
259
        }
260
        
261
        return -1;
262
    }
263
    
264
    /**
265
     * Returns a shallow copy of this <tt>GapList</tt> instance.  (The
266
     * elements themselves are not copied.)
267
     *
268
     * @return  a clone of this <tt>GapList</tt> instance.
269
     */
270
    public Object clone() {
271
        try {
272
            GapList clonedList = (GapList)super.clone();
273
            int size = size();
274
            Object[] clonedElementData = new Object[size];
275
            copyAllData(clonedElementData);
276
            clonedList.elementData = clonedElementData;
277
            // Will retain gapStart - would have to call moved*() otherwise
278
            clonedList.gapStart = size;
279
            clonedList.resetModCount();
280
            return clonedList;
281
282
        } catch (CloneNotSupportedException e) {
283
            // this shouldn't happen, since we are Cloneable
284
            throw new InternalError();
285
        }
286
    }
287
    
288
    public void copyItems(int srcStartIndex, int srcEndIndex,
289
    Object[] dest, int destIndex) {
290
        
291
        if (srcStartIndex < 0 || srcEndIndex < srcStartIndex || srcEndIndex > size()) {
292
            throw new IndexOutOfBoundsException("srcStartIndex=" + srcStartIndex // NOI18N
293
            + ", srcEndIndex=" + srcEndIndex + ", size()=" + size()); // NOI18N
294
        }
295
        
296
        if (srcEndIndex < gapStart) { // fully below gap
297
            System.arraycopy(elementData, srcStartIndex,
298
            dest, destIndex, srcEndIndex - srcStartIndex);
299
            
300
        } else { // above gap or spans the gap
301
            if (srcStartIndex >= gapStart) { // fully above gap
302
                System.arraycopy(elementData, srcStartIndex + gapLength, dest, destIndex,
303
                srcEndIndex - srcStartIndex);
304
                
305
            } else { // spans gap
306
                int beforeGap = gapStart - srcStartIndex;
307
                System.arraycopy(elementData, srcStartIndex, dest, destIndex, beforeGap);
308
                System.arraycopy(elementData, gapStart + gapLength, dest, destIndex + beforeGap,
309
                srcEndIndex - srcStartIndex - beforeGap);
310
            }
311
        }
312
    }
313
    
314
    /**
315
     * Returns an array containing all of the elements in this list
316
     * in the correct order.
317
     *
318
     * @return an array containing all of the elements in this list
319
     * 	       in the correct order.
320
     */
321
    public Object[] toArray() {
322
        int size = size();
323
        Object[] result = new Object[size];
324
        copyAllData(result);
325
        return result;
326
    }
327
    
328
    /**
329
     * Returns an array containing all of the elements in this list in the
330
     * correct order; the runtime type of the returned array is that of the
331
     * specified array.  If the list fits in the specified array, it is
332
     * returned therein.  Otherwise, a new array is allocated with the runtime
333
     * type of the specified array and the size of this list.<p>
334
     *
335
     * If the list fits in the specified array with room to spare (i.e., the
336
     * array has more elements than the list), the element in the array
337
     * immediately following the end of the collection is set to
338
     * <tt>null</tt>.  This is useful in determining the length of the list
339
     * <i>only</i> if the caller knows that the list does not contain any
340
     * <tt>null</tt> elements.
341
     *
342
     * @param a the array into which the elements of the list are to
343
     *		be stored, if it is big enough; otherwise, a new array of the
344
     * 		same runtime type is allocated for this purpose.
345
     * @return an array containing the elements of the list.
346
     * @throws ArrayStoreException if the runtime type of a is not a supertype
347
     *         of the runtime type of every element in this list.
348
     */
349
    public Object[] toArray(Object a[]) {
350
        int size = size();
351
        if (a.length < size) {
352
            a = (Object[])java.lang.reflect.Array.newInstance(
353
                a.getClass().getComponentType(), size);
354
        }
355
        copyAllData(a);
356
        if (a.length > size)
357
            a[size] = null;
358
        
359
        return a;
360
    }
361
    
362
    // Positional Access Operations
363
    
364
    /**
365
     * Returns the element at the specified position in this list.
366
     *
367
     * @param  index index of element to return.
368
     * @return the element at the specified position in this list.
369
     * @throws    IndexOutOfBoundsException if index is out of range <tt>(index
370
     * 		  &lt; 0 || index &gt;= size())</tt>.
371
     */
372
    public Object get(int index) {
373
        // rangeCheck(index) not necessary - would fail with AIOOBE anyway
374
        return elementData[(index < gapStart) ? index : (index + gapLength)];
375
    }
376
    
377
    /**
378
     * Replaces the element at the specified position in this list with
379
     * the specified element.
380
     *
381
     * @param index index of element to replace.
382
     * @param element element to be stored at the specified position.
383
     * @return the element previously at the specified position.
384
     * @throws    IndexOutOfBoundsException if index out of range
385
     *		  <tt>(index &lt; 0 || index &gt;= size())</tt>.
386
     */
387
    public Object set(int index, Object element) {
388
        // rangeCheck(index) not necessary - would fail with AIOOBE anyway
389
        if (index >= gapStart) {
390
            index += gapLength;
391
        }
392
        Object oldValue = elementData[index];
393
        elementData[index] = element;
394
        return oldValue;
395
    }
396
    
397
    /**
398
     * Appends the specified element to the end of this list.
399
     *
400
     * @param o element to be appended to this list.
401
     * @return <tt>true</tt> (as per the general contract of Collection.add).
402
     */
403
    public boolean add(Object o) {
404
        add(size(), o);
405
        return true;
406
    }
407
    
408
    /**
409
     * Inserts the specified element at the specified position in this
410
     * list. Shifts the element currently at that position (if any) and
411
     * any subsequent elements to the right (adds one to their indices).
412
     *
413
     * @param index index at which the specified element is to be inserted.
414
     * @param element element to be inserted.
415
     * @throws    IndexOutOfBoundsException if index is out of range
416
     *		  <tt>(index &lt; 0 || index &gt; size())</tt>.
417
     */
418
    public void add(int index, Object element) {
419
        int size = size();
420
        if (index > size || index < 0) {
421
            throw new IndexOutOfBoundsException(
422
                "Index: " + index + ", Size: " + size); // NOI18N
423
        }
424
425
        ensureCapacity(size + 1);  // Increments modCount!!
426
        moveGap(index);
427
428
        elementData[gapStart++] = element;
429
        gapLength--;
430
    }
431
    
432
    /**
433
     * Appends all of the elements in the specified Collection to the end of
434
     * this list, in the order that they are returned by the
435
     * specified Collection's Iterator.  The behavior of this operation is
436
     * undefined if the specified Collection is modified while the operation
437
     * is in progress.  (This implies that the behavior of this call is
438
     * undefined if the specified Collection is this list, and this
439
     * list is nonempty.)
440
     *
441
     * @param c the elements to be inserted into this list.
442
     * @return <tt>true</tt> if this list changed as a result of the call.
443
     * @throws    NullPointerException if the specified collection is null.
444
     */
445
    public boolean addAll(Collection c) {
446
        return addAll(size(), c);
447
    }
448
    
449
    /**
450
     * Inserts all of the elements in the specified Collection into this
451
     * list, starting at the specified position.  Shifts the element
452
     * currently at that position (if any) and any subsequent elements to
453
     * the right (increases their indices).  The new elements will appear
454
     * in the list in the order that they are returned by the
455
     * specified Collection's iterator.
456
     *
457
     * @param index index at which to insert first element
458
     *		    from the specified collection.
459
     * @param c elements to be inserted into this list.
460
     * @return <tt>true</tt> if this list changed as a result of the call.
461
     * @throws    IndexOutOfBoundsException if index out of range <tt>(index
462
     *		  &lt; 0 || index &gt; size())</tt>.
463
     * @throws    NullPointerException if the specified Collection is null.
464
     */
465
    public boolean addAll(int index, Collection c) {
466
        return addArray(index, c.toArray());
467
    }
468
469
    /*
470
     * Inserts all elements from the given array into this list, starting
471
     * at the given index.
472
     *
473
     * @param index index at which to insert first element from the array.
474
     * @param elements array of elements to insert.
475
     */
476
    public boolean addArray(int index, Object[] elements) {
477
        return addArray(index, elements, 0, elements.length);
478
    }
479
480
    /**
481
     * Inserts elements from the given array into this list, starting
482
     * at the given index.
483
     *
484
     * @param index index at which to insert first element.
485
     * @param elements array of elements from which to insert elements.
486
     * @param off offset in the elements pointing to first element to copy.
487
     * @param len number of elements to copy from the elements array.
488
     */
489
    public boolean addArray(int index, Object[] elements, int off, int len) {
490
        int size = size();
491
        if (index > size || index < 0) {
492
            throw new IndexOutOfBoundsException(
493
                "Index: " + index + ", Size: " + size); // NOI18N
494
        }
495
        
496
        ensureCapacity(size + len);  // Increments modCount
497
        
498
        moveGap(index);
499
        System.arraycopy(elements, off, elementData, gapStart, len);
500
        gapStart += len;
501
        gapLength -= len;
502
503
        return (len != 0);
504
    }
505
    
506
    
507
    
508
    /**
509
     * Removes all of the elements from this list.  The list will
510
     * be empty after this call returns.
511
     */
512
    public void clear() {
513
        removeRange(0, size());
514
    }
515
    
516
    /**
517
     * Removes the element at the specified position in this list.
518
     * Shifts any subsequent elements to the left (subtracts one from their
519
     * indices).
520
     *
521
     * @param index the index of the element to removed.
522
     * @return the element that was removed from the list.
523
     * @throws    IndexOutOfBoundsException if index out of range <tt>(index
524
     * 		  &lt; 0 || index &gt;= size())</tt>.
525
     */
526
    public Object remove(int index) {
527
        int size = size();
528
        if (index >= size || index < 0) {
529
            throw new IndexOutOfBoundsException(
530
                "remove(): Index: " + index + ", Size: " + size); // NOI18N
531
        }
532
533
        modCount++;
534
        moveGap(index + 1); // if previous were adds() - this should be no-op
535
        Object oldValue = elementData[index];
536
        removeUpdate(index, elementData, index, index + 1);
537
        elementData[index] = null;
538
        gapStart--;
539
        gapLength++;
540
        
541
        return oldValue;
542
    }
543
544
    /**
545
     * Removes elements at the given index.
546
     *
547
     * @param index index of the first element to be removed.
548
     * @param count number of elements to remove.
549
     */
550
    public void remove(int index, int count) {
551
        int toIndex = index + count;
552
        if (index < 0 || toIndex < index || toIndex > size()) {
553
            throw new IndexOutOfBoundsException("index=" + index // NOI18N
554
            + ", count=" + count + ", size()=" + size()); // NOI18N
555
        }
556
        removeRange(index, toIndex);
557
    }
558
    
559
    /**
560
     * Removes from this List all of the elements whose index is between
561
     * fromIndex, inclusive and toIndex, exclusive.  Shifts any succeeding
562
     * elements to the left (reduces their index).
563
     * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
564
     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
565
     *
566
     * @param fromIndex index of first element to be removed.
567
     * @param toIndex index after last element to be removed.
568
     */
569
    protected void removeRange(int fromIndex, int toIndex) {
570
        modCount++;
571
        if (fromIndex == toIndex) {
572
            return;
573
        }
574
        
575
        int removeCount = toIndex - fromIndex;
576
        if (fromIndex >= gapStart) { // completely over gap
577
            // Move gap to the start of the removed area
578
            // (this should be the minimum necessary count of elements moved)
579
            moveGap(fromIndex);
580
            
581
            // Allow GC of removed items
582
            fromIndex += gapLength; // begining of abandoned area
583
            toIndex += gapLength;
584
            removeUpdate(fromIndex - gapLength, elementData, fromIndex, toIndex);
585
            while (fromIndex < toIndex) {
586
                elementData[fromIndex] = null;
587
                fromIndex++;
588
            }
589
            
590
        } else { // completely below gap or spans the gap
591
            if (toIndex <= gapStart) {
592
                // Move gap to the end of the removed area
593
                // (this should be the minimum necessary count of elements moved)
594
                moveGap(toIndex);
595
                gapStart = fromIndex;
596
                // Call removeUpdate() for items that will be physically removed soon
597
                removeUpdate(fromIndex, elementData, fromIndex, toIndex);
598
                
599
            } else { // spans gap: gapStart > fromIndex but gapStart - fromIndex < removeCount
600
                removeUpdate(fromIndex, elementData, fromIndex, gapStart);
601
                // Allow GC of removed items
602
                for (int clearIndex = fromIndex; clearIndex < gapStart; clearIndex++) {
603
                    elementData[clearIndex] = null;
604
                }
605
                
606
                fromIndex = gapStart + gapLength; // part above the gap
607
                gapStart = toIndex - removeCount; // original value of fromIndex
608
                toIndex += gapLength;
609
                removeUpdate(gapStart, elementData, fromIndex, toIndex);
610
            }
611
            
612
            // Allow GC of removed items
613
            while (fromIndex < toIndex) {
614
                elementData[fromIndex++] = null;
615
            }
616
            
617
        }
618
        
619
        gapLength += removeCount;
620
    }
621
    
622
    /**
623
     * Called prior physical removing of the data from the list.
624
     * <br>
625
     * The implementation can possibly update the elements in the removed area.
626
     * <br>
627
     * After this method finishes the whole removed area will be
628
     * <code>null</code>-ed.
629
     *
630
     * @param index index in the list of the first item being removed.
631
     * @param data array of objects from which the data are being removed.
632
     *  The next two parameters define the indexes at which the elements
633
     *  can be updated.
634
     *  <br>
635
     *  Absolutely no changes should be done outside of
636
     *  <code>&lt;startOff, endOff)</code> area.
637
     * @param startOff offset in the data array of the first element that
638
     *  will be removed.
639
     * @param endOff offset in the data array following the last item that will
640
     *  be removed.
641
     */
642
    protected void removeUpdate(int index, Object[] data, int startOff, int endOff) {
643
    }
644
645
    /*
646
    protected void movedAboveGapUpdate(Object[] array, int index, int count) {
647
    }
648
    
649
    protected void movedBelowGapUpdate(Object[] array, int index, int count) {
650
    }
651
    */
652
    
653
    private void moveGap(int index) {
654
        if (index == gapStart) {
655
            return; // do nothing
656
        }
657
658
        if (index < gapStart) { // move gap down
659
            int moveSize = gapStart - index;
660
            System.arraycopy(elementData, index, elementData,
661
            gapStart + gapLength - moveSize, moveSize);
662
            clearEmpty(index, Math.min(moveSize, gapLength));
663
            gapStart = index;
664
            // movedAboveGapUpdate(elementData, gapStart + gapLength, moveSize);
665
            
666
        } else { // above gap
667
            int gapEnd = gapStart + gapLength;
668
            int moveSize = index - gapStart;
669
            System.arraycopy(elementData, gapEnd, elementData, gapStart, moveSize);
670
            if (index < gapEnd) {
671
                clearEmpty(gapEnd, moveSize);
672
            } else {
673
                clearEmpty(index, gapLength);
674
            }
675
            // movedBelowGapUpdate(elementData, gapStart, moveSize);
676
            gapStart += moveSize;
677
        }
678
    }
679
    
680
    private void copyAllData(Object[] toArray) {
681
        if (gapLength != 0) {
682
            int gapEnd = gapStart + gapLength;
683
            System.arraycopy(elementData, 0, toArray, 0, gapStart);
684
            System.arraycopy(elementData, gapEnd, toArray, gapStart,
685
                elementData.length - gapEnd);
686
        } else { // no gap => single copy of everything
687
            System.arraycopy(elementData, 0, toArray, 0, elementData.length);
688
        }
689
    }
690
    
691
    private void clearEmpty(int index, int length) {
692
        while (--length >= 0) {
693
            elementData[index++] = null; // allow GC
694
        }
695
    }
696
    
697
    private void resetModCount() {
698
        modCount = 0;
699
    }
700
    
701
    /**
702
     * Save the state of the <tt>GapList</tt> instance to a stream (that
703
     * is, serialize it).
704
     *
705
     * @serialData The length of the array backing the <tt>GapList</tt>
706
     *             instance is emitted (int), followed by all of its elements
707
     *             (each an <tt>Object</tt>) in the proper order.
708
     */
709
    private void writeObject(java.io.ObjectOutputStream s)
710
    throws java.io.IOException{
711
        // Write out element count, and any hidden stuff
712
        s.defaultWriteObject();
713
        
714
        // Write out array length
715
        s.writeInt(elementData.length);
716
        
717
        // Write out all elements in the proper order.
718
        int i = 0;
719
        while (i < gapStart) {
720
            s.writeObject(elementData[i]);
721
            i++;
722
        }
723
        i += gapLength;
724
        int elementDataLength = elementData.length;
725
        while (i < elementDataLength) {
726
            s.writeObject(elementData[i]);
727
            i++;
728
        }
729
    }
730
    
731
    /**
732
     * Reconstitute the <tt>GapList</tt> instance from a stream (that is,
733
     * deserialize it).
734
     */
735
    private void readObject(java.io.ObjectInputStream s)
736
    throws java.io.IOException, ClassNotFoundException {
737
        // Read in size, and any hidden stuff
738
        s.defaultReadObject();
739
        
740
        // Read in array length and allocate array
741
        int arrayLength = s.readInt();
742
        elementData = new Object[arrayLength];
743
        
744
        // Read in all elements in the proper order.
745
        int i = 0;
746
        while (i < gapStart) {
747
            elementData[i] = s.readObject();
748
            i++;
749
        }
750
        i += gapLength;
751
        int elementDataLength = elementData.length;
752
        while (i < elementDataLength) {
753
            elementData[i] = s.readObject();
754
            i++;
755
        }
756
    }
757
    
758
    /**
759
     * Internal consistency check.
760
     */
761
    void consistencyCheck() {
762
        if (gapStart < 0 || gapLength < 0
763
            || gapStart + gapLength > elementData.length
764
        ) {
765
            consistencyError("Inconsistent gap"); // NOI18N
766
        }
767
        
768
        // Check whether the whole gap contains only nulls
769
        for (int i = gapStart + gapLength - 1; i >= gapStart; i--) {
770
            if (elementData[i] != null) {
771
                consistencyError("Non-null value at raw-index i"); // NOI18N
772
            }
773
        }
774
    }
775
    
776
    private void consistencyError(String s) {
777
        throw new IllegalStateException(s + ": " + toStringInternals()); // NOI18N
778
    }
779
    
780
    String toStringInternals() {
781
        return "elementData.length=" + elementData.length // NOI18N
782
            + ", gapStart=" + gapStart + ", gapLength=" + gapLength; // NOI18N
783
    }
784
    
785
}
(-)editor/util/src/org/netbeans/modules/editor/util/PriorityMutex.java (-147 lines)
Removed Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.modules.editor.util;
15
16
/**
17
 * Mutex that allows only one thread to proceed
18
 * other threads must wait until that one finishes.
19
 * <br>
20
 * The thread that "holds" the mutex (has the mutex access granted)
21
 * may reenter the mutex arbitrary number of times
22
 * (just increasing a "depth" of the locking).
23
 * <br>
24
 * If the priority thread enters waiting on the mutex
25
 * then it will get serviced first once the current thread
26
 * leaves the mutex.
27
 *
28
 * @author Miloslav Metelka
29
 * @version 1.00
30
 */
31
32
public class PriorityMutex {
33
34
    private Thread lockThread;
35
36
    private int lockDepth;
37
    
38
    private Thread waitingPriorityThread;
39
    
40
    /**
41
     * Acquire the ownership of the mutex.
42
     *
43
     * <p>
44
     * The following pattern should always be used:
45
     * <pre>
46
     *   mutex.lock();
47
     *   try {
48
     *       ...
49
     *   } finally {
50
     *       mutex.unlock();
51
     *   }
52
     * </pre>
53
     */
54
    public synchronized void lock() {
55
        Thread thread = Thread.currentThread();
56
        if (thread != lockThread) { // not nested locking
57
            // Will wait if either there is another thread already holding the lock
58
            // or if there is a priority thread waiting but it's not this thread
59
            while (lockThread != null
60
                || (waitingPriorityThread != null && waitingPriorityThread != thread)
61
            ) {
62
                try {
63
                    if (waitingPriorityThread == null && isPriorityThread()) {
64
                        waitingPriorityThread = thread;
65
                    }
66
67
                    wait();
68
69
                } catch (InterruptedException e) {
70
                    waitingPriorityThread = null;
71
                }
72
            }
73
74
            lockThread = thread;
75
76
            if (thread == waitingPriorityThread) {
77
                waitingPriorityThread = null; // it's now allowed to enter
78
            }
79
        }
80
81
        lockDepth++;
82
    }
83
    
84
    /**
85
     * Release the ownership of the mutex.
86
     *
87
     * @see lock()
88
     */
89
    public synchronized void unlock() {
90
        if (Thread.currentThread() != lockThread) {
91
            throw new IllegalStateException("Not locker"); // NOI18N
92
        }
93
94
        if (--lockDepth == 0) {
95
            lockThread = null;
96
97
            notifyAll(); // must all to surely notify waitingPriorityThread too
98
        }
99
    }
100
    
101
    /**
102
     * Can be called by the thread
103
     * that acquired the mutex to check whether there
104
     * is a priority thread (such as AWT event-notification thread)
105
     * waiting.
106
     * <br>
107
     * If there is a priority thread waiting the non-priority thread
108
     * should attempt to stop its work as soon and release the ownership
109
     * of the mutex.
110
     * <br>
111
     * The method must *not* be called without first taking the ownership
112
     * of the mutex (it is intentionally not synchronized).
113
     */
114
    public boolean isPriorityThreadWaiting() {
115
        return (waitingPriorityThread != null);
116
    }
117
    
118
    /**
119
     * Return a thread that acquired this mutex.
120
     * <br>
121
     * This method is intended for diagnostic purposes only.
122
     *
123
     * @return thread that currently acquired lock the mutex
124
        or <code>null</code>
125
     *  if there is currently no thread holding that acquired this mutex.
126
     */
127
    public final synchronized Thread getLockThread() {
128
        return lockThread;
129
    }
130
131
    /**
132
     * Return true if the current thread that is entering this method
133
     * is a priority thread
134
     * and should be allowed to enter as soon as possible.
135
     *
136
     * <p>
137
     * The default implementation assumes that
138
     * {@link javax.swing.SwingUtilities#isEventDispatchThread()}
139
     * is a priority thread.
140
     *
141
     * @return true if the entering thread is a priority thread.
142
     */
143
    protected boolean isPriorityThread() {
144
        return javax.swing.SwingUtilities.isEventDispatchThread();
145
    }
146
147
}
(-)editor/util/src/org/netbeans/modules/editor/util/element/ElementUtilities.java (-39 lines)
Removed Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.modules.editor.util.element;
15
16
import javax.swing.text.Element;
17
18
/**
19
 * Various utility methods related to elements.
20
 *
21
 * @author Miloslav Metelka
22
 * @version 1.00
23
 */
24
25
public final class ElementUtilities {
26
    
27
    private ElementUtilities() {
28
        // No instances
29
    }
30
    
31
    public static void updateOffsetRange(Element[] elements, int[] offsetRange) {
32
        int elementsLength = elements.length;
33
        if (elementsLength > 0) {
34
            offsetRange[0] = Math.min(offsetRange[0], elements[0].getStartOffset());
35
            offsetRange[1] = Math.max(offsetRange[1], elements[elementsLength - 1].getEndOffset());
36
        }
37
    }
38
39
}
(-)editor/util/src/org/netbeans/modules/editor/util/element/GapBranchElement.java (-245 lines)
Removed Link Here
1
/*
2
 *                 Sun Public License Notice
3
 * 
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 * 
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.modules.editor.util.element;
15
16
import javax.swing.text.Element;
17
import javax.swing.event.DocumentEvent;
18
import javax.swing.undo.AbstractUndoableEdit;
19
import javax.swing.undo.CannotUndoException;
20
import javax.swing.undo.CannotRedoException;
21
import org.netbeans.modules.editor.util.*;
22
23
/**
24
 * Branch element that uses gap list to maintain its child elements.
25
 *
26
 * @author Miloslav Metelka
27
 * @version 1.00
28
 */
29
30
public abstract class GapBranchElement implements Element {
31
    
32
    protected static final Element[] EMPTY_ELEMENT_ARRAY = new Element[0];
33
34
    private GapList children;
35
    
36
    public GapBranchElement() {
37
        children = new GapList();
38
    }
39
    
40
    public int getElementCount() {
41
        return children.size();
42
    }
43
    
44
    public Element getElement(int index) {
45
        return (Element)children.get(index);
46
    }
47
    
48
    public void copyElements(int srcBegin, int srcEnd, Element dst[], int dstBegin) {
49
        children.copyItems(srcBegin, srcEnd, dst, dstBegin);
50
    }
51
52
    /**
53
     * Gets the child element index closest to the given offset.
54
     * The offset is specified relative to the beginning of the
55
     * document.  Returns <code>-1</code> if the
56
     * <code>Element</code> is a leaf, otherwise returns
57
     * the index of the <code>Element</code> that best represents
58
     * the given location.  Returns <code>0</code> if the location
59
     * is less than the start offset. Returns
60
     * <code>getElementCount() - 1</code> if the location is
61
     * greater than or equal to the end offset.
62
     *
63
     * <p>
64
     * This implementation is in sync with the original
65
     * <code>Element.getElementIndex()</code> specification
66
     * but it differs
67
     * from <code>AbstractDocument.BranchElement.getElementIndex()</code>
68
     * which returns 0 in case it does not have any children.
69
     * <br>
70
     * This implementation returns -1 in that case because in fact
71
     * the element act as a leaf element in such case.
72
     * <br>
73
     * Nonetheless there should be no difference in functionality
74
     * if this implementation is used for line elements
75
     * because there is always at least one line element even
76
     * for empty doc because of the extra '\n' after the end
77
     * of the AbstractDocument-based implementations.
78
     *
79
     * @param offset the specified offset >= 0
80
     * @return the element index >= 0
81
     */
82
    public int getElementIndex(int offset) {
83
        int low = 0;
84
        int high = getElementCount() - 1;
85
        
86
        if (high == -1) { // no children => return -1
87
            return -1;
88
        }
89
        
90
        while (low <= high) {
91
            int mid = (low + high) / 2;
92
            int elemStartOffset = getElement(mid).getStartOffset();
93
            
94
            if (elemStartOffset < offset) {
95
                low = mid + 1;
96
            } else if (elemStartOffset > offset) {
97
                high = mid - 1;
98
            } else { // element starts at offset
99
                return mid;
100
            }
101
        }
102
103
        if (high < 0) { // if offset < getElement(0).getStartOffset()
104
            high = 0;
105
        }
106
        return high;
107
    }
108
109
    public boolean isLeaf() {
110
        return false;
111
    }
112
    
113
    protected void replace(int index, int removeCount, Element[] addedElems) {
114
        if (removeCount > 0) {
115
            children.remove(index, removeCount);
116
        }
117
        if (addedElems != null) {
118
            children.addArray(index, addedElems);
119
        }
120
    }
121
    
122
    /** Get info about <CODE>DocMarks</CODE>. */
123
    public String toString() {
124
        return children.toString();
125
    }
126
127
    public class Edit extends AbstractUndoableEdit
128
    implements DocumentEvent.ElementChange {
129
        
130
        private int index;
131
        
132
        private Element[] childrenAdded;
133
        
134
        private Element[] childrenRemoved;
135
       
136
        public Edit(int index, Element[] childrenRemoved, Element[] childrenAdded) {
137
            this.index = index;
138
            this.childrenRemoved = childrenRemoved;
139
            this.childrenAdded = childrenAdded;
140
        }
141
        
142
	public Element getElement() {
143
            return GapBranchElement.this;
144
        }
145
146
	public int getIndex() {
147
            return index;
148
        }
149
150
        public Element[] getChildrenRemoved() {
151
            return childrenRemoved;
152
        }
153
154
        public Element[] getChildrenAdded() {
155
            return childrenAdded;
156
        }
157
158
        public void undo() throws CannotUndoException {
159
            super.undo();
160
161
            replace(index, childrenAdded.length, childrenRemoved);
162
163
            // Switch childrenAdded with childrenRemoved
164
            Element[] tmp = childrenRemoved;
165
            childrenRemoved = childrenAdded;
166
            childrenAdded = tmp;
167
        }
168
        
169
        public void redo() throws CannotRedoException {
170
            super.redo();
171
172
            // Switch childrenAdded with childrenRemoved
173
            Element[] tmp = childrenRemoved;
174
            childrenRemoved = childrenAdded;
175
            childrenAdded = tmp;
176
177
            replace(index, childrenRemoved.length, childrenAdded);
178
        }
179
        
180
    }
181
182
    /**
183
     * Extension of {@link GapBranchElement}
184
     * that overrides {@link #getElementIndex(int)}
185
     * which remembers the last returned element index.
186
     */
187
    public abstract class LastIndex {
188
        
189
        private int lastReturnedElementIndex;
190
    
191
        /**
192
         * Implementation that remembers the last returned element index
193
         * and checks the element at the last index when next called.
194
         * <br>
195
         * This may improve performance if there are typically many repetitive calls
196
         * with offset values hitting the last returned element index.
197
         */
198
        public int getElementIndex(int offset) {
199
            int low = 0;
200
            int high = getElementCount() - 1;
201
202
            if (high == -1) { // no children => return -1
203
                return -1;
204
            }
205
206
            int lastIndex = lastReturnedElementIndex; // make copy to be thread-safe
207
            if (lastIndex >= low && lastIndex <= high) {
208
                Element lastElem = getElement(lastIndex);
209
                int lastElemStartOffset = lastElem.getStartOffset();
210
                if (offset >= lastElemStartOffset) {
211
                    int lastElemEndOffset = lastElem.getEndOffset();
212
                    if (offset < lastElemEndOffset) { // hit
213
                        return lastIndex;
214
                    } else { // above
215
                        low = lastIndex + 1;
216
                    }
217
                } else { // below lastIndex
218
                    high = lastIndex - 1;
219
                }
220
            }
221
222
            while (low <= high) {
223
                int mid = (low + high) / 2;
224
                int elemStartOffset = ((Element)children.get(mid)).getStartOffset();
225
226
                if (elemStartOffset < offset) {
227
                    low = mid + 1;
228
                } else if (elemStartOffset > offset) {
229
                    high = mid - 1;
230
                } else { // element starts at offset
231
                    lastReturnedElementIndex = mid;
232
                    return mid;
233
                }
234
            }
235
236
            if (high < 0) {
237
                high = 0;
238
            }
239
            lastReturnedElementIndex = high;
240
            return high;
241
        }
242
        
243
    }
244
245
}
(-)editor/util/test/unit/src/org/netbeans/lib/editor/util/GapListRandomTest.java (+187 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.lib.editor.util;
15
16
import java.util.ArrayList;
17
import java.util.Random;
18
import junit.framework.*;
19
20
21
/**
22
 * Random test of GapList correctness.
23
 *
24
 * @author mmetelka
25
 */
26
public class GapListRandomTest extends TestCase {
27
    
28
    private static final boolean debug = false;
29
    
30
    private static final int OP_COUNT_1 = 10000;
31
    private static final int ADD_RATIO_1 = 100;
32
    private static final int ADD_ALL_RATIO_1 = 10;
33
    private static final int ADD_ALL_MAX_COUNT_1 = 10;
34
    private static final int REMOVE_RATIO_1 = 100;
35
    private static final int REMOVE_RANGE_RATIO_1 = 10;
36
    private static final int CLEAR_RATIO_1 = 5;
37
    private static final int SET_RATIO_1 = 50;
38
    
39
    private static final int OP_COUNT_2 = 10000;
40
    private static final int ADD_RATIO_2 = 50;
41
    private static final int ADD_ALL_RATIO_2 = 20;
42
    private static final int ADD_ALL_MAX_COUNT_2 = 5;
43
    private static final int REMOVE_RATIO_2 = 100;
44
    private static final int REMOVE_RANGE_RATIO_2 = 10;
45
    private static final int CLEAR_RATIO_2 = 3;
46
    private static final int SET_RATIO_2 = 50;
47
    
48
    private ArrayList al;
49
    
50
    private GapList gl;
51
    
52
    public GapListRandomTest(java.lang.String testName) {
53
        super(testName);
54
    }
55
    
56
    public static Test suite() {
57
        TestSuite suite = new TestSuite(GapListRandomTest.class);
58
        return suite;
59
    }
60
61
    protected void setUp() throws java.lang.Exception {
62
    }
63
64
    protected void tearDown() throws java.lang.Exception {
65
    }
66
67
    public void test() {
68
        testFresh(0);
69
    }
70
71
    public void testFresh(long seed) {
72
        Random random = new Random();
73
        if (seed != 0) {
74
            System.err.println("TESTING with SEED=" + seed);
75
            random.setSeed(seed);
76
        }
77
        
78
        gl = new GapList();
79
        al = new ArrayList();
80
        
81
        
82
        testRound(random, OP_COUNT_1, ADD_RATIO_1, ADD_ALL_RATIO_1, ADD_ALL_MAX_COUNT_1,
83
            REMOVE_RATIO_1, REMOVE_RANGE_RATIO_1, CLEAR_RATIO_1, SET_RATIO_1);
84
        testRound(random, OP_COUNT_2, ADD_RATIO_2, ADD_ALL_RATIO_2, ADD_ALL_MAX_COUNT_2,
85
            REMOVE_RATIO_2, REMOVE_RANGE_RATIO_2, CLEAR_RATIO_2, SET_RATIO_2);
86
    }
87
    
88
    private void testRound(Random random, int opCount,
89
    int addRatio, int addAllRatio, int addAllMaxCount,
90
    int removeRatio, int removeRangeRatio, int clearRatio, int setRatio) {
91
        
92
        int ratioSum = addRatio + addAllRatio + removeRatio + removeRangeRatio
93
            + clearRatio + setRatio;
94
        
95
        for (int op = 0; op < opCount; op++) {
96
            double r = random.nextDouble() * ratioSum;
97
98
            if ((r -= addRatio) < 0) {
99
                Object o = new Object();
100
                int index = (int)(al.size() * random.nextDouble());
101
                al.add(index, o);
102
                if (debug) {
103
                    debugOp(op, "add() at index=" + index); // NOI18N
104
                }
105
                gl.add(index, o);
106
107
            } else if ((r -= addAllRatio) < 0) {
108
                int count = (int)(random.nextDouble() * addAllMaxCount);
109
                ArrayList l = new ArrayList();
110
                for (int i = count; i > 0; i--) {
111
                    l.add(new Object());
112
                }
113
114
                Object o = new Object();
115
                int index = (int)(al.size() * random.nextDouble());
116
                al.addAll(index, l);
117
                if (debug) {
118
                    debugOp(op, "addAll() at index=" + index); // NOI18N
119
                }
120
                gl.addAll(index, l);
121
122
            } else if ((r -= removeRatio) < 0) {
123
                if (al.size() > 0) { // is anything to remove
124
                    int index = (int)(al.size() * random.nextDouble());
125
                    al.remove(index);
126
                    if (debug) {
127
                        debugOp(op, "remove() at index=" + index); // NOI18N
128
                    }
129
                    gl.remove(index);
130
                }
131
132
            } else if ((r -= removeRangeRatio) < 0) {
133
                if (al.size() > 0) { // is anything to remove
134
                    int index = (int)(al.size() * random.nextDouble());
135
                    int length = (int)((al.size() - index + 1) * random.nextDouble());
136
                    for (int count = length; count > 0; count--) {
137
                        al.remove(index);
138
                    }
139
                    if (debug) {
140
                        debugOp(op, "remove() at index=" + index + ", length=" + length); // NOI18N
141
                    }
142
                    gl.remove(index, length);
143
                }
144
                
145
            } else if ((r -= clearRatio) < 0) {
146
                al.clear();
147
                if (debug) {
148
                    debugOp(op, "clear()"); // NOI18N
149
                }
150
                gl.clear();
151
                
152
            } else if ((r -= setRatio) < 0) {
153
                if (al.size() > 0) { // is anything to remove
154
                    int index = (int)(al.size() * random.nextDouble());
155
                    Object o = new Object();
156
                    al.set(index, o);
157
                    if (debug) {
158
                        debugOp(op, "set() at index=" + index); // NOI18N
159
                    }
160
                    gl.set(index, o);
161
                }
162
            }
163
164
            checkConsistency();
165
        }
166
        
167
    }
168
        
169
    private void debugOp(int op, String s) {
170
        System.err.println("op: " + op + ", " + s + ", " + gl.toStringInternals());
171
    }
172
    
173
    private void checkConsistency() {
174
        gl.consistencyCheck();
175
176
        assertEquals(gl.size(), al.size());
177
        
178
        int size = al.size();
179
        for (int i = 0; i < size; i++) {
180
            assertTrue("Contents differ at index " + i + ", gl: " + gl.get(i) // NOI18N
181
                + ", al:" + al.get(i), // NOI18N
182
                (gl.get(i) == al.get(i)));
183
        }
184
    }
185
    
186
    
187
}
(-)editor/util/test/unit/src/org/netbeans/modules/editor/util/GapListRandomTest.java (-180 lines)
Removed Link Here
1
package org.netbeans.modules.editor.util;
2
/*
3
 * GapListTest.java
4
 * JUnit based test
5
 *
6
 * Created on June 26, 2004, 8:37 AM
7
 */
8
9
10
import java.util.ArrayList;
11
import java.util.Random;
12
import junit.framework.*;
13
import junit.framework.*;
14
15
/**
16
 *
17
 * @author mmetelka
18
 */
19
public class GapListRandomTest extends TestCase {
20
    
21
    private static final boolean debug = false;
22
    
23
    private static final int OP_COUNT_1 = 10000;
24
    private static final int ADD_RATIO_1 = 100;
25
    private static final int ADD_ALL_RATIO_1 = 10;
26
    private static final int ADD_ALL_MAX_COUNT_1 = 10;
27
    private static final int REMOVE_RATIO_1 = 100;
28
    private static final int REMOVE_RANGE_RATIO_1 = 10;
29
    private static final int CLEAR_RATIO_1 = 5;
30
    private static final int SET_RATIO_1 = 50;
31
    
32
    private static final int OP_COUNT_2 = 10000;
33
    private static final int ADD_RATIO_2 = 50;
34
    private static final int ADD_ALL_RATIO_2 = 20;
35
    private static final int ADD_ALL_MAX_COUNT_2 = 5;
36
    private static final int REMOVE_RATIO_2 = 100;
37
    private static final int REMOVE_RANGE_RATIO_2 = 10;
38
    private static final int CLEAR_RATIO_2 = 3;
39
    private static final int SET_RATIO_2 = 50;
40
    
41
    private ArrayList al;
42
    
43
    private GapList gl;
44
    
45
    public GapListRandomTest(java.lang.String testName) {
46
        super(testName);
47
    }
48
    
49
    public static Test suite() {
50
        TestSuite suite = new TestSuite(GapListRandomTest.class);
51
        return suite;
52
    }
53
54
    protected void setUp() throws java.lang.Exception {
55
    }
56
57
    protected void tearDown() throws java.lang.Exception {
58
    }
59
60
    public void test() {
61
        testFresh(0);
62
    }
63
64
    public void testFresh(long seed) {
65
        Random random = new Random();
66
        if (seed != 0) {
67
            System.err.println("TESTING with SEED=" + seed);
68
            random.setSeed(seed);
69
        }
70
        
71
        gl = new GapList();
72
        al = new ArrayList();
73
        
74
        
75
        testRound(random, OP_COUNT_1, ADD_RATIO_1, ADD_ALL_RATIO_1, ADD_ALL_MAX_COUNT_1,
76
            REMOVE_RATIO_1, REMOVE_RANGE_RATIO_1, CLEAR_RATIO_1, SET_RATIO_1);
77
        testRound(random, OP_COUNT_2, ADD_RATIO_2, ADD_ALL_RATIO_2, ADD_ALL_MAX_COUNT_2,
78
            REMOVE_RATIO_2, REMOVE_RANGE_RATIO_2, CLEAR_RATIO_2, SET_RATIO_2);
79
    }
80
    
81
    private void testRound(Random random, int opCount,
82
    int addRatio, int addAllRatio, int addAllMaxCount,
83
    int removeRatio, int removeRangeRatio, int clearRatio, int setRatio) {
84
        
85
        int ratioSum = addRatio + addAllRatio + removeRatio + removeRangeRatio
86
            + clearRatio + setRatio;
87
        
88
        for (int op = 0; op < opCount; op++) {
89
            double r = random.nextDouble() * ratioSum;
90
91
            if ((r -= addRatio) < 0) {
92
                Object o = new Object();
93
                int index = (int)(al.size() * random.nextDouble());
94
                al.add(index, o);
95
                if (debug) {
96
                    debugOp(op, "add() at index=" + index); // NOI18N
97
                }
98
                gl.add(index, o);
99
100
            } else if ((r -= addAllRatio) < 0) {
101
                int count = (int)(random.nextDouble() * addAllMaxCount);
102
                ArrayList l = new ArrayList();
103
                for (int i = count; i > 0; i--) {
104
                    l.add(new Object());
105
                }
106
107
                Object o = new Object();
108
                int index = (int)(al.size() * random.nextDouble());
109
                al.addAll(index, l);
110
                if (debug) {
111
                    debugOp(op, "addAll() at index=" + index); // NOI18N
112
                }
113
                gl.addAll(index, l);
114
115
            } else if ((r -= removeRatio) < 0) {
116
                if (al.size() > 0) { // is anything to remove
117
                    int index = (int)(al.size() * random.nextDouble());
118
                    al.remove(index);
119
                    if (debug) {
120
                        debugOp(op, "remove() at index=" + index); // NOI18N
121
                    }
122
                    gl.remove(index);
123
                }
124
125
            } else if ((r -= removeRangeRatio) < 0) {
126
                if (al.size() > 0) { // is anything to remove
127
                    int index = (int)(al.size() * random.nextDouble());
128
                    int length = (int)((al.size() - index + 1) * random.nextDouble());
129
                    for (int count = length; count > 0; count--) {
130
                        al.remove(index);
131
                    }
132
                    if (debug) {
133
                        debugOp(op, "remove() at index=" + index + ", length=" + length); // NOI18N
134
                    }
135
                    gl.remove(index, length);
136
                }
137
                
138
            } else if ((r -= clearRatio) < 0) {
139
                al.clear();
140
                if (debug) {
141
                    debugOp(op, "clear()"); // NOI18N
142
                }
143
                gl.clear();
144
                
145
            } else if ((r -= setRatio) < 0) {
146
                if (al.size() > 0) { // is anything to remove
147
                    int index = (int)(al.size() * random.nextDouble());
148
                    Object o = new Object();
149
                    al.set(index, o);
150
                    if (debug) {
151
                        debugOp(op, "set() at index=" + index); // NOI18N
152
                    }
153
                    gl.set(index, o);
154
                }
155
            }
156
157
            checkConsistency();
158
        }
159
        
160
    }
161
        
162
    private void debugOp(int op, String s) {
163
        System.err.println("op: " + op + ", " + s + ", " + gl.toStringInternals());
164
    }
165
    
166
    private void checkConsistency() {
167
        gl.consistencyCheck();
168
169
        assertEquals(gl.size(), al.size());
170
        
171
        int size = al.size();
172
        for (int i = 0; i < size; i++) {
173
            assertTrue("Contents differ at index " + i + ", gl: " + gl.get(i) // NOI18N
174
                + ", al:" + al.get(i), // NOI18N
175
                (gl.get(i) == al.get(i)));
176
        }
177
    }
178
    
179
    
180
}
(-)ide/golden/public-packages.txt (-2 / +2 lines)
Lines 144-149 Link Here
144
org.netbeans.lib.cvsclient.response
144
org.netbeans.lib.cvsclient.response
145
org.netbeans.lib.cvsclient.util
145
org.netbeans.lib.cvsclient.util
146
org.netbeans.lib.editor.hyperlink.spi
146
org.netbeans.lib.editor.hyperlink.spi
147
org.netbeans.lib.editor.util
148
org.netbeans.lib.editor.util.swing
147
org.netbeans.lib.editor.view
149
org.netbeans.lib.editor.view
148
org.netbeans.modules.ant.freeform.spi
150
org.netbeans.modules.ant.freeform.spi
149
org.netbeans.modules.ant.freeform.spi.support
151
org.netbeans.modules.ant.freeform.spi.support
Lines 154-161 Link Here
154
org.netbeans.modules.editor.java
156
org.netbeans.modules.editor.java
155
org.netbeans.modules.editor.options
157
org.netbeans.modules.editor.options
156
org.netbeans.modules.editor.plain
158
org.netbeans.modules.editor.plain
157
org.netbeans.modules.editor.util
158
org.netbeans.modules.editor.util.element
159
org.netbeans.modules.form
159
org.netbeans.modules.form
160
org.netbeans.modules.i18n
160
org.netbeans.modules.i18n
161
org.netbeans.modules.i18n.java
161
org.netbeans.modules.i18n.java

Return to bug 56339