| /******************************************************************************* |
| * Copyright (c) 2012 Obeo. |
| |
| * 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: |
| * Obeo - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.mylyn.docs.intent.modelingunit.update; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.mylyn.docs.intent.collab.common.logger.IIntentLogger.LogType; |
| import org.eclipse.mylyn.docs.intent.collab.common.logger.IntentLogger; |
| import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.IntentCommand; |
| import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.ReadOnlyException; |
| import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.RepositoryAdapter; |
| import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.SaveException; |
| import org.eclipse.mylyn.docs.intent.core.compiler.CompilerPackage; |
| import org.eclipse.mylyn.docs.intent.core.compiler.ModelElementChangeStatus; |
| import org.eclipse.mylyn.docs.intent.core.compiler.ReferenceChangeStatus; |
| import org.eclipse.mylyn.docs.intent.core.compiler.StructuralFeatureChangeStatus; |
| import org.eclipse.mylyn.docs.intent.core.compiler.SynchronizerChangeState; |
| import org.eclipse.mylyn.docs.intent.core.compiler.SynchronizerCompilationStatus; |
| import org.eclipse.mylyn.docs.intent.core.document.IntentGenericElement; |
| import org.eclipse.mylyn.docs.intent.core.modelingunit.AbstractValue; |
| import org.eclipse.mylyn.docs.intent.core.modelingunit.ContributionInstruction; |
| import org.eclipse.mylyn.docs.intent.core.modelingunit.InstanciationInstruction; |
| import org.eclipse.mylyn.docs.intent.core.modelingunit.ModelingUnitInstructionReference; |
| import org.eclipse.mylyn.docs.intent.core.modelingunit.ModelingUnitPackage; |
| import org.eclipse.mylyn.docs.intent.core.modelingunit.StructuralFeatureAffectation; |
| |
| /** |
| * Utility which updates modeling units according to synchronization status. |
| * |
| * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> |
| */ |
| public class SyncStatusUpdater extends AbstractModelingUnitUpdater { |
| |
| /** |
| * Creates a modeling unit updater. |
| * |
| * @param repositoryAdapter |
| * the repository adapter |
| */ |
| public SyncStatusUpdater(RepositoryAdapter repositoryAdapter) { |
| super(repositoryAdapter); |
| } |
| |
| /** |
| * Initializes the match from a status. |
| * |
| * @param status |
| * the status |
| */ |
| private void initMatch(SynchronizerCompilationStatus status) { |
| Resource compiledResource = repositoryAdapter.getResource(status.getCompiledResourceURI()); |
| Resource workingCopyResource = resourceSet.getResource( |
| URI.createURI(status.getWorkingCopyResourceURI().replaceAll("\"", "")), true); |
| includeMatch(compiledResource, workingCopyResource); |
| } |
| |
| /** |
| * Fixes the given statuses by updating the given modeling unit. |
| * |
| * @param statusToFix |
| * the statuses to fix |
| */ |
| public void fixSynchronizationStatus(final SynchronizerCompilationStatus... statusToFix) { |
| repositoryAdapter.execute(new IntentCommand() { |
| public void execute() { |
| for (SynchronizerCompilationStatus status : statusToFix) { |
| initMatch(status); |
| switch (status.eClass().getClassifierID()) { |
| case CompilerPackage.MODEL_ELEMENT_CHANGE_STATUS: |
| fixModelElementChange((ModelElementChangeStatus)status); |
| break; |
| case CompilerPackage.ATTRIBUTE_CHANGE_STATUS: |
| case CompilerPackage.REFERENCE_CHANGE_STATUS: |
| fixStructuralFeatureChange((StructuralFeatureChangeStatus)status); |
| break; |
| default: |
| break; |
| } |
| } |
| try { |
| repositoryAdapter.save(); |
| } catch (ReadOnlyException e) { |
| IntentLogger.getInstance().log(LogType.ERROR, e.getMessage()); |
| } catch (SaveException e) { |
| IntentLogger.getInstance().log(LogType.ERROR, e.getMessage()); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * Fixes the given statuses by updating the given modeling unit. |
| * |
| * @param status |
| * the status to fix |
| */ |
| private void fixModelElementChange(ModelElementChangeStatus status) { |
| IntentGenericElement target = status.getTarget(); |
| switch (status.getChangeState().getValue()) { |
| case SynchronizerChangeState.WORKING_COPY_TARGET_VALUE: |
| EObject container = getContainer(target, ModelingUnitPackage.CONTRIBUTION_INSTRUCTION, |
| ModelingUnitPackage.INSTANCIATION_INSTRUCTION); |
| if (container instanceof ContributionInstruction) { |
| ContributionInstruction contribution = (ContributionInstruction)container; |
| container = contribution.getContributionReference().getReferencedInstruction(); |
| } |
| |
| if (container instanceof InstanciationInstruction) { |
| InstanciationInstruction instanciation = (InstanciationInstruction)container; |
| |
| // computes additions |
| EObject workingCopyObject = getWorkingCopyEObject(status |
| .getWorkingCopyElementURIFragment()); |
| |
| List<EObject> newObjects = new ArrayList<EObject>(); |
| for (Iterator<EObject> iterator = workingCopyObject.eAllContents(); iterator.hasNext();) { |
| newObjects.add(iterator.next()); |
| } |
| setNewObjects(newObjects); |
| |
| StructuralFeatureAffectation affectation = generateSingleAffectation( |
| workingCopyObject.eContainingFeature(), workingCopyObject); |
| if (affectation != null) { |
| instanciation.getStructuralFeatures().add(affectation); |
| } |
| } |
| break; |
| case SynchronizerChangeState.COMPILED_TARGET_VALUE: |
| IntentGenericElement affectation = getContainer(target, |
| ModelingUnitPackage.STRUCTURAL_FEATURE_AFFECTATION); |
| if (affectation != null) { |
| removeFromContainer(affectation); |
| } else if (target instanceof InstanciationInstruction) { |
| // in this case, the instanciation is not contained by the affectation so we need to |
| // remove it separately |
| InstanciationInstruction instanciation = (InstanciationInstruction)target; |
| ModelingUnitInstructionReference reference = query |
| .getModelingUnitInstructionReference(instanciation); |
| if (reference != null) { |
| removeFromContainer(reference); |
| } |
| removeFromContainer(instanciation); |
| } |
| // TODO remove related contributions |
| // TODO remove related references |
| break; |
| default: |
| IntentLogger.getInstance().log( |
| LogType.INFO, |
| "UNSUPPORTED MODEL ELEMENT CHANGE: " + status.getMessage() + '(' |
| + status.getChangeState() + ')'); |
| break; |
| } |
| } |
| |
| /** |
| * Fixes the given statuses. |
| * |
| * @param status |
| * the status to fix |
| */ |
| private void fixStructuralFeatureChange(StructuralFeatureChangeStatus status) { |
| EObject element = getWorkingCopyEObject(status.getWorkingCopyElementURIFragment()); |
| EStructuralFeature feature = element.eClass().getEStructuralFeature(status.getFeatureName()); |
| Object newValue = null; |
| if (status instanceof ReferenceChangeStatus) { |
| // in case of collections, we only want the value related to the status |
| newValue = getWorkingCopyEObject(((ReferenceChangeStatus)status) |
| .getWorkingCopyTargetURIFragment()); |
| } |
| |
| if (newValue == null) { |
| newValue = element.eGet(feature); |
| } |
| |
| switch (status.getChangeState().getValue()) { |
| case SynchronizerChangeState.UPDATE_VALUE: |
| if (status.getTarget() instanceof AbstractValue) { |
| if (newValue == null) { |
| EObject affectation = getContainer(status.getTarget(), |
| ModelingUnitPackage.STRUCTURAL_FEATURE_AFFECTATION); |
| if (affectation instanceof StructuralFeatureAffectation) { |
| removeFromContainer((StructuralFeatureAffectation)affectation); |
| } |
| } else { |
| setValue((AbstractValue)status.getTarget(), newValue); |
| } |
| } else if (status.getTarget() instanceof InstanciationInstruction) { |
| addAffectations(status.getTarget(), generateAffectations(feature, newValue)); |
| } |
| break; |
| |
| case SynchronizerChangeState.COMPILED_TARGET_VALUE: |
| EObject affectation = getContainer(status.getTarget(), |
| ModelingUnitPackage.STRUCTURAL_FEATURE_AFFECTATION); |
| if (affectation instanceof StructuralFeatureAffectation) { |
| removeFromContainer((StructuralFeatureAffectation)affectation); |
| } |
| break; |
| |
| case SynchronizerChangeState.WORKING_COPY_TARGET_VALUE: |
| IntentGenericElement container = getContainer(status.getTarget(), |
| ModelingUnitPackage.CONTRIBUTION_INSTRUCTION, |
| ModelingUnitPackage.INSTANCIATION_INSTRUCTION); |
| addAffectations(container, generateAffectations(feature, newValue)); |
| break; |
| |
| default: |
| IntentLogger.getInstance().log(LogType.INFO, |
| "UNSUPPORTED CHANGE: " + status.getMessage() + " (" + status.getChangeState() + ')'); |
| break; |
| } |
| } |
| |
| /** |
| * Adds the given affectation in the container. |
| * |
| * @param container |
| * the container |
| * @param affectations |
| * the affectation |
| */ |
| private void addAffectations(IntentGenericElement container, |
| List<StructuralFeatureAffectation> affectations) { |
| if (container instanceof ContributionInstruction) { |
| ContributionInstruction contribution = (ContributionInstruction)container; |
| contribution.getContributions().addAll(affectations); |
| } else if (container instanceof InstanciationInstruction) { |
| InstanciationInstruction instanciation = (InstanciationInstruction)container; |
| instanciation.getStructuralFeatures().addAll(affectations); |
| } |
| } |
| |
| } |