content: /*
   * Copyright 2016 the original author or authors.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.github.alexfalappa.nbspringboot.navigator;
  
  import javax.swing.SwingUtilities;
  
  import org.netbeans.api.java.source.CancellableTask;
  import org.netbeans.api.java.source.CompilationInfo;
  import org.netbeans.api.java.source.JavaSource;
  import org.netbeans.api.java.source.support.LookupBasedJavaSourceTaskFactory;
  import org.netbeans.swing.etable.ETable;
  import org.openide.filesystems.FileObject;
  import org.openide.util.Lookup;
  import org.openide.util.Utilities;
  
  import com.sun.source.tree.CompilationUnitTree;
  import com.sun.source.util.TreePath;
  
  /**
   * This factory triggers the scanning of compilation units. If it is active, it uses the {@link ElementScanningTask}, otherwise an
   * empty task.
   *
   * @author Michael J. Simons, 2016-09-16
   * @author Alessandro Falappa
   */
  public class ElementScanningTaskFactory extends LookupBasedJavaSourceTaskFactory {
  
      /**
       * This task uses the {@link MappedElementExtractor} to scan the current compilation unit for mapped elements.
       *
       * @author Michael J. Simons, 2016-09-16
       */
      static class ElementScanningTask implements CancellableTask<CompilationInfo> {
  
          private final ETable table;
          private final MappedElementsModel targetModel;
          private MappedElementExtractor mappedElementExtractor;
  
          public ElementScanningTask(ETable table, MappedElementsModel targetModel) {
              this.table = table;
              this.targetModel = targetModel;
          }
  
          @Override
          public void cancel() {
              if (mappedElementExtractor != null) {
                  mappedElementExtractor.cancel();
                  mappedElementExtractor = null;
              }
          }
  
          @Override
          public void run(CompilationInfo p) throws Exception {
              final CompilationUnitTree compilationUnitTree = p.getCompilationUnit();
              final TreePath rootPath = new TreePath(compilationUnitTree);
              mappedElementExtractor = new MappedElementExtractor(p.getFileObject(), compilationUnitTree, p.getTrees(), rootPath);
              SwingUtilities.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                      targetModel.refresh(compilationUnitTree.accept(mappedElementExtractor, null));
                      table.setModel(targetModel);
                  }
              });
          }
      }
  
      private final CancellableTask<CompilationInfo> EMPTY_TASK = new CancellableTask<CompilationInfo>() {
          @Override
          public void cancel() {
          }
  
          @Override
          public void run(CompilationInfo parameter) throws Exception {
          }
      };
      private final ETable table;
      private final MappedElementsModel mappedElementsModel;
      private volatile boolean active = false;
  
      public ElementScanningTaskFactory(final ETable table, final MappedElementsModel mappedElementsModel) {
          super(JavaSource.Phase.PARSED, JavaSource.Priority.NORMAL);
          this.table = table;
          this.mappedElementsModel = mappedElementsModel;
      }
  
      public void activate() {
          active = true;
          setLookup(Utilities.actionsGlobalContext());
      }
  
      public void deactivate() {
          active = false;
          setLookup(Lookup.EMPTY);
      }
  
      @Override
      protected CancellableTask<CompilationInfo> createTask(final FileObject fo) {
          return active ? new ElementScanningTask(table, mappedElementsModel) : EMPTY_TASK;
      }
  }
  