diff options
Diffstat (limited to 'plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewSetImpl.java')
-rw-r--r-- | plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewSetImpl.java | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewSetImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewSetImpl.java new file mode 100644 index 0000000000..abbd800759 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewSetImpl.java @@ -0,0 +1,314 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2008 Eike Stepper, Germany. + * 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: + * Simon McDuff - initial API and implementation + * Simon McDuff - http://bugs.eclipse.org/246619 + **************************************************************************/ +package org.eclipse.emf.internal.cdo; + +import org.eclipse.emf.cdo.CDOView; +import org.eclipse.emf.cdo.CDOViewSet; +import org.eclipse.emf.cdo.common.CDOProtocolConstants; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.eresource.impl.CDOResourceFactoryImpl; +import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl; +import org.eclipse.emf.cdo.util.CDOURIUtil; + +import org.eclipse.emf.internal.cdo.bundle.OM; +import org.eclipse.emf.internal.cdo.util.CDOViewSetPackageRegistryImpl; +import org.eclipse.emf.internal.cdo.util.FSMUtil; + +import org.eclipse.emf.common.notify.Adapter; +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.notify.impl.NotifierImpl; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.Resource.Factory.Registry; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +/** + * @author Simon McDuff + * @since 2.0 + */ +public class CDOViewSetImpl extends NotifierImpl implements CDOViewSet, Adapter +{ + private Set<CDOViewImpl> views = new HashSet<CDOViewImpl>(); + + private Map<String, CDOViewImpl> mapOfViews = new HashMap<String, CDOViewImpl>(); + + private ResourceSet resourceSet; + + private CDOResourceFactoryImpl resourceFactory = new CDOResourceFactoryImpl(this); + + private CDOViewSetPackageRegistryImpl packageRegistry = new CDOViewSetPackageRegistryImpl(this); + + public CDOViewSetImpl() + { + } + + public ResourceSet getResourceSet() + { + return resourceSet; + } + + public EPackage.Registry getPackageRegistry() + { + return packageRegistry; + } + + public CDOResourceFactoryImpl getResourceFactory() + { + return resourceFactory; + } + + public CDOView[] getViews() + { + synchronized (views) + { + return views.toArray(new CDOView[views.size()]); + } + } + + /** + * @throws IllegalArgumentException + * if repositoryUUID doesn't match any CDOView. + */ + public CDOViewImpl resolveUUID(String repositoryUUID) + { + CDOViewImpl view = null; + + synchronized (views) + { + view = mapOfViews.get(repositoryUUID); + + if (view == null) + { + if (repositoryUUID != null) + { + throw new IllegalArgumentException("Cannot find associate CDOView for reposUUID " + repositoryUUID); + } + + if (mapOfViews.size() == 1) + { + return views.iterator().next(); + } + + if (mapOfViews.size() == 0) + { + return null; + } + + throw new IllegalStateException("Don't know which CDOView to take since no authority has been specified"); + } + } + return view; + } + + public CDOViewImpl getView(String repositoryUUID) + { + synchronized (views) + { + return mapOfViews.get(repositoryUUID); + } + } + + public void add(CDOViewImpl view) + { + synchronized (views) + { + CDOView lookupView = mapOfViews.get(view.getSession().getRepositoryUUID()); + if (lookupView != null) + { + throw new RuntimeException("Only one view/transaction per repository can be open for the same resource set"); + } + + views.add(view); + mapOfViews.put(view.getSession().getRepositoryUUID(), view); + + if (views.size() == 1) + { + initializeResources(view); + } + } + + if (eNotificationRequired()) + { + NotificationImpl notification = new NotificationImpl(NotificationImpl.ADD, null, view); + eNotify(notification); + } + } + + private void initializeResources(CDOView cdoView) + { + // Intialize the resourceset correctly when it get connected to the first time to a view. + for (Resource resource : resourceSet.getResources()) + { + if (resource instanceof CDOResourceImpl) + { + CDOResourceImpl cdoResource = (CDOResourceImpl)resource; + if (cdoResource.cdoView() == null) + { + URI newURI = CDOURIUtil.createResourceURI(cdoView, cdoResource.getPath()); + cdoResource.setURI(newURI); + notifyAdd(cdoResource); + } + } + } + } + + public void remove(CDOViewImpl view) + { + List<Resource> resToRemove = new ArrayList<Resource>(); + synchronized (views) + { + // It is important to remove view from the list first. It is the way we can differentiate close and detach. + views.remove(view); + mapOfViews.remove(view.getSession().getRepositoryUUID()); + + for (Resource resource : getResourceSet().getResources()) + { + if (resource instanceof CDOResource) + { + CDOResource cdoRes = (CDOResource)resource; + if (cdoRes.cdoView() == view) + { + resToRemove.add(resource); + } + } + } + } + + getResourceSet().getResources().removeAll(resToRemove); + if (eNotificationRequired()) + { + NotificationImpl notification = new NotificationImpl(NotificationImpl.REMOVE, view, null); + eNotify(notification); + } + } + + public Notifier getTarget() + { + return resourceSet; + } + + public void setTarget(Notifier newTarget) + { + if (resourceSet != null) + { + throw new IllegalStateException("Cannot associate more than 1 resourceset to this viewset"); + } + if (isAdapterForType(newTarget)) + { + resourceSet = (ResourceSet)newTarget; + EPackage.Registry oldPackageRegistry = resourceSet.getPackageRegistry(); + resourceSet.setPackageRegistry(getPackageRegistry()); + for (Entry<String, Object> entry : oldPackageRegistry.entrySet()) + { + getPackageRegistry().put(entry.getKey(), entry.getValue()); + } + Registry registry = resourceSet.getResourceFactoryRegistry(); + Map<String, Object> map = registry.getProtocolToFactoryMap(); + map.put(CDOProtocolConstants.PROTOCOL_NAME, getResourceFactory()); + } + else + { + throw new IllegalArgumentException("Doesn't support " + newTarget); + } + } + + public boolean isAdapterForType(Object type) + { + return type instanceof ResourceSet; + } + + @SuppressWarnings("unchecked") + public void notifyChanged(Notification notification) + { + try + { + switch (notification.getEventType()) + { + case Notification.ADD: + if (notification.getNewValue() instanceof CDOResourceImpl) + { + notifyAdd((CDOResourceImpl)notification.getNewValue()); + } + break; + + case Notification.ADD_MANY: + { + List<Resource> newResources = (List<Resource>)notification.getNewValue(); + for (Resource newResource : newResources) + { + if (newResource instanceof CDOResourceImpl) + { + notifyAdd((CDOResourceImpl)newResource); + } + } + } + break; + + case Notification.REMOVE: + if (notification.getOldValue() instanceof CDOResourceImpl) + { + notifyRemove((CDOResourceImpl)notification.getOldValue()); + } + break; + + case Notification.REMOVE_MANY: + { + List<Resource> resources = (List<Resource>)notification.getOldValue(); + for (Resource oldResource : resources) + { + if (oldResource instanceof CDOResourceImpl) + { + notifyRemove((CDOResourceImpl)oldResource); + } + } + } + break; + } + } + catch (RuntimeException ex) + { + OM.LOG.error(ex); + throw ex; + } + } + + /** + * Only generates event to CDOView if it is a new CDOResource. + */ + private void notifyAdd(CDOResourceImpl resourceImpl) + { + CDOViewImpl view = resolveUUID(resourceImpl.getURI().authority()); + if (view != null && FSMUtil.isTransient(resourceImpl)) + { + view.toTransaction().attach(resourceImpl); + } + } + + /** + * + */ + private void notifyRemove(CDOResourceImpl resourceImpl) + { + // Don't do anything + } +} |