Package org.springframework.ide.eclipse.core.java

Source Code of org.springframework.ide.eclipse.core.java.SuperTypeHierarchyCache

/*******************************************************************************
* Copyright (c) 2007, 2009 Spring IDE Developers
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.core.java;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.ITypeHierarchyChangedListener;
import org.eclipse.jdt.core.JavaModelException;

/**
* Cache for {@link ITypeHierarchy} instances.
* <p>
* The implementation has been taken from {@link org.eclipse.jdt.internal.corext.util.SuperTypeHierarchyCache}.
* @author Christian Dupuis
* @since 2.0.1
*/
public class SuperTypeHierarchyCache {

  /**
   * Internal cache entry
   */
  private static class HierarchyCacheEntry implements ITypeHierarchyChangedListener {

    private long lastAccess;

    private ITypeHierarchy typeHierarchy;

    public HierarchyCacheEntry(ITypeHierarchy hierarchy) {
      typeHierarchy = hierarchy;
      typeHierarchy.addTypeHierarchyChangedListener(this);
      markAsAccessed();
    }

    public void dispose() {
      typeHierarchy.removeTypeHierarchyChangedListener(this);
      typeHierarchy = null;
    }

    public long getLastAccess() {
      return lastAccess;
    }

    public ITypeHierarchy getTypeHierarchy() {
      return typeHierarchy;
    }

    public void markAsAccessed() {
      lastAccess = System.currentTimeMillis();
    }

    public void typeHierarchyChanged(ITypeHierarchy typeHierarchy) {
      removeHierarchyEntryFromCache(this);
    }
  }

  private static final int CACHE_SIZE = 50;

  private static List<HierarchyCacheEntry> HIERACHY_CACHE = new ArrayList<HierarchyCacheEntry>(CACHE_SIZE);

  private static void addTypeHierarchyToCache(ITypeHierarchy hierarchy) {
    synchronized (HIERACHY_CACHE) {
      int nEntries = HIERACHY_CACHE.size();
      if (nEntries >= CACHE_SIZE) {
        // find obsolete entries or remove entry that was least recently
        // accessed
        HierarchyCacheEntry oldest = null;
        List<HierarchyCacheEntry> obsoleteHierarchies = new ArrayList<HierarchyCacheEntry>(CACHE_SIZE);
        for (int i = 0; i < nEntries; i++) {
          HierarchyCacheEntry entry = (HierarchyCacheEntry) HIERACHY_CACHE.get(i);
          ITypeHierarchy curr = entry.getTypeHierarchy();
          if (!curr.exists() || hierarchy.contains(curr.getType())) {
            obsoleteHierarchies.add(entry);
          }
          else {
            if (oldest == null || entry.getLastAccess() < oldest.getLastAccess()) {
              oldest = entry;
            }
          }
        }
        if (!obsoleteHierarchies.isEmpty()) {
          for (int i = 0; i < obsoleteHierarchies.size(); i++) {
            removeHierarchyEntryFromCache((HierarchyCacheEntry) obsoleteHierarchies.get(i));
          }
        }
        else if (oldest != null) {
          removeHierarchyEntryFromCache(oldest);
        }
      }
      HierarchyCacheEntry newEntry = new HierarchyCacheEntry(hierarchy);
      HIERACHY_CACHE.add(newEntry);
    }
  }

  private static ITypeHierarchy findTypeHierarchyInCache(IType type) {
    synchronized (HIERACHY_CACHE) {
      for (int i = HIERACHY_CACHE.size() - 1; i >= 0; i--) {
        HierarchyCacheEntry curr = (HierarchyCacheEntry) HIERACHY_CACHE.get(i);
        ITypeHierarchy hierarchy = curr.getTypeHierarchy();
        if (!hierarchy.exists()) {
          removeHierarchyEntryFromCache(curr);
        }
        else {
          if (hierarchy.contains(type)) {
            curr.markAsAccessed();
            return hierarchy;
          }
        }
      }
    }
    return null;
  }

  /**
   * Get the {@link ITypeHierarchy} for the given {@link IType}.
   * <p>
   * If no hierarchy can be found in the cache a new one will be created.
   * <p>
   * Calling this method is equivalent to calling {@link #getTypeHierarchy(IType, null)}.
   * @param type the {@link IType} to get the super type hierarchy for
   * @return the {@link ITypeHierarchy} for the given <code>type</code>
   */
  public static ITypeHierarchy getTypeHierarchy(IType type) throws JavaModelException {
    return getTypeHierarchy(type, null);
  }

  /**
   * Get the {@link ITypeHierarchy} for the given {@link IType}.
   * <p>
   * If no hierarchy can be found in the cache a new one will be created.
   * @param type the {@link IType} to get the super type hierarchy for
   * @param progressMonitor a {@link IProgressMonitor} instance to report progress
   * @return the {@link ITypeHierarchy} for the given <code>type</code>
   */
  public static ITypeHierarchy getTypeHierarchy(IType type, IProgressMonitor progressMonitor)
      throws JavaModelException {
    ITypeHierarchy hierarchy = findTypeHierarchyInCache(type);
    if (hierarchy == null) {
      hierarchy = type.newTypeHierarchy(progressMonitor);
      addTypeHierarchyToCache(hierarchy);
    }
    return hierarchy;
  }

  /**
   * Checks if a {@link ITypeHierarchy} for a given {@link IType} is in the internal cache.
   * @param type the {@link IType} to check if a {@link ITypeHierarchy} is cached
   * @return true if a {@link ITypeHierarchy} is cached
   */
  public static boolean hasInCache(IType type) {
    return findTypeHierarchyInCache(type) != null;
  }

  private static void removeHierarchyEntryFromCache(HierarchyCacheEntry entry) {
    synchronized (HIERACHY_CACHE) {
      entry.dispose();
      HIERACHY_CACHE.remove(entry);
    }
  }
}
TOP

Related Classes of org.springframework.ide.eclipse.core.java.SuperTypeHierarchyCache

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.