/******************************************************************************* * 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.ArrayList; 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.groovy.ast.expr.BinaryExpression; import org.codehaus.groovy.ast.expr.ClosureExpression; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.MethodCallExpression; import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.ast.stmt.BlockStatement; import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.ast.stmt.Statement; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResourceDelta; 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.DomainClass; import org.grails.ide.eclipse.editor.groovy.elements.GrailsProject; import org.grails.ide.eclipse.editor.groovy.elements.GrailsWorkspaceCore; /** * Manages the Named Criteria queries for domain classes in a project * @author Andrew Eisenberg * @created Nov 25, 2011 */ public class PerProjectNamedQueriesHolder implements IGrailsProjectInfo { private static final String[] NO_QUERIES = new String[0]; private IProject project; private Map<String, String[]> domainClassToQueries = new HashMap<String, String[]>();; public IProject getProject() { return project; } public void setProject(IProject project) { this.project = project; } 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.DOMAIN_CLASS) { foundRelevantChange = true; break; } } if (foundRelevantChange) { domainClassToQueries.clear(); } } } public String[] findNamedQueries(DomainClass domainClass) { if (domainClass.getGroovyClass() == null) { return NO_QUERIES; } String name = domainClass.getGroovyClass().getName(); String[] queries = domainClassToQueries.get(name); if (queries == null) { queries = ensureInitialized(domainClass.getGroovyClass()); synchronized (GrailsCore.get().getLockForProject(project)) { domainClassToQueries.put(name, queries); } } return queries; } private String[] ensureInitialized(ClassNode domainClass) { FieldNode field = domainClass.getField("namedQueries"); if (field != null && field.isStatic()) { Expression initialExpression = field.getInitialExpression(); if (initialExpression instanceof ClosureExpression) { Statement code = ((ClosureExpression) initialExpression).getCode(); if (code instanceof BlockStatement) { List<Statement> statements = ((BlockStatement) code).getStatements(); if (statements != null) { List<String> namedQueries = new ArrayList<String>(statements.size()); for (Statement s : statements) { if (s instanceof ExpressionStatement) { Expression expr = ((ExpressionStatement) s).getExpression(); if (expr instanceof MethodCallExpression) { MethodCallExpression call = (MethodCallExpression) expr; namedQueries.add(call.getMethodAsString()); } } } return namedQueries.toArray(NO_QUERIES); } } } } return NO_QUERIES; } public void dispose() { project = null; domainClassToQueries = null; } }