PLSQL/Folding/src/org/netbeans/modules/plsql/fold/NewPlsqlFoldManager.java
author Subhashini Sooriarachchi <subslk@netbeans.org>
Mon, 12 Aug 2013 11:26:54 +0530
changeset 464 e10b2e8563fc
parent 362 9a549f0d1c97
permissions -rw-r--r--
EADS-3749 encountering issues with the displaying of code in Developer Studio when code folding is enabled
jrechtacek@0
     1
/*
jrechtacek@0
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jrechtacek@0
     3
 *
jrechtacek@0
     4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
jrechtacek@0
     5
 *
jrechtacek@0
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jrechtacek@0
     7
 * Other names may be trademarks of their respective owners.
jrechtacek@0
     8
 *
jrechtacek@0
     9
 * The contents of this file are subject to the terms of either the GNU
jrechtacek@0
    10
 * General Public License Version 2 only ("GPL") or the Common
jrechtacek@0
    11
 * Development and Distribution License("CDDL") (collectively, the
jrechtacek@0
    12
 * "License"). You may not use this file except in compliance with the
jrechtacek@0
    13
 * License. You can obtain a copy of the License at
jrechtacek@0
    14
 * http://www.netbeans.org/cddl-gplv2.html
jrechtacek@0
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jrechtacek@0
    16
 * specific language governing permissions and limitations under the
jrechtacek@0
    17
 * License.  When distributing the software, include this License Header
jrechtacek@0
    18
 * Notice in each file and include the License file at
jrechtacek@0
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jrechtacek@0
    20
 * particular file as subject to the "Classpath" exception as provided
jrechtacek@0
    21
 * by Oracle in the GPL Version 2 section of the License file that
jrechtacek@0
    22
 * accompanied this code. If applicable, add the following below the
jrechtacek@0
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jrechtacek@0
    24
 * your own identifying information:
jrechtacek@0
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jrechtacek@0
    26
 *
jrechtacek@0
    27
 * If you wish your version of this file to be governed by only the CDDL
jrechtacek@0
    28
 * or only the GPL Version 2, indicate your decision by adding
jrechtacek@0
    29
 * "[Contributor] elects to include this software in this distribution
jrechtacek@0
    30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jrechtacek@0
    31
 * single choice of license, a recipient has the option to distribute
jrechtacek@0
    32
 * your version of this file under either the CDDL, the GPL Version 2 or
jrechtacek@0
    33
 * to extend the choice of license to its licensees as provided above.
jrechtacek@0
    34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jrechtacek@0
    35
 * Version 2 license, then the option applies only if the new code is
jrechtacek@0
    36
 * made subject to such option by the copyright holder.
jrechtacek@0
    37
 *
jrechtacek@0
    38
 * Contributor(s):
jrechtacek@0
    39
 *
jrechtacek@0
    40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
jrechtacek@0
    41
 */
jrechtacek@0
    42
package org.netbeans.modules.plsql.fold;
jrechtacek@0
    43
jrechtacek@0
    44
import java.util.ArrayList;
subslk@464
    45
import java.util.Collections;
subslk@464
    46
import java.util.Comparator;
jrechtacek@0
    47
import java.util.List;
jrechtacek@0
    48
import java.util.Observable;
jrechtacek@0
    49
import java.util.Observer;
chrislovsund@355
    50
import java.util.logging.Level;
chrislovsund@355
    51
import java.util.logging.Logger;
jrechtacek@0
    52
import javax.swing.event.DocumentEvent;
subslk@464
    53
import javax.swing.text.AbstractDocument;
jrechtacek@0
    54
import javax.swing.text.BadLocationException;
jrechtacek@0
    55
import javax.swing.text.Document;
jrechtacek@0
    56
import org.netbeans.api.editor.fold.Fold;
jrechtacek@0
    57
import org.netbeans.api.editor.fold.FoldHierarchy;
jrechtacek@0
    58
import org.netbeans.api.editor.fold.FoldType;
jrechtacek@0
    59
import org.netbeans.editor.BaseDocument;
chrislovsund@355
    60
import org.netbeans.modules.plsql.lexer.PlsqlBlock;
chrislovsund@355
    61
import org.netbeans.modules.plsql.lexer.PlsqlBlockFactory;
chrislovsund@355
    62
import org.netbeans.modules.plsql.lexer.PlsqlBlockType;
chrislovsund@86
    63
import org.netbeans.modules.plsqlsupport.options.OptionsUtilities;
jrechtacek@0
    64
import org.netbeans.spi.editor.fold.FoldHierarchyTransaction;
jrechtacek@0
    65
import org.netbeans.spi.editor.fold.FoldManager;
jrechtacek@0
    66
import org.netbeans.spi.editor.fold.FoldOperation;
subslk@464
    67
import org.openide.util.Exceptions;
jrechtacek@0
    68
import org.openide.util.Lookup;
chrislovsund@355
    69
import org.openide.util.RequestProcessor;
jrechtacek@0
    70
jrechtacek@0
    71
/**
jrechtacek@0
    72
 *
chrislovsund@355
    73
 * @author chrlse
jrechtacek@0
    74
 */
chrislovsund@355
    75
public class NewPlsqlFoldManager implements FoldManager, Runnable, Observer {
jrechtacek@0
    76
subslk@464
    77
    private static final Logger LOG = Logger.getLogger(NewPlsqlFoldManager.class.getName());
subslk@464
    78
    private static final RequestProcessor RP = new RequestProcessor(NewPlsqlFoldManager.class.getName(), 1, false, false);
subslk@464
    79
    private static final int TASK_DELAY = 100;
subslk@464
    80
    private final RequestProcessor.Task task = RP.create(this);
subslk@464
    81
    private FoldOperation operation;
subslk@464
    82
    private Document doc;
subslk@464
    83
    // Note: FoldSearchObject need to be in a List, otherwise contains doesn't work. Seems HashSet keeps internal list of hash.
subslk@464
    84
    private final List<FoldSearchObject> foldSearchObjects = new ArrayList<FoldSearchObject>();
subslk@464
    85
    private List<Fold> removedFoldList = new ArrayList<Fold>(3);
subslk@464
    86
    private boolean initial = true;
subslk@464
    87
    private PlsqlBlockFactory blockFactory;
jrechtacek@0
    88
subslk@464
    89
    @Override
subslk@464
    90
    public void init(FoldOperation operation) {
subslk@464
    91
        this.operation = operation;
subslk@464
    92
        if (LOG.isLoggable(Level.FINE)) {
subslk@464
    93
            LOG.log(Level.FINE, "Initialized: {0}", System.identityHashCode(this));
subslk@464
    94
        }
subslk@464
    95
    }
chrislovsund@355
    96
subslk@464
    97
    private FoldOperation getOperation() {
subslk@464
    98
        return operation;
subslk@464
    99
    }
jrechtacek@0
   100
subslk@464
   101
    @Override
subslk@464
   102
    public void initFolds(FoldHierarchyTransaction transaction) {
subslk@464
   103
        doc = getOperation().getHierarchy().getComponent().getDocument();
subslk@464
   104
        blockFactory = getBlockFactory();
subslk@464
   105
        if (blockFactory != null) {
subslk@464
   106
            blockFactory.addObserver(this);
subslk@464
   107
        }
subslk@464
   108
        task.schedule(TASK_DELAY);
subslk@464
   109
    }
jrechtacek@0
   110
subslk@464
   111
    @Override
subslk@464
   112
    public void insertUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
subslk@464
   113
        if (LOG.isLoggable(Level.FINER)) {
subslk@464
   114
            LOG.log(Level.FINER, "insertUpdate: {0}", System.identityHashCode(this));
subslk@464
   115
        }
subslk@464
   116
        processRemovedFolds(transaction);
subslk@464
   117
    }
chrislovsund@355
   118
subslk@464
   119
    @Override
subslk@464
   120
    public void removeUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
subslk@464
   121
        if (LOG.isLoggable(Level.FINER)) {
subslk@464
   122
            LOG.log(Level.FINER, "removeUpdate: {0}", System.identityHashCode(this));
subslk@464
   123
        }
subslk@464
   124
        processRemovedFolds(transaction);
subslk@464
   125
    }
chrislovsund@355
   126
subslk@464
   127
    @Override
subslk@464
   128
    public void changedUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
subslk@464
   129
        if (LOG.isLoggable(Level.FINER)) {
subslk@464
   130
            LOG.log(Level.FINER, "changeUpdate: {0}", System.identityHashCode(this));
subslk@464
   131
        }
subslk@464
   132
        processRemovedFolds(transaction);
subslk@464
   133
    }
chrislovsund@355
   134
subslk@464
   135
    @Override
subslk@464
   136
    public void removeEmptyNotify(Fold emptyFold) {
subslk@464
   137
        if (LOG.isLoggable(Level.FINER)) {
subslk@464
   138
            LOG.log(Level.FINER, "removeEmptyNotify: {0}", System.identityHashCode(this));
subslk@464
   139
        }
subslk@464
   140
        removeFoldNotify(emptyFold);
subslk@464
   141
    }
chrislovsund@355
   142
subslk@464
   143
    @Override
subslk@464
   144
    public void removeDamagedNotify(Fold damagedFold) {
subslk@464
   145
        if (LOG.isLoggable(Level.FINER)) {
subslk@464
   146
            LOG.log(Level.FINER, "removeDamagedNotify: {0}", System.identityHashCode(this));
subslk@464
   147
        }
subslk@464
   148
        removeFoldNotify(damagedFold);
subslk@464
   149
    }
chrislovsund@355
   150
subslk@464
   151
    @Override
subslk@464
   152
    public void expandNotify(Fold expandedFold) {
subslk@464
   153
    }
chrislovsund@355
   154
subslk@464
   155
    @Override
subslk@464
   156
    public void release() {
subslk@464
   157
        if (LOG.isLoggable(Level.FINE)) {
subslk@464
   158
            LOG.log(Level.FINE, "release: {0}", System.identityHashCode(this));
subslk@464
   159
        }
subslk@464
   160
    }
chrislovsund@355
   161
subslk@464
   162
    @Override
subslk@464
   163
    public void update(Observable o, Object arg) {
subslk@464
   164
        if (LOG.isLoggable(Level.FINER)) {
subslk@464
   165
            LOG.log(Level.FINER, "update: {0}", System.identityHashCode(this));
subslk@464
   166
        }
subslk@464
   167
        task.schedule(TASK_DELAY);
subslk@464
   168
    }
chrislovsund@355
   169
subslk@464
   170
    @Override
subslk@464
   171
    public void run() {
subslk@464
   172
        if (operation.isReleased()) {
subslk@464
   173
            if (LOG.isLoggable(Level.FINE)) {
subslk@464
   174
                LOG.log(Level.FINE, "Update skipped, already released: {0}", System.identityHashCode(this));
subslk@464
   175
            }
subslk@464
   176
            return;
subslk@464
   177
        }
subslk@464
   178
        ((BaseDocument) doc).readLock();
subslk@464
   179
        try {
subslk@464
   180
            if (blockFactory != null) {
subslk@464
   181
                FoldHierarchy hierarchy = getOperation().getHierarchy();
jrechtacek@0
   182
subslk@464
   183
                hierarchy.lock();
subslk@464
   184
                try {
subslk@464
   185
                    if (operation.isReleased()) {
subslk@464
   186
                        if (LOG.isLoggable(Level.FINE)) {
subslk@464
   187
                            LOG.log(Level.FINE, "Update skipped, already released: {0}", System.identityHashCode(this));
subslk@464
   188
                        }
subslk@464
   189
                        return;
subslk@464
   190
                    }
subslk@464
   191
                    if (LOG.isLoggable(Level.FINE)) {
subslk@464
   192
                        LOG.log(Level.FINE, "Updating: {0}", System.identityHashCode(this));
subslk@464
   193
                        LOG.log(Level.FINE, "blockFactory.getBlockHierarchy().size(): {0}", blockFactory.getBlockHierarchy().size());
subslk@464
   194
                        LOG.log(Level.FINE, "blockFactory.getNewBlocks().size(): {0}", blockFactory.getNewBlocks().size());
subslk@464
   195
                        LOG.log(Level.FINE, "blockFactory.getRemovedBlocks().size(): {0}", blockFactory.getRemovedBlocks().size());
subslk@464
   196
                    }
subslk@464
   197
                    FoldHierarchyTransaction transaction = getOperation().openTransaction();
subslk@464
   198
                    try {
subslk@464
   199
subslk@464
   200
                        final Fold root = hierarchy.getRootFold();
subslk@464
   201
subslk@464
   202
                        if (initial) {
subslk@464
   203
                            List<PlsqlBlock> blocks = blockFactory.getBlockHierarchy();
subslk@464
   204
                            updateFolds(blocks, transaction, null);
subslk@464
   205
                            //Add custom fold blocks
subslk@464
   206
                            updateFolds(blockFactory.getCustomFolds(), transaction, null);
subslk@464
   207
                            initial = false;
subslk@464
   208
                        } else {
subslk@464
   209
                            final List<FoldSearchObject> collapsedFolds = new ArrayList<FoldSearchObject>();
subslk@464
   210
                            getCollapsedFolds(root, collapsedFolds);
subslk@464
   211
                            final List<PlsqlBlock> oldBlocks = blockFactory.getRemovedBlocks();
subslk@464
   212
subslk@464
   213
                            //Remove non existing blocks   
subslk@464
   214
                            if (!oldBlocks.isEmpty()) {
subslk@464
   215
                                final int childCount = root.getFoldCount();
subslk@464
   216
                                for (int i = (childCount - 1); i >= 0; i--) {
subslk@464
   217
                                    final Fold child = root.getFold(i);
subslk@464
   218
                                    removeWithChildren(child, oldBlocks, transaction);
subslk@464
   219
                                }
subslk@464
   220
                            }
subslk@464
   221
                            //Add new blocks to the hierarchy
subslk@464
   222
                            List<PlsqlBlock> blocks = blockFactory.getNewBlocks();
subslk@464
   223
                            updateFolds(blocks, transaction, collapsedFolds);
subslk@464
   224
                            //Add custom fold blocks
subslk@464
   225
                            updateFolds(blockFactory.getCustomFolds(), transaction, collapsedFolds);
subslk@464
   226
                        }
subslk@464
   227
                    } catch (BadLocationException ex) {
subslk@464
   228
                        Exceptions.printStackTrace(ex);
subslk@464
   229
                    } finally {
subslk@464
   230
                        transaction.commit();
subslk@464
   231
                    }
subslk@464
   232
                } finally {
subslk@464
   233
                    hierarchy.unlock();
subslk@464
   234
                }
subslk@464
   235
            }
subslk@464
   236
        } finally {
subslk@464
   237
            ((BaseDocument) doc).readUnlock();
subslk@464
   238
        }
subslk@464
   239
    }
subslk@464
   240
subslk@464
   241
    private void getCollapsedFolds(final Fold parent, final List<FoldSearchObject> foldInfoLst) {
subslk@464
   242
        if (parent.isCollapsed()) {
subslk@464
   243
            final FoldSearchObject tempInfo = new FoldSearchObject(parent.getStartOffset(), parent.getEndOffset(), parent.getType());
subslk@464
   244
            foldInfoLst.add(tempInfo);
subslk@464
   245
        }
subslk@464
   246
        final int count = parent.getFoldCount();
subslk@464
   247
        for (int i = 0; i < count; i++) {
subslk@464
   248
            final Fold temp = parent.getFold(i);
subslk@464
   249
            getCollapsedFolds(temp, foldInfoLst);
subslk@464
   250
        }
subslk@464
   251
    }
subslk@464
   252
subslk@464
   253
    /**
subslk@464
   254
     * Remove fold with its children
subslk@464
   255
     *
subslk@464
   256
     * @param fold
subslk@464
   257
     * @param blockHier
subslk@464
   258
     * @param transaction
subslk@464
   259
     * @return true if removed all the children
subslk@464
   260
     */
subslk@464
   261
    private void removeWithChildren(final Fold fold, final List<PlsqlBlock> blockHier, final FoldHierarchyTransaction transaction) {
subslk@464
   262
subslk@464
   263
        final int childCount = fold.getFoldCount();
subslk@464
   264
        for (int i = (childCount - 1); i >= 0; i--) {
subslk@464
   265
            final Fold child = fold.getFold(i);
subslk@464
   266
            removeWithChildren(child, blockHier, transaction);
subslk@464
   267
        }
subslk@464
   268
subslk@464
   269
        //If a custom fold remove
subslk@464
   270
        if (fold.getType() == PlsqlFoldTypes.CUSTOM || checkExists(fold, blockHier)) {
subslk@464
   271
            operation.removeFromHierarchy(fold, transaction);
subslk@464
   272
            foldSearchObjects.remove(new FoldSearchObject(new FoldAdapter(fold)));
subslk@464
   273
        }
subslk@464
   274
    }
subslk@464
   275
subslk@464
   276
    /**
subslk@464
   277
     * Method that will check whether given fold exists in block hier
subslk@464
   278
     *
subslk@464
   279
     * @param fold
subslk@464
   280
     * @param blockHier
subslk@464
   281
     * @return
subslk@464
   282
     */
subslk@464
   283
    private boolean checkExists(final Fold fold, final List<PlsqlBlock> blockHier) {
subslk@464
   284
        final Comparator<PlsqlBlock> comparator = new Comparator<PlsqlBlock>() {
subslk@464
   285
            @Override
subslk@464
   286
            public int compare(final PlsqlBlock o1, final PlsqlBlock o2) {
subslk@464
   287
                Integer o1pos, o2pos;
subslk@464
   288
                if (o1.getStartOffset() > -1 && o2.getStartOffset() > -1) {
subslk@464
   289
                    o1pos = Integer.valueOf(o1.getStartOffset());
subslk@464
   290
                    o2pos = Integer.valueOf(o2.getStartOffset());
subslk@464
   291
                } else {
subslk@464
   292
                    o1pos = Integer.valueOf(o1.getEndOffset());
subslk@464
   293
                    o2pos = Integer.valueOf(o2.getEndOffset());
subslk@464
   294
                }
subslk@464
   295
                return o1pos.compareTo(o2pos);
subslk@464
   296
            }
subslk@464
   297
        };
subslk@464
   298
        return checkExists(fold, blockHier, comparator);
subslk@464
   299
    }
subslk@464
   300
subslk@464
   301
    /**
subslk@464
   302
     * Method that will check whether given fold exists in block hier
subslk@464
   303
     *
subslk@464
   304
     * @param fold
subslk@464
   305
     * @param blockHier
subslk@464
   306
     * @param comparator
subslk@464
   307
     * @return
subslk@464
   308
     */
subslk@464
   309
    private boolean checkExists(final Fold fold, final List<PlsqlBlock> blockHier, final Comparator<PlsqlBlock> comparator) {
subslk@464
   310
        final int size = blockHier.size();
subslk@464
   311
        Collections.sort(blockHier, comparator);
subslk@464
   312
        if (size == 0) {
subslk@464
   313
            return false;
subslk@464
   314
        }
subslk@464
   315
        //make sure that the fold isn't before the first block or after the last block in the hierarchy.
subslk@464
   316
        if (fold.getStartOffset() > blockHier.get(size - 1).getEndOffset()
subslk@464
   317
                || fold.getEndOffset() < blockHier.get(0).getStartOffset()) {
subslk@464
   318
            return false;
subslk@464
   319
        }
subslk@464
   320
        for (int i = 0; i < size; i++) {
subslk@464
   321
            final PlsqlBlock block = blockHier.get(i);
subslk@464
   322
            if (block.getStartOffset() <= fold.getStartOffset() && block.getEndOffset() >= fold.getEndOffset()) {
subslk@464
   323
                return true;
subslk@464
   324
            }
subslk@464
   325
            if (block.getPreviousStart() <= fold.getStartOffset() && block.getPreviousEnd() >= fold.getEndOffset()) {
subslk@464
   326
                return true;
subslk@464
   327
            }
subslk@464
   328
            if ((block.getEndOffset() == fold.getEndOffset() || fold.getEndOffset() == block.getPreviousEnd()
subslk@464
   329
                    || block.getStartOffset() == fold.getStartOffset() || block.getPreviousStart() == fold.getStartOffset())
subslk@464
   330
                    && (getFoldType(block.getType()).equals(fold.getType()))
subslk@464
   331
                    && (getFoldDescription(block).equals(fold.getDescription()))) {
subslk@464
   332
                return true;
subslk@464
   333
            }
subslk@464
   334
subslk@464
   335
            if (checkExists(fold, block.getChildBlocks(), comparator)) {
subslk@464
   336
                return true;
subslk@464
   337
            }
subslk@464
   338
        }
subslk@464
   339
subslk@464
   340
        return false;
subslk@464
   341
    }
subslk@464
   342
subslk@464
   343
    private FoldType getFoldType(final PlsqlBlockType blockType) {
subslk@464
   344
        switch (blockType) {
subslk@464
   345
            case VIEW:
subslk@464
   346
                return PlsqlFoldTypes.VIEW;
subslk@464
   347
            case TABLE_COMMENT:
subslk@464
   348
                return PlsqlFoldTypes.TABLECOMMENT;
subslk@464
   349
            case COLUMN_COMMENT:
subslk@464
   350
                return PlsqlFoldTypes.COLUMNCOMMENT;
subslk@464
   351
            case COMMENT:
subslk@464
   352
                return PlsqlFoldTypes.COMMENT;
subslk@464
   353
            case PACKAGE:
subslk@464
   354
                return PlsqlFoldTypes.PACKAGE;
subslk@464
   355
            case PACKAGE_BODY:
subslk@464
   356
                return PlsqlFoldTypes.PACKAGEBODY;
subslk@464
   357
            case PROCEDURE_IMPL:
subslk@464
   358
                return PlsqlFoldTypes.PROCEDUREIMPL;
subslk@464
   359
            case FUNCTION_IMPL:
subslk@464
   360
                return PlsqlFoldTypes.FUNCTIONIMPL;
subslk@464
   361
            case PROCEDURE_DEF:
subslk@464
   362
                return PlsqlFoldTypes.PROCEDUREDEF;
subslk@464
   363
            case FUNCTION_DEF:
subslk@464
   364
                return PlsqlFoldTypes.FUNCTIONDEF;
subslk@464
   365
            case DECLARE_END:
subslk@464
   366
                return PlsqlFoldTypes.DECLAREEND;
subslk@464
   367
            case BEGIN_END:
subslk@464
   368
                return PlsqlFoldTypes.BEGINEND;
subslk@464
   369
            case TRIGGER:
subslk@464
   370
                return PlsqlFoldTypes.TRIGGER;
subslk@464
   371
            case IF:
subslk@464
   372
                return PlsqlFoldTypes.IF;
subslk@464
   373
            case CASE:
subslk@464
   374
                return PlsqlFoldTypes.CASE;
subslk@464
   375
            case WHILE_LOOP:
subslk@464
   376
                return PlsqlFoldTypes.WHILELOOP;
subslk@464
   377
            case FOR_LOOP:
subslk@464
   378
                return PlsqlFoldTypes.FORLOOP;
subslk@464
   379
            case LOOP:
subslk@464
   380
                return PlsqlFoldTypes.LOOP;
subslk@464
   381
            case CUSTOM_FOLD:
subslk@464
   382
                return PlsqlFoldTypes.CUSTOM;
subslk@464
   383
            case STATEMENT:
subslk@464
   384
                return PlsqlFoldTypes.STATEMENT;
subslk@464
   385
            case CURSOR:
subslk@464
   386
                return PlsqlFoldTypes.CURSOR;
subslk@464
   387
            case JAVA_SOURCE:
subslk@464
   388
                return PlsqlFoldTypes.JAVASOURCE;
subslk@464
   389
            default:
subslk@464
   390
                return null;
subslk@464
   391
        }
subslk@464
   392
    }
subslk@464
   393
subslk@464
   394
    /**
subslk@464
   395
     * Method that will return the fold description given the Plsql block Used
subslk@464
   396
     * when changing the descriptions only.
subslk@464
   397
     *
subslk@464
   398
     * @param block
subslk@464
   399
     * @return
subslk@464
   400
     */
subslk@464
   401
    private String getFoldDescription(final PlsqlBlock block) {
subslk@464
   402
        switch (block.getType()) {
subslk@464
   403
            case VIEW:
subslk@464
   404
                return block.getPrefix() + "VIEW " + block.getName();
subslk@464
   405
            case TABLE_COMMENT:
subslk@464
   406
                return "COMMENT ON TABLE " + block.getName();
subslk@464
   407
            case COLUMN_COMMENT:
subslk@464
   408
                return "COLUMN COMMENTS ON TABLE " + block.getName();
subslk@464
   409
            case COMMENT:
subslk@464
   410
                return block.getName();
subslk@464
   411
            case PACKAGE:
subslk@464
   412
                return block.getPrefix() + "PACKAGE " + block.getName();
subslk@464
   413
            case PACKAGE_BODY:
subslk@464
   414
                return block.getPrefix() + "PACKAGE BODY " + block.getName();
subslk@464
   415
            case PROCEDURE_IMPL:
subslk@464
   416
                return block.getPrefix() + "PROCEDURE IMPLEMENTATION " + block.getName();
subslk@464
   417
            case FUNCTION_IMPL:
subslk@464
   418
                return block.getPrefix() + "FUNCTION IMPLEMENTATION " + block.getName();
subslk@464
   419
            case PROCEDURE_DEF:
subslk@464
   420
                return "PROCEDURE DEFINITION " + block.getName();
subslk@464
   421
            case FUNCTION_DEF:
subslk@464
   422
                return "FUNCTION DEFINITION " + block.getName();
subslk@464
   423
            case DECLARE_END:
subslk@464
   424
                return "DECLARE BLOCK";
subslk@464
   425
            case BEGIN_END:
subslk@464
   426
                return "BEGIN BLOCK";
subslk@464
   427
            case TRIGGER:
subslk@464
   428
                return block.getPrefix() + "TRIGGER " + block.getName();
subslk@464
   429
            case IF:
subslk@464
   430
                return block.getName();
subslk@464
   431
            case CASE:
subslk@464
   432
                return block.getName();
subslk@464
   433
            case WHILE_LOOP:
subslk@464
   434
                return "WHILE " + block.getName();
subslk@464
   435
            case FOR_LOOP:
subslk@464
   436
                return "FOR " + block.getName();
subslk@464
   437
            case LOOP:
subslk@464
   438
                return "LOOP ";
subslk@464
   439
            case CUSTOM_FOLD:
subslk@464
   440
                return block.getName();
subslk@464
   441
            case STATEMENT:
subslk@464
   442
                return block.getPrefix() + block.getName();
subslk@464
   443
            case CURSOR:
subslk@464
   444
                return "CURSOR " + block.getName();
subslk@464
   445
            case JAVA_SOURCE:
subslk@464
   446
                return block.getPrefix() + "JAVA SOURCE";
subslk@464
   447
            default:
subslk@464
   448
                return "";
subslk@464
   449
        }
subslk@464
   450
    }
subslk@464
   451
subslk@464
   452
    private void removeFoldNotify(Fold removedFold) {
subslk@464
   453
        removedFoldList.add(removedFold);
subslk@464
   454
    }
subslk@464
   455
subslk@464
   456
    private void processRemovedFolds(FoldHierarchyTransaction transaction) {
subslk@464
   457
        for (Fold removedFold : removedFoldList) {
subslk@464
   458
            operation.removeFromHierarchy(removedFold, transaction);
subslk@464
   459
            if (LOG.isLoggable(Level.FINE)) {
subslk@464
   460
                LOG.log(Level.FINE, "Fold={0} removed={1}", new Object[]{removedFold, true});
subslk@464
   461
            }
subslk@464
   462
        }
subslk@464
   463
        removedFoldList.clear();
subslk@464
   464
    }
subslk@464
   465
subslk@464
   466
    private Document getDocument() {
subslk@464
   467
        Object obj = null;
subslk@464
   468
        for (int i = 0; i < 10; i++) {
subslk@464
   469
            obj = getOperation().getHierarchy().getComponent().getDocument();
subslk@464
   470
            if (obj instanceof AbstractDocument) {
subslk@464
   471
                return (Document) obj;
subslk@464
   472
            }
chrislovsund@355
   473
            try {
subslk@464
   474
                Thread.currentThread().sleep(i);
subslk@464
   475
            } catch (InterruptedException e) {
subslk@464
   476
            }
subslk@464
   477
        }
subslk@464
   478
        throw new IllegalStateException("[PLSQLFolding] PLSQLFoldManager.getDocument() NOT returned AbstractDocument, but " + obj.getClass() + "!. This is caused by not yet resolved issue #49497."); //NOI18N
subslk@464
   479
    }
chrislovsund@355
   480
subslk@464
   481
    private void updateFolds(final List<PlsqlBlock> blockHier, final FoldHierarchyTransaction transaction, final List<FoldSearchObject> collapsedFolds) throws BadLocationException {
subslk@464
   482
        final int count = blockHier.size();
subslk@464
   483
        Document doc = getDocument();
subslk@464
   484
        for (int i = 0; i < count; i++) {
subslk@464
   485
            final PlsqlBlock block = blockHier.get(i);
subslk@464
   486
            FoldType foldType = null;
subslk@464
   487
            final PlsqlBlockType type = block.getType();
subslk@464
   488
            String description = "";
subslk@464
   489
subslk@464
   490
            if (!(type == PlsqlBlockType.COMMENT && doc.getText(block.getStartOffset(), block.getEndOffset() - block.getStartOffset()).indexOf("\n") == -1)) { // check for single line comments
subslk@464
   491
                foldType = getFoldType(type);
subslk@464
   492
                description = getFoldDescription(block);
subslk@464
   493
subslk@464
   494
                if (doc.getEndPosition().getOffset() >= block.getEndOffset()) {                    
subslk@464
   495
                    operation.addToHierarchy(foldType, description, isCollapsed(block, foldType, collapsedFolds),
subslk@464
   496
                            block.getStartOffset(), block.getEndOffset(), 0, 0, null, transaction);
subslk@464
   497
                    //check for any child folds and add them also
subslk@464
   498
                    updateFolds(block.getChildBlocks(), transaction, collapsedFolds);
subslk@464
   499
                }
jrechtacek@0
   500
            }
subslk@464
   501
        }
subslk@464
   502
    }
jrechtacek@0
   503
subslk@464
   504
    /**
subslk@464
   505
     * Method that will select and return the corresponding fold to parent from
subslk@464
   506
     * oldRoot fold hierarchy
subslk@464
   507
     *
subslk@464
   508
     * @param parent
subslk@464
   509
     * @param foldInfoLst
subslk@464
   510
     * @return
subslk@464
   511
     */
subslk@464
   512
    private boolean isCollapsed(final PlsqlBlock block, final FoldType foldType, final List<FoldSearchObject> foldInfoLst) {
subslk@464
   513
        if (OptionsUtilities.isPlSqlExpandFolds()) {
subslk@464
   514
            return false;
subslk@464
   515
        }
subslk@464
   516
        if (foldInfoLst == null) {
subslk@464
   517
            return foldType == PlsqlFoldTypes.COMMENT;
subslk@464
   518
        }
subslk@464
   519
        final int size = foldInfoLst.size();
subslk@464
   520
        for (int i = 0; i < size; i++) {
subslk@464
   521
            final FoldSearchObject temp = foldInfoLst.get(i);
jrechtacek@0
   522
subslk@464
   523
            if ((temp.getFoldType() == foldType)
subslk@464
   524
                    && (temp.getStartOffset() == block.getPreviousStart())
subslk@464
   525
                    && (temp.getEndOffset() == block.getPreviousEnd())) {
subslk@464
   526
                return true;
subslk@464
   527
            }
subslk@464
   528
        }
chrislovsund@355
   529
subslk@464
   530
        return false;
subslk@464
   531
    }
chrislovsund@355
   532
subslk@464
   533
    /**
subslk@464
   534
     * Method that will return the relevant block factory
subslk@464
   535
     *
subslk@464
   536
     * @return
subslk@464
   537
     */
subslk@464
   538
    private PlsqlBlockFactory getBlockFactory() {
subslk@464
   539
        final Object obj = doc.getProperty(Document.StreamDescriptionProperty);
subslk@464
   540
        if (obj instanceof Lookup.Provider) {
subslk@464
   541
            return ((Lookup.Provider) obj).getLookup().lookup(PlsqlBlockFactory.class);
subslk@464
   542
        }
subslk@464
   543
        return null;
subslk@464
   544
    }
jrechtacek@0
   545
}