blob: 0c26f4fc29c8052c4f1f1f87970567bf4d1c90d8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2008 Oracle. 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:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.core.internal.resource.java;
import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jpt.core.JpaAnnotationProvider;
import org.eclipse.jpt.core.ResourceModelListener;
import org.eclipse.jpt.core.internal.AbstractResourceModel;
import org.eclipse.jpt.core.resource.java.JavaResourceModel;
import org.eclipse.jpt.core.resource.java.JpaCompilationUnit;
import org.eclipse.jpt.core.utility.jdt.AnnotationEditFormatter;
import org.eclipse.jpt.utility.CommandExecutorProvider;
import org.eclipse.jpt.utility.internal.BitTools;
// TODO we need access to the JPA platform
public class JavaResourceModelImpl
extends AbstractResourceModel
implements JavaResourceModel
{
private final Collection<ResourceModelListener> resourceModelListeners;
private final JpaCompilationUnit jpaCompilationUnit;
public JavaResourceModelImpl(
IFile file, JpaAnnotationProvider annotationProvider,
CommandExecutorProvider modifySharedDocumentCommandExecutorProvider,
AnnotationEditFormatter annotationEditFormatter) {
super(file);
this.resourceModelListeners = new ArrayList<ResourceModelListener>();
// TODO use JPA factory, via the platform
this.jpaCompilationUnit =
new JpaCompilationUnitImpl(file, annotationProvider, modifySharedDocumentCommandExecutorProvider, annotationEditFormatter, this);
}
public String getResourceType() {
return JAVA_RESOURCE_TYPE;
}
public JpaCompilationUnit getJpaCompilationUnit() {
return this.jpaCompilationUnit;
}
public void addResourceModelChangeListener(ResourceModelListener listener) {
if (listener == null) {
throw new IllegalArgumentException("Listener cannot be null");
}
if (this.resourceModelListeners.contains(listener)) {
throw new IllegalArgumentException("Listener " + listener + " already added");
}
this.resourceModelListeners.add(listener);
}
public void removeResourceModelChangeListener(ResourceModelListener listener) {
if (!this.resourceModelListeners.contains(listener)) {
throw new IllegalArgumentException("Listener " + listener + " was never added");
}
this.resourceModelListeners.add(listener);
}
public void resourceChanged() {
if (this.jpaCompilationUnit == null) {
throw new IllegalStateException("Change events should not be fired during construction");
}
for (ResourceModelListener listener : this.resourceModelListeners) {
listener.resourceModelChanged();
}
}
public void javaElementChanged(ElementChangedEvent event) {
synchWithJavaDelta(event.getDelta());
}
private void synchWithJavaDelta(IJavaElementDelta delta) {
switch (delta.getElement().getElementType()) {
case IJavaElement.JAVA_PROJECT :
if (this.updateOnClasspathChanges(delta)) {
break;
}
case IJavaElement.JAVA_MODEL :
case IJavaElement.PACKAGE_FRAGMENT_ROOT :
case IJavaElement.PACKAGE_FRAGMENT :
this.synchChildrenWithJavaDelta(delta);
break;
case IJavaElement.COMPILATION_UNIT :
this.synchCompilationUnitWithJavaDelta(delta);
break;
default :
break; // the event is somehow lower than a compilation unit
}
}
private void synchChildrenWithJavaDelta(IJavaElementDelta delta) {
for (IJavaElementDelta child : delta.getAffectedChildren()) {
this.synchWithJavaDelta(child); // recurse
}
}
private void synchCompilationUnitWithJavaDelta(IJavaElementDelta delta) {
// ignore changes to/from primary working copy - no content has changed;
// and make sure there are no other flags set that indicate both a change to/from
// primary working copy AND content has changed
if (BitTools.onlyFlagIsSet(delta.getFlags(), IJavaElementDelta.F_PRIMARY_WORKING_COPY)) {
return;
}
if (delta.getKind() == IJavaElementDelta.REMOVED) {
//we get the java notification for removal before we get the resource notification.
//we do not need to handle this event and will get exceptions building an astRoot if we try.
return;
}
if (delta.getElement().equals(this.jpaCompilationUnit.getCompilationUnit())) {
//TODO possibly hop on the UI thread here so that we know only 1 thread is changing our model
this.jpaCompilationUnit.updateFromJava();
}
}
//bug 235384 - we need to update all compilation units when a classpath change occurs.
//The persistence.jar could have been added/removed from the classpath which affects
//whether we know about the jpa annotations or not.
private boolean updateOnClasspathChanges(IJavaElementDelta delta) {
if (BitTools.flagIsSet(delta.getFlags(), IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) ||
BitTools.flagIsSet(delta.getFlags(), IJavaElementDelta.F_CLASSPATH_CHANGED)) {
this.jpaCompilationUnit.updateFromJava();
return true;
}
return false;
}
public void resolveTypes() {
this.jpaCompilationUnit.resolveTypes();
}
}