/******************************************************************************* * Copyright (c) 2012 Pivotal Software, Inc. * 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: * Pivotal Software, Inc. - initial API and implementation *******************************************************************************/ package org.grails.ide.eclipse.editor.groovy.types; import java.util.HashMap; import java.util.List; import java.util.Map; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.FieldNode; import org.codehaus.jdt.groovy.model.GroovyCompilationUnit; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.grails.ide.eclipse.core.GrailsCoreActivator; import org.grails.ide.eclipse.core.internal.plugins.GrailsCore; import org.grails.ide.eclipse.core.internal.plugins.GrailsElementKind; import org.grails.ide.eclipse.core.internal.plugins.IGrailsProjectInfo; import org.grails.ide.eclipse.editor.groovy.elements.GrailsProject; import org.grails.ide.eclipse.editor.groovy.elements.GrailsWorkspaceCore; /** * Caches {@link ClassNode}s that correspond to grails services * @since 2.6.0 */ public class PerProjectServiceCache implements IGrailsProjectInfo { private Map<String, ClassNode> serviceCache; private IProject project; private IJavaProject javaProject; public void dispose() { synchronized (GrailsCore.get().getLockForProject(project)) { project = null; javaProject = null; serviceCache = null; } } public IProject getProject() { return project; } /** * The cache is flushed when the classpath changes or there is a refresh dependencies */ public void projectChanged(GrailsElementKind[] changeKinds, IResourceDelta change) { synchronized (GrailsCore.get().getLockForProject(project)) { boolean foundRelevantChange = false; for (GrailsElementKind changeKind : changeKinds) { if (changeKind == GrailsElementKind.PROJECT || changeKind == GrailsElementKind.CLASSPATH || changeKind == GrailsElementKind.SERVICE_CLASS) { foundRelevantChange = true; break; } } if (foundRelevantChange) { // also remvoe references to service classes in the // type cache PerProjectTypeCache typeCache = GrailsCore.get().connect(project, PerProjectTypeCache.class); if (serviceCache != null) { for (ClassNode serviceClass : serviceCache.values()) { typeCache.clearFromCache(serviceClass.getName()); } serviceCache = null; } } } } public void setProject(IProject project) { this.project = project; this.javaProject = JavaCore.create(project); } public Map<String, ClassNode> findServicesFor(List<FieldNode> fields) { ensureInitialized(); Map<String, ClassNode> existingServices = new HashMap<String, ClassNode>(); for (FieldNode field : fields) { String name = field.getName(); ClassNode serviceClass = serviceCache.get(name); if (serviceClass != null) { existingServices.put(name, serviceClass); } } return existingServices; } private void ensureInitialized() { if (serviceCache == null) { try { serviceCache = GrailsWorkspaceCore.get().create(javaProject).findAllServices(); } catch (JavaModelException e) { GrailsCoreActivator.log(e); } } } /** * Not API!!! For testing only * * @param type specify that this type is a service. */ public void addService(GroovyCompilationUnit unit, String name) { ensureInitialized(); List<ClassNode> classes = unit.getModuleNode().getClasses(); ClassNode service = null; for (ClassNode clazz : classes) { if (clazz.getNameWithoutPackage().equals(name)) { service = clazz; } } if (service == null) { throw new IllegalArgumentException("Could not find '" + name + "' class in module"); //$NON-NLS-1$ //$NON-NLS-2$ } serviceCache.put(GrailsProject.getBeanName(unit.getType(name)), service); } public Map<String, ClassNode> getAllServices() { ensureInitialized(); return serviceCache; } }