1.1 --- a/PLSQL/Folding/src/org/netbeans/modules/plsql/fold/NewPlsqlFoldManager.java Mon Mar 18 15:49:13 2013 +0100
1.2 +++ b/PLSQL/Folding/src/org/netbeans/modules/plsql/fold/NewPlsqlFoldManager.java Mon Aug 12 11:26:54 2013 +0530
1.3 @@ -42,12 +42,15 @@
1.4 package org.netbeans.modules.plsql.fold;
1.5
1.6 import java.util.ArrayList;
1.7 +import java.util.Collections;
1.8 +import java.util.Comparator;
1.9 import java.util.List;
1.10 import java.util.Observable;
1.11 import java.util.Observer;
1.12 import java.util.logging.Level;
1.13 import java.util.logging.Logger;
1.14 import javax.swing.event.DocumentEvent;
1.15 +import javax.swing.text.AbstractDocument;
1.16 import javax.swing.text.BadLocationException;
1.17 import javax.swing.text.Document;
1.18 import org.netbeans.api.editor.fold.Fold;
1.19 @@ -61,6 +64,7 @@
1.20 import org.netbeans.spi.editor.fold.FoldHierarchyTransaction;
1.21 import org.netbeans.spi.editor.fold.FoldManager;
1.22 import org.netbeans.spi.editor.fold.FoldOperation;
1.23 +import org.openide.util.Exceptions;
1.24 import org.openide.util.Lookup;
1.25 import org.openide.util.RequestProcessor;
1.26
1.27 @@ -70,281 +74,472 @@
1.28 */
1.29 public class NewPlsqlFoldManager implements FoldManager, Runnable, Observer {
1.30
1.31 - private static final Logger LOG = Logger.getLogger(NewPlsqlFoldManager.class.getName());
1.32 - private static final RequestProcessor RP = new RequestProcessor(NewPlsqlFoldManager.class.getName(), 1, false, false);
1.33 - private static final int TASK_DELAY = 1000;
1.34 - private final RequestProcessor.Task task = RP.create(this);
1.35 - private FoldOperation operation;
1.36 - private Document doc;
1.37 - // Note: FoldSearchObject need to be in a List, otherwise contains doesn't work. Seems HashSet keeps internal list of hash.
1.38 - private final List<FoldSearchObject> foldSearchObjects = new ArrayList<FoldSearchObject>();
1.39 - private List<Fold> removedFoldList = new ArrayList<Fold>(3);
1.40 - private boolean initial = true;
1.41 - private PlsqlBlockFactory blockFactory;
1.42 + private static final Logger LOG = Logger.getLogger(NewPlsqlFoldManager.class.getName());
1.43 + private static final RequestProcessor RP = new RequestProcessor(NewPlsqlFoldManager.class.getName(), 1, false, false);
1.44 + private static final int TASK_DELAY = 100;
1.45 + private final RequestProcessor.Task task = RP.create(this);
1.46 + private FoldOperation operation;
1.47 + private Document doc;
1.48 + // Note: FoldSearchObject need to be in a List, otherwise contains doesn't work. Seems HashSet keeps internal list of hash.
1.49 + private final List<FoldSearchObject> foldSearchObjects = new ArrayList<FoldSearchObject>();
1.50 + private List<Fold> removedFoldList = new ArrayList<Fold>(3);
1.51 + private boolean initial = true;
1.52 + private PlsqlBlockFactory blockFactory;
1.53
1.54 - @Override
1.55 - public void init(FoldOperation operation) {
1.56 - this.operation = operation;
1.57 - if (LOG.isLoggable(Level.FINE)) {
1.58 - LOG.log(Level.FINE, "Initialized: {0}", System.identityHashCode(this));
1.59 - }
1.60 - }
1.61 + @Override
1.62 + public void init(FoldOperation operation) {
1.63 + this.operation = operation;
1.64 + if (LOG.isLoggable(Level.FINE)) {
1.65 + LOG.log(Level.FINE, "Initialized: {0}", System.identityHashCode(this));
1.66 + }
1.67 + }
1.68
1.69 - private FoldOperation getOperation() {
1.70 - return operation;
1.71 - }
1.72 + private FoldOperation getOperation() {
1.73 + return operation;
1.74 + }
1.75
1.76 - @Override
1.77 - public void initFolds(FoldHierarchyTransaction transaction) {
1.78 - doc = getOperation().getHierarchy().getComponent().getDocument();
1.79 - blockFactory = getBlockFactory();
1.80 - if (blockFactory != null) {
1.81 - blockFactory.addObserver(this);
1.82 - }
1.83 - task.schedule(TASK_DELAY);
1.84 - }
1.85 + @Override
1.86 + public void initFolds(FoldHierarchyTransaction transaction) {
1.87 + doc = getOperation().getHierarchy().getComponent().getDocument();
1.88 + blockFactory = getBlockFactory();
1.89 + if (blockFactory != null) {
1.90 + blockFactory.addObserver(this);
1.91 + }
1.92 + task.schedule(TASK_DELAY);
1.93 + }
1.94
1.95 - @Override
1.96 - public void insertUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
1.97 - if (LOG.isLoggable(Level.FINER)) {
1.98 - LOG.log(Level.FINER, "insertUpdate: {0}", System.identityHashCode(this));
1.99 - }
1.100 - processRemovedFolds(transaction);
1.101 - }
1.102 + @Override
1.103 + public void insertUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
1.104 + if (LOG.isLoggable(Level.FINER)) {
1.105 + LOG.log(Level.FINER, "insertUpdate: {0}", System.identityHashCode(this));
1.106 + }
1.107 + processRemovedFolds(transaction);
1.108 + }
1.109
1.110 - @Override
1.111 - public void removeUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
1.112 - if (LOG.isLoggable(Level.FINER)) {
1.113 - LOG.log(Level.FINER, "removeUpdate: {0}", System.identityHashCode(this));
1.114 - }
1.115 - processRemovedFolds(transaction);
1.116 - }
1.117 + @Override
1.118 + public void removeUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
1.119 + if (LOG.isLoggable(Level.FINER)) {
1.120 + LOG.log(Level.FINER, "removeUpdate: {0}", System.identityHashCode(this));
1.121 + }
1.122 + processRemovedFolds(transaction);
1.123 + }
1.124
1.125 - @Override
1.126 - public void changedUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
1.127 - }
1.128 + @Override
1.129 + public void changedUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
1.130 + if (LOG.isLoggable(Level.FINER)) {
1.131 + LOG.log(Level.FINER, "changeUpdate: {0}", System.identityHashCode(this));
1.132 + }
1.133 + processRemovedFolds(transaction);
1.134 + }
1.135
1.136 - @Override
1.137 - public void removeEmptyNotify(Fold emptyFold) {
1.138 - if (LOG.isLoggable(Level.FINER)) {
1.139 - LOG.log(Level.FINER, "removeEmptyNotify: {0}", System.identityHashCode(this));
1.140 - }
1.141 - removeFoldNotify(emptyFold);
1.142 - }
1.143 + @Override
1.144 + public void removeEmptyNotify(Fold emptyFold) {
1.145 + if (LOG.isLoggable(Level.FINER)) {
1.146 + LOG.log(Level.FINER, "removeEmptyNotify: {0}", System.identityHashCode(this));
1.147 + }
1.148 + removeFoldNotify(emptyFold);
1.149 + }
1.150
1.151 - @Override
1.152 - public void removeDamagedNotify(Fold damagedFold) {
1.153 - if (LOG.isLoggable(Level.FINER)) {
1.154 - LOG.log(Level.FINER, "removeDamagedNotify: {0}", System.identityHashCode(this));
1.155 - }
1.156 - removeFoldNotify(damagedFold);
1.157 - }
1.158 + @Override
1.159 + public void removeDamagedNotify(Fold damagedFold) {
1.160 + if (LOG.isLoggable(Level.FINER)) {
1.161 + LOG.log(Level.FINER, "removeDamagedNotify: {0}", System.identityHashCode(this));
1.162 + }
1.163 + removeFoldNotify(damagedFold);
1.164 + }
1.165
1.166 - @Override
1.167 - public void expandNotify(Fold expandedFold) {
1.168 - }
1.169 + @Override
1.170 + public void expandNotify(Fold expandedFold) {
1.171 + }
1.172
1.173 - @Override
1.174 - public void release() {
1.175 - if (LOG.isLoggable(Level.FINE)) {
1.176 - LOG.log(Level.FINE, "release: {0}", System.identityHashCode(this));
1.177 - }
1.178 - }
1.179 + @Override
1.180 + public void release() {
1.181 + if (LOG.isLoggable(Level.FINE)) {
1.182 + LOG.log(Level.FINE, "release: {0}", System.identityHashCode(this));
1.183 + }
1.184 + }
1.185
1.186 - @Override
1.187 - public void update(Observable o, Object arg) {
1.188 - if (LOG.isLoggable(Level.FINER)) {
1.189 - LOG.log(Level.FINER, "update: {0}", System.identityHashCode(this));
1.190 - }
1.191 - task.schedule(TASK_DELAY);
1.192 - }
1.193 + @Override
1.194 + public void update(Observable o, Object arg) {
1.195 + if (LOG.isLoggable(Level.FINER)) {
1.196 + LOG.log(Level.FINER, "update: {0}", System.identityHashCode(this));
1.197 + }
1.198 + task.schedule(TASK_DELAY);
1.199 + }
1.200
1.201 - @Override
1.202 - public void run() {
1.203 - if (operation.isReleased()) {
1.204 - if (LOG.isLoggable(Level.FINE)) {
1.205 - LOG.log(Level.FINE, "Update skipped, already released: {0}", System.identityHashCode(this));
1.206 - }
1.207 - return;
1.208 - }
1.209 - ((BaseDocument) doc).readLock();
1.210 - try {
1.211 + @Override
1.212 + public void run() {
1.213 + if (operation.isReleased()) {
1.214 + if (LOG.isLoggable(Level.FINE)) {
1.215 + LOG.log(Level.FINE, "Update skipped, already released: {0}", System.identityHashCode(this));
1.216 + }
1.217 + return;
1.218 + }
1.219 + ((BaseDocument) doc).readLock();
1.220 + try {
1.221 + if (blockFactory != null) {
1.222 + FoldHierarchy hierarchy = getOperation().getHierarchy();
1.223
1.224 - if (blockFactory != null) {
1.225 - FoldHierarchy hierarchy = getOperation().getHierarchy();
1.226 - hierarchy.lock();
1.227 + hierarchy.lock();
1.228 + try {
1.229 + if (operation.isReleased()) {
1.230 + if (LOG.isLoggable(Level.FINE)) {
1.231 + LOG.log(Level.FINE, "Update skipped, already released: {0}", System.identityHashCode(this));
1.232 + }
1.233 + return;
1.234 + }
1.235 + if (LOG.isLoggable(Level.FINE)) {
1.236 + LOG.log(Level.FINE, "Updating: {0}", System.identityHashCode(this));
1.237 + LOG.log(Level.FINE, "blockFactory.getBlockHierarchy().size(): {0}", blockFactory.getBlockHierarchy().size());
1.238 + LOG.log(Level.FINE, "blockFactory.getNewBlocks().size(): {0}", blockFactory.getNewBlocks().size());
1.239 + LOG.log(Level.FINE, "blockFactory.getRemovedBlocks().size(): {0}", blockFactory.getRemovedBlocks().size());
1.240 + }
1.241 + FoldHierarchyTransaction transaction = getOperation().openTransaction();
1.242 + try {
1.243 +
1.244 + final Fold root = hierarchy.getRootFold();
1.245 +
1.246 + if (initial) {
1.247 + List<PlsqlBlock> blocks = blockFactory.getBlockHierarchy();
1.248 + updateFolds(blocks, transaction, null);
1.249 + //Add custom fold blocks
1.250 + updateFolds(blockFactory.getCustomFolds(), transaction, null);
1.251 + initial = false;
1.252 + } else {
1.253 + final List<FoldSearchObject> collapsedFolds = new ArrayList<FoldSearchObject>();
1.254 + getCollapsedFolds(root, collapsedFolds);
1.255 + final List<PlsqlBlock> oldBlocks = blockFactory.getRemovedBlocks();
1.256 +
1.257 + //Remove non existing blocks
1.258 + if (!oldBlocks.isEmpty()) {
1.259 + final int childCount = root.getFoldCount();
1.260 + for (int i = (childCount - 1); i >= 0; i--) {
1.261 + final Fold child = root.getFold(i);
1.262 + removeWithChildren(child, oldBlocks, transaction);
1.263 + }
1.264 + }
1.265 + //Add new blocks to the hierarchy
1.266 + List<PlsqlBlock> blocks = blockFactory.getNewBlocks();
1.267 + updateFolds(blocks, transaction, collapsedFolds);
1.268 + //Add custom fold blocks
1.269 + updateFolds(blockFactory.getCustomFolds(), transaction, collapsedFolds);
1.270 + }
1.271 + } catch (BadLocationException ex) {
1.272 + Exceptions.printStackTrace(ex);
1.273 + } finally {
1.274 + transaction.commit();
1.275 + }
1.276 + } finally {
1.277 + hierarchy.unlock();
1.278 + }
1.279 + }
1.280 + } finally {
1.281 + ((BaseDocument) doc).readUnlock();
1.282 + }
1.283 + }
1.284 +
1.285 + private void getCollapsedFolds(final Fold parent, final List<FoldSearchObject> foldInfoLst) {
1.286 + if (parent.isCollapsed()) {
1.287 + final FoldSearchObject tempInfo = new FoldSearchObject(parent.getStartOffset(), parent.getEndOffset(), parent.getType());
1.288 + foldInfoLst.add(tempInfo);
1.289 + }
1.290 + final int count = parent.getFoldCount();
1.291 + for (int i = 0; i < count; i++) {
1.292 + final Fold temp = parent.getFold(i);
1.293 + getCollapsedFolds(temp, foldInfoLst);
1.294 + }
1.295 + }
1.296 +
1.297 + /**
1.298 + * Remove fold with its children
1.299 + *
1.300 + * @param fold
1.301 + * @param blockHier
1.302 + * @param transaction
1.303 + * @return true if removed all the children
1.304 + */
1.305 + private void removeWithChildren(final Fold fold, final List<PlsqlBlock> blockHier, final FoldHierarchyTransaction transaction) {
1.306 +
1.307 + final int childCount = fold.getFoldCount();
1.308 + for (int i = (childCount - 1); i >= 0; i--) {
1.309 + final Fold child = fold.getFold(i);
1.310 + removeWithChildren(child, blockHier, transaction);
1.311 + }
1.312 +
1.313 + //If a custom fold remove
1.314 + if (fold.getType() == PlsqlFoldTypes.CUSTOM || checkExists(fold, blockHier)) {
1.315 + operation.removeFromHierarchy(fold, transaction);
1.316 + foldSearchObjects.remove(new FoldSearchObject(new FoldAdapter(fold)));
1.317 + }
1.318 + }
1.319 +
1.320 + /**
1.321 + * Method that will check whether given fold exists in block hier
1.322 + *
1.323 + * @param fold
1.324 + * @param blockHier
1.325 + * @return
1.326 + */
1.327 + private boolean checkExists(final Fold fold, final List<PlsqlBlock> blockHier) {
1.328 + final Comparator<PlsqlBlock> comparator = new Comparator<PlsqlBlock>() {
1.329 + @Override
1.330 + public int compare(final PlsqlBlock o1, final PlsqlBlock o2) {
1.331 + Integer o1pos, o2pos;
1.332 + if (o1.getStartOffset() > -1 && o2.getStartOffset() > -1) {
1.333 + o1pos = Integer.valueOf(o1.getStartOffset());
1.334 + o2pos = Integer.valueOf(o2.getStartOffset());
1.335 + } else {
1.336 + o1pos = Integer.valueOf(o1.getEndOffset());
1.337 + o2pos = Integer.valueOf(o2.getEndOffset());
1.338 + }
1.339 + return o1pos.compareTo(o2pos);
1.340 + }
1.341 + };
1.342 + return checkExists(fold, blockHier, comparator);
1.343 + }
1.344 +
1.345 + /**
1.346 + * Method that will check whether given fold exists in block hier
1.347 + *
1.348 + * @param fold
1.349 + * @param blockHier
1.350 + * @param comparator
1.351 + * @return
1.352 + */
1.353 + private boolean checkExists(final Fold fold, final List<PlsqlBlock> blockHier, final Comparator<PlsqlBlock> comparator) {
1.354 + final int size = blockHier.size();
1.355 + Collections.sort(blockHier, comparator);
1.356 + if (size == 0) {
1.357 + return false;
1.358 + }
1.359 + //make sure that the fold isn't before the first block or after the last block in the hierarchy.
1.360 + if (fold.getStartOffset() > blockHier.get(size - 1).getEndOffset()
1.361 + || fold.getEndOffset() < blockHier.get(0).getStartOffset()) {
1.362 + return false;
1.363 + }
1.364 + for (int i = 0; i < size; i++) {
1.365 + final PlsqlBlock block = blockHier.get(i);
1.366 + if (block.getStartOffset() <= fold.getStartOffset() && block.getEndOffset() >= fold.getEndOffset()) {
1.367 + return true;
1.368 + }
1.369 + if (block.getPreviousStart() <= fold.getStartOffset() && block.getPreviousEnd() >= fold.getEndOffset()) {
1.370 + return true;
1.371 + }
1.372 + if ((block.getEndOffset() == fold.getEndOffset() || fold.getEndOffset() == block.getPreviousEnd()
1.373 + || block.getStartOffset() == fold.getStartOffset() || block.getPreviousStart() == fold.getStartOffset())
1.374 + && (getFoldType(block.getType()).equals(fold.getType()))
1.375 + && (getFoldDescription(block).equals(fold.getDescription()))) {
1.376 + return true;
1.377 + }
1.378 +
1.379 + if (checkExists(fold, block.getChildBlocks(), comparator)) {
1.380 + return true;
1.381 + }
1.382 + }
1.383 +
1.384 + return false;
1.385 + }
1.386 +
1.387 + private FoldType getFoldType(final PlsqlBlockType blockType) {
1.388 + switch (blockType) {
1.389 + case VIEW:
1.390 + return PlsqlFoldTypes.VIEW;
1.391 + case TABLE_COMMENT:
1.392 + return PlsqlFoldTypes.TABLECOMMENT;
1.393 + case COLUMN_COMMENT:
1.394 + return PlsqlFoldTypes.COLUMNCOMMENT;
1.395 + case COMMENT:
1.396 + return PlsqlFoldTypes.COMMENT;
1.397 + case PACKAGE:
1.398 + return PlsqlFoldTypes.PACKAGE;
1.399 + case PACKAGE_BODY:
1.400 + return PlsqlFoldTypes.PACKAGEBODY;
1.401 + case PROCEDURE_IMPL:
1.402 + return PlsqlFoldTypes.PROCEDUREIMPL;
1.403 + case FUNCTION_IMPL:
1.404 + return PlsqlFoldTypes.FUNCTIONIMPL;
1.405 + case PROCEDURE_DEF:
1.406 + return PlsqlFoldTypes.PROCEDUREDEF;
1.407 + case FUNCTION_DEF:
1.408 + return PlsqlFoldTypes.FUNCTIONDEF;
1.409 + case DECLARE_END:
1.410 + return PlsqlFoldTypes.DECLAREEND;
1.411 + case BEGIN_END:
1.412 + return PlsqlFoldTypes.BEGINEND;
1.413 + case TRIGGER:
1.414 + return PlsqlFoldTypes.TRIGGER;
1.415 + case IF:
1.416 + return PlsqlFoldTypes.IF;
1.417 + case CASE:
1.418 + return PlsqlFoldTypes.CASE;
1.419 + case WHILE_LOOP:
1.420 + return PlsqlFoldTypes.WHILELOOP;
1.421 + case FOR_LOOP:
1.422 + return PlsqlFoldTypes.FORLOOP;
1.423 + case LOOP:
1.424 + return PlsqlFoldTypes.LOOP;
1.425 + case CUSTOM_FOLD:
1.426 + return PlsqlFoldTypes.CUSTOM;
1.427 + case STATEMENT:
1.428 + return PlsqlFoldTypes.STATEMENT;
1.429 + case CURSOR:
1.430 + return PlsqlFoldTypes.CURSOR;
1.431 + case JAVA_SOURCE:
1.432 + return PlsqlFoldTypes.JAVASOURCE;
1.433 + default:
1.434 + return null;
1.435 + }
1.436 + }
1.437 +
1.438 + /**
1.439 + * Method that will return the fold description given the Plsql block Used
1.440 + * when changing the descriptions only.
1.441 + *
1.442 + * @param block
1.443 + * @return
1.444 + */
1.445 + private String getFoldDescription(final PlsqlBlock block) {
1.446 + switch (block.getType()) {
1.447 + case VIEW:
1.448 + return block.getPrefix() + "VIEW " + block.getName();
1.449 + case TABLE_COMMENT:
1.450 + return "COMMENT ON TABLE " + block.getName();
1.451 + case COLUMN_COMMENT:
1.452 + return "COLUMN COMMENTS ON TABLE " + block.getName();
1.453 + case COMMENT:
1.454 + return block.getName();
1.455 + case PACKAGE:
1.456 + return block.getPrefix() + "PACKAGE " + block.getName();
1.457 + case PACKAGE_BODY:
1.458 + return block.getPrefix() + "PACKAGE BODY " + block.getName();
1.459 + case PROCEDURE_IMPL:
1.460 + return block.getPrefix() + "PROCEDURE IMPLEMENTATION " + block.getName();
1.461 + case FUNCTION_IMPL:
1.462 + return block.getPrefix() + "FUNCTION IMPLEMENTATION " + block.getName();
1.463 + case PROCEDURE_DEF:
1.464 + return "PROCEDURE DEFINITION " + block.getName();
1.465 + case FUNCTION_DEF:
1.466 + return "FUNCTION DEFINITION " + block.getName();
1.467 + case DECLARE_END:
1.468 + return "DECLARE BLOCK";
1.469 + case BEGIN_END:
1.470 + return "BEGIN BLOCK";
1.471 + case TRIGGER:
1.472 + return block.getPrefix() + "TRIGGER " + block.getName();
1.473 + case IF:
1.474 + return block.getName();
1.475 + case CASE:
1.476 + return block.getName();
1.477 + case WHILE_LOOP:
1.478 + return "WHILE " + block.getName();
1.479 + case FOR_LOOP:
1.480 + return "FOR " + block.getName();
1.481 + case LOOP:
1.482 + return "LOOP ";
1.483 + case CUSTOM_FOLD:
1.484 + return block.getName();
1.485 + case STATEMENT:
1.486 + return block.getPrefix() + block.getName();
1.487 + case CURSOR:
1.488 + return "CURSOR " + block.getName();
1.489 + case JAVA_SOURCE:
1.490 + return block.getPrefix() + "JAVA SOURCE";
1.491 + default:
1.492 + return "";
1.493 + }
1.494 + }
1.495 +
1.496 + private void removeFoldNotify(Fold removedFold) {
1.497 + removedFoldList.add(removedFold);
1.498 + }
1.499 +
1.500 + private void processRemovedFolds(FoldHierarchyTransaction transaction) {
1.501 + for (Fold removedFold : removedFoldList) {
1.502 + operation.removeFromHierarchy(removedFold, transaction);
1.503 + if (LOG.isLoggable(Level.FINE)) {
1.504 + LOG.log(Level.FINE, "Fold={0} removed={1}", new Object[]{removedFold, true});
1.505 + }
1.506 + }
1.507 + removedFoldList.clear();
1.508 + }
1.509 +
1.510 + private Document getDocument() {
1.511 + Object obj = null;
1.512 + for (int i = 0; i < 10; i++) {
1.513 + obj = getOperation().getHierarchy().getComponent().getDocument();
1.514 + if (obj instanceof AbstractDocument) {
1.515 + return (Document) obj;
1.516 + }
1.517 try {
1.518 - if (operation.isReleased()) {
1.519 - if (LOG.isLoggable(Level.FINE)) {
1.520 - LOG.log(Level.FINE, "Update skipped, already released: {0}", System.identityHashCode(this));
1.521 - }
1.522 - return;
1.523 - }
1.524 - if (LOG.isLoggable(Level.FINE)) {
1.525 - LOG.log(Level.FINE, "Updating: {0}", System.identityHashCode(this));
1.526 - LOG.log(Level.FINE, "blockFactory.getBlockHierarchy().size(): {0}", blockFactory.getBlockHierarchy().size());
1.527 - LOG.log(Level.FINE, "blockFactory.getNewBlocks().size(): {0}", blockFactory.getNewBlocks().size());
1.528 - LOG.log(Level.FINE, "blockFactory.getRemovedBlocks().size(): {0}", blockFactory.getRemovedBlocks().size());
1.529 - }
1.530 - FoldHierarchyTransaction transaction = getOperation().openTransaction();
1.531 - try {
1.532 - //Add new blocks to the hierarchy
1.533 - List<PlsqlBlock> blocks = blockFactory.getNewBlocks();
1.534 - if (initial) {
1.535 - blocks = blockFactory.getBlockHierarchy();
1.536 - initial = false;
1.537 - }
1.538 + Thread.currentThread().sleep(i);
1.539 + } catch (InterruptedException e) {
1.540 + }
1.541 + }
1.542 + throw new IllegalStateException("[PLSQLFolding] PLSQLFoldManager.getDocument() NOT returned AbstractDocument, but " + obj.getClass() + "!. This is caused by not yet resolved issue #49497."); //NOI18N
1.543 + }
1.544
1.545 - updateFolds(blocks, transaction);
1.546 - //Add custom fold blocks
1.547 - updateFolds(blockFactory.getCustomFolds(), transaction);
1.548 - } finally {
1.549 - transaction.commit();
1.550 - }
1.551 - } finally {
1.552 - hierarchy.unlock();
1.553 + private void updateFolds(final List<PlsqlBlock> blockHier, final FoldHierarchyTransaction transaction, final List<FoldSearchObject> collapsedFolds) throws BadLocationException {
1.554 + final int count = blockHier.size();
1.555 + Document doc = getDocument();
1.556 + for (int i = 0; i < count; i++) {
1.557 + final PlsqlBlock block = blockHier.get(i);
1.558 + FoldType foldType = null;
1.559 + final PlsqlBlockType type = block.getType();
1.560 + String description = "";
1.561 +
1.562 + if (!(type == PlsqlBlockType.COMMENT && doc.getText(block.getStartOffset(), block.getEndOffset() - block.getStartOffset()).indexOf("\n") == -1)) { // check for single line comments
1.563 + foldType = getFoldType(type);
1.564 + description = getFoldDescription(block);
1.565 +
1.566 + if (doc.getEndPosition().getOffset() >= block.getEndOffset()) {
1.567 + operation.addToHierarchy(foldType, description, isCollapsed(block, foldType, collapsedFolds),
1.568 + block.getStartOffset(), block.getEndOffset(), 0, 0, null, transaction);
1.569 + //check for any child folds and add them also
1.570 + updateFolds(block.getChildBlocks(), transaction, collapsedFolds);
1.571 + }
1.572 }
1.573 - }
1.574 - } finally {
1.575 - ((BaseDocument) doc).readUnlock();
1.576 - }
1.577 - }
1.578 + }
1.579 + }
1.580
1.581 - private void removeFoldNotify(Fold removedFold) {
1.582 - removedFoldList.add(removedFold);
1.583 - }
1.584 + /**
1.585 + * Method that will select and return the corresponding fold to parent from
1.586 + * oldRoot fold hierarchy
1.587 + *
1.588 + * @param parent
1.589 + * @param foldInfoLst
1.590 + * @return
1.591 + */
1.592 + private boolean isCollapsed(final PlsqlBlock block, final FoldType foldType, final List<FoldSearchObject> foldInfoLst) {
1.593 + if (OptionsUtilities.isPlSqlExpandFolds()) {
1.594 + return false;
1.595 + }
1.596 + if (foldInfoLst == null) {
1.597 + return foldType == PlsqlFoldTypes.COMMENT;
1.598 + }
1.599 + final int size = foldInfoLst.size();
1.600 + for (int i = 0; i < size; i++) {
1.601 + final FoldSearchObject temp = foldInfoLst.get(i);
1.602
1.603 - private void processRemovedFolds(FoldHierarchyTransaction transaction) {
1.604 - for (Fold removedFold : removedFoldList) {
1.605 - boolean remove = foldSearchObjects.remove(new FoldSearchObject(new FoldAdapter(removedFold)));
1.606 - if (LOG.isLoggable(Level.FINE)) {
1.607 - LOG.log(Level.FINE, "Fold={0} removed={1}", new Object[]{removedFold, remove});
1.608 - }
1.609 - }
1.610 - removedFoldList.clear();
1.611 - }
1.612 + if ((temp.getFoldType() == foldType)
1.613 + && (temp.getStartOffset() == block.getPreviousStart())
1.614 + && (temp.getEndOffset() == block.getPreviousEnd())) {
1.615 + return true;
1.616 + }
1.617 + }
1.618
1.619 - private void updateFolds(List<PlsqlBlock> blocks, FoldHierarchyTransaction transaction) {
1.620 - for (PlsqlBlock block : blocks) {
1.621 + return false;
1.622 + }
1.623
1.624 - FoldType foldType = null;
1.625 - final PlsqlBlockType type = block.getType();
1.626 - String description = null;
1.627 - try {
1.628 - if (!(type == PlsqlBlockType.COMMENT && doc.getText(block.getStartOffset(), block.getEndOffset() - block.getStartOffset()).indexOf("\n") == -1)) { // check for single line comments
1.629 - if (type == PlsqlBlockType.VIEW) {
1.630 - foldType = PlsqlFoldTypes.VIEW;
1.631 - description = block.getPrefix() + "VIEW " + block.getName();
1.632 - } else if (type == PlsqlBlockType.TABLE_COMMENT) {
1.633 - foldType = PlsqlFoldTypes.TABLECOMMENT;
1.634 - description = "COMMENT ON TABLE " + block.getName();
1.635 - } else if (type == PlsqlBlockType.COLUMN_COMMENT) {
1.636 - foldType = PlsqlFoldTypes.COLUMNCOMMENT;
1.637 - description = "COLUMN COMMENTS ON TABLE " + block.getName();
1.638 - } else if (type == PlsqlBlockType.COMMENT) {
1.639 - foldType = PlsqlFoldTypes.COMMENT;
1.640 - description = block.getName();
1.641 - } else if (type == PlsqlBlockType.PACKAGE) {
1.642 - foldType = PlsqlFoldTypes.PACKAGE;
1.643 - description = block.getPrefix() + "PACKAGE " + block.getName();
1.644 - } else if (type == PlsqlBlockType.PACKAGE_BODY) {
1.645 - foldType = PlsqlFoldTypes.PACKAGEBODY;
1.646 - description = block.getPrefix() + "PACKAGE BODY " + block.getName();
1.647 - } else if (type == PlsqlBlockType.PROCEDURE_IMPL) {
1.648 - foldType = PlsqlFoldTypes.PROCEDUREIMPL;
1.649 - description = block.getPrefix() + "PROCEDURE IMPLEMENTATION " + block.getName();
1.650 - } else if (type == PlsqlBlockType.FUNCTION_IMPL) {
1.651 - foldType = PlsqlFoldTypes.FUNCTIONIMPL;
1.652 - description = block.getPrefix() + "FUNCTION IMPLEMENTATION " + block.getName();
1.653 - } else if (type == PlsqlBlockType.PROCEDURE_DEF) {
1.654 - foldType = PlsqlFoldTypes.PROCEDUREDEF;
1.655 - description = "PROCEDURE DEFINITION " + block.getName();
1.656 - } else if (type == PlsqlBlockType.FUNCTION_DEF) {
1.657 - foldType = PlsqlFoldTypes.FUNCTIONDEF;
1.658 - description = "FUNCTION DEFINITION " + block.getName();
1.659 - } else if (type == PlsqlBlockType.DECLARE_END) {
1.660 - foldType = PlsqlFoldTypes.DECLAREEND;
1.661 - description = "DECLARE BLOCK";
1.662 - } else if (type == PlsqlBlockType.BEGIN_END) {
1.663 - foldType = PlsqlFoldTypes.BEGINEND;
1.664 - description = "BEGIN BLOCK";
1.665 - } else if (type == PlsqlBlockType.TRIGGER) {
1.666 - foldType = PlsqlFoldTypes.TRIGGER;
1.667 - description = block.getPrefix() + "TRIGGER " + block.getName();
1.668 - } else if (type == PlsqlBlockType.IF) {
1.669 - foldType = PlsqlFoldTypes.IF;
1.670 - description = block.getName();
1.671 - } else if (type == PlsqlBlockType.CASE) {
1.672 - foldType = PlsqlFoldTypes.CASE;
1.673 - description = block.getName();
1.674 - } else if (type == PlsqlBlockType.WHILE_LOOP) {
1.675 - foldType = PlsqlFoldTypes.WHILELOOP;
1.676 - description = "WHILE " + block.getName();
1.677 - } else if (type == PlsqlBlockType.FOR_LOOP) {
1.678 - foldType = PlsqlFoldTypes.FORLOOP;
1.679 - description = "FOR " + block.getName();
1.680 - } else if (type == PlsqlBlockType.LOOP) {
1.681 - foldType = PlsqlFoldTypes.LOOP;
1.682 - description = "LOOP ";
1.683 - } else if (type == PlsqlBlockType.CUSTOM_FOLD) {
1.684 - foldType = PlsqlFoldTypes.CUSTOM;
1.685 - description = block.getName();
1.686 - } else if (type == PlsqlBlockType.STATEMENT) {
1.687 - foldType = PlsqlFoldTypes.STATEMENT;
1.688 - description = block.getPrefix() + block.getName();
1.689 - } else if (type == PlsqlBlockType.CURSOR) {
1.690 - foldType = PlsqlFoldTypes.CURSOR;
1.691 - description = "CURSOR " + block.getName();
1.692 - } else if (type == PlsqlBlockType.JAVA_SOURCE) {
1.693 - foldType = PlsqlFoldTypes.JAVASOURCE;
1.694 - description = block.getPrefix() + "JAVA SOURCE";
1.695 - }
1.696 -
1.697 - final FoldSearchObject foldSearchObject = new FoldSearchObject(block.getStartOffset(), block.getEndOffset());
1.698 - if (!foldSearchObjects.contains(foldSearchObject)) {
1.699 - try {
1.700 - final Fold fold = operation.addToHierarchy(foldType, description, isCollapsed(foldType), block.getStartOffset(), block.getEndOffset(), 0, 0, null, transaction);
1.701 - foldSearchObjects.add(new FoldSearchObject(new FoldAdapter(fold)));
1.702 - } catch (BadLocationException ex) {
1.703 - if (LOG.isLoggable(Level.FINE)) {
1.704 - LOG.log(Level.FINE, "Ignore BadLocationException", ex);
1.705 - }
1.706 - }
1.707 - }
1.708 - updateFolds(block.getChildBlocks(), transaction);
1.709 - }
1.710 - } catch (BadLocationException ex) {
1.711 - if (LOG.isLoggable(Level.FINE)) {
1.712 - LOG.log(Level.FINE, "Ignore BadLocationException", ex);
1.713 - }
1.714 - }
1.715 - }
1.716 - }
1.717 -
1.718 - /**
1.719 - * Method that will select and return the corresponding fold to parent from oldRoot fold hierarchy
1.720 - *
1.721 - * @param parent
1.722 - * @param foldInfoLst
1.723 - * @return
1.724 - */
1.725 - private boolean isCollapsed(final FoldType foldType) {
1.726 - if (OptionsUtilities.isPlSqlExpandFolds()) {
1.727 - return false;
1.728 - }
1.729 - return foldType == PlsqlFoldTypes.COMMENT;
1.730 - }
1.731 -
1.732 - /**
1.733 - * Method that will return the relevant block factory
1.734 - *
1.735 - * @return
1.736 - */
1.737 - private PlsqlBlockFactory getBlockFactory() {
1.738 - final Object obj = doc.getProperty(Document.StreamDescriptionProperty);
1.739 - if (obj instanceof Lookup.Provider) {
1.740 - return ((Lookup.Provider) obj).getLookup().lookup(PlsqlBlockFactory.class);
1.741 - }
1.742 - return null;
1.743 - }
1.744 + /**
1.745 + * Method that will return the relevant block factory
1.746 + *
1.747 + * @return
1.748 + */
1.749 + private PlsqlBlockFactory getBlockFactory() {
1.750 + final Object obj = doc.getProperty(Document.StreamDescriptionProperty);
1.751 + if (obj instanceof Lookup.Provider) {
1.752 + return ((Lookup.Provider) obj).getLookup().lookup(PlsqlBlockFactory.class);
1.753 + }
1.754 + return null;
1.755 + }
1.756 }