blob: 835636c48b219120cc95239c88077f8f54e4eafd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2006 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.common.internal.emf.resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.wst.common.internal.emf.utilities.IDUtil;
public class ReferencedXMIResourceImpl extends CompatibilityXMIResourceImpl implements ReferencedResource {
//TODO Add toString hook
private static final String TO_STRING = "ReferencedXMIResource, file = "; //$NON-NLS-1$
private static final String READ_COUNT_TO_STRING = " R= "; //$NON-NLS-1$
private static final String WRITE_COUNT_TO_STRING = " W= "; //$NON-NLS-1$
private int readReferenceCount = 1;
private int editReferenceCount = 0;
protected boolean isNew = true;
protected boolean forceRefresh;
public static class ESynchronizedAdapterList extends EAdapterList
{
public ESynchronizedAdapterList(Notifier notifier) {
super(notifier);
}
public synchronized boolean add(Object object)
{
return super.add(object);
}
public synchronized void add(int index, Object object)
{
super.add(index, object);
}
public synchronized boolean addAll(Collection collection)
{
return super.addAll(collection);
}
public synchronized boolean remove(Object object)
{
return super.remove(object);
}
public synchronized Object remove(int index)
{
return super.remove(index);
}
public synchronized boolean removeAll(Collection collection)
{
return super.removeAll(collection);
}
public synchronized void clear()
{
super.clear();
}
public synchronized Object set(int index, Object object)
{
return super.set(index, object);
}
public synchronized void move(int newPosition, Object object)
{
super.move(newPosition, object);
}
public synchronized Object move(int newPosition, int oldPosition)
{
return super.move(newPosition, oldPosition);
}
}
/**
* ReferencableXMIResourceImpl constructor comment.
*/
public ReferencedXMIResourceImpl() {
super();
}
public ReferencedXMIResourceImpl(URI uri) {
super(uri);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.common.internal.emf.resource.ReferencedResource#getReadCount()
*/
public int getReadCount() {
return readReferenceCount;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.common.internal.emf.resource.ReferencedResource#getWriteCount()
*/
public int getWriteCount() {
return editReferenceCount;
}
/*
* @see ReferencedResource#accessForRead
*/
public void accessForRead() {
checkDeleted();
if (!isNew())
readReferenceCount++;
isNew = false;
}
/*
* @see ReferencedResource#accessForWrite
*/
public void accessForWrite() {
checkDeleted();
editReferenceCount++;
if (isNew)
releaseFromRead();
isNew = false;
if (!isTrackingModification())
setTrackingModification(true);
}
/*
* Check if this resource has been removed and throw an exception if it does not have a
* ResourceSet.
*/
protected void checkDeleted() {
if (getResourceSet() == null)
throw new RuntimeException(DELETED_ERROR_MSG);
}
/**
*
*/
public void collectContainedObjects(java.util.List collecting, EObject parentObject) {
java.util.Iterator children = parentObject.eContents().iterator();
while (children.hasNext()) {
EObject child = (EObject) children.next();
collecting.add(child);
collectContainedObjects(collecting, child);
}
}
/**
*
*/
public void ensureFullIDHydration() {
List allRefObjects = new ArrayList();
Iterator rootObjects = getContents().iterator();
while (rootObjects.hasNext()) {
EObject child = (EObject) rootObjects.next();
allRefObjects.add(child);
collectContainedObjects(allRefObjects, child);
}
Iterator iter = allRefObjects.iterator();
while (iter.hasNext())
IDUtil.assignID((EObject) iter.next(), this);
}
/**
* If the resource is no longer being accessed, then remove it from the resource set.
*/
public void unloadIfNecessary() {
if ((getTotalReferenceCount() <= 0) || (editReferenceCount <= 0 && isModified()))
unload();
}
/**
* Return the number of write accesses to this resource.
*
* @return int The number of references.
*/
protected int getTotalReferenceCount() {
return editReferenceCount + readReferenceCount;
}
/*
* @see ReferencedResource#isNew
*/
public boolean isNew() {
return isNew;
}
/*
* @see ReferencedResource#isReadOnly
*/
public boolean isReadOnly() {
return editReferenceCount <= 0;
}
/*
* @see ReferencedResource#isShared
*/
public boolean isShared() {
return getTotalReferenceCount() > 1;
}
/*
* @see ReferencedResource#isSharedForWrite
*/
public boolean isSharedForWrite() {
return editReferenceCount > 1;
}
/**
* @see ReferencedResource#preDelete
*/
public void preDelete() {
}
/*
* @see ReferencedResource#releaseFromRead
*/
public void releaseFromRead() {
readReferenceCount--;
if (readReferenceCount < 0)
throw new RuntimeException("Read reference count error: " + this.toString()); //$NON-NLS-1$
unloadIfNecessary();
}
/*
* @see ReferencedResource#releaseFromWrite
*/
public void releaseFromWrite() {
editReferenceCount--;
if (editReferenceCount < 0)
throw new RuntimeException("Write reference count error: " + this.toString()); //$NON-NLS-1$
unloadIfNecessary();
}
/*
* @see ReferencedResource#saveIfNecessary
*/
public void saveIfNecessary() throws Exception {
if (!isSharedForWrite()) // caller is the only referencer
save(Collections.EMPTY_MAP);
}
public String toString() {
return TO_STRING + getURI().toString() + READ_COUNT_TO_STRING + new Integer(readReferenceCount) + WRITE_COUNT_TO_STRING + new Integer(editReferenceCount);
}
/*
* @see ReferencedResource#needsToSave()
*/
public boolean needsToSave() {
return isModified() && !isSharedForWrite();
}
/**
* @see ReferencedResource#setForceRefresh(boolean)
*/
public void setForceRefresh(boolean b) {
forceRefresh = b;
}
/**
* @see ReferencedResource#shouldForceRefresh()
*/
public boolean shouldForceRefresh() {
return forceRefresh;
}
protected void basicDoLoad(InputStream arg0, Map arg1) throws IOException {
boolean isTrackingMods = isTrackingModification();
try {
if (isTrackingMods)
setTrackingModification(false);
super.basicDoLoad(arg0, arg1);
} finally {
if (isTrackingMods)
setTrackingModification(true);
}
}
/**
* @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#doUnload()
*/
protected void doUnload() {
if (isTrackingModification() && editReferenceCount < 1) //do not turn off modification if
// we still have a write count
setTrackingModification(false);
super.doUnload();
setForceRefresh(false);
setModified(false); //dcb - this is required to ensure that resources without files are
// marked as not modified.
if (readReferenceCount == 0 && editReferenceCount == 0) {
getResourceSet().getResources().remove(this);
}
}
/**
* The resource has been unloaded, and there are no references. Treat the resource like a new
* Resource
*/
// never used
// private void resetAsNew() {
// readReferenceCount = 1;
// isNew = true;
// }
/**
* @see org.eclipse.emf.ecore.resource.Resource#save(Object)
*/
public void save(Map options) throws IOException {
notifyAboutToSave();
try {
super.save(options);
} catch (Exception e) {
notifySaveFailed();
if (e instanceof IOException)
throw (IOException) e;
else
Logger.getLogger().write(e);
}
notifySaved();
}
protected void notifySaved() {
notifySaveEvent(RESOURCE_WAS_SAVED);
}
protected void notifyAboutToSave() {
notifySaveEvent(RESOURCE_ABOUT_TO_SAVE);
}
protected void notifySaveFailed() {
notifySaveEvent(RESOURCE_SAVE_FAILED);
}
private void notifySaveEvent(int eventType) {
if (eNotificationRequired()) {
Notification notification =
new NotificationImpl(eventType, this, this)
{
public Object getNotifier()
{
return ReferencedXMIResourceImpl.this;
}
public int getFeatureID(Class expectedClass)
{
return eventType;
}
};
eNotify(notification);
}
}
/**
* @see com.ibm.etools.emf.workbench.ReferencedResource#wasReverted()
*/
public boolean wasReverted() {
return false;
}
public EList eAdapters()
{
if (eAdapters == null)
{
eAdapters = new ESynchronizedAdapterList(this);
}
return eAdapters;
}
}