blob: b0efa83c3f2ef6f7f410f3fa318db0fa7752bfa4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017, 2018 EclipseSource Services GmbH 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:
* Philip Langer - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.fallback;
import com.google.common.collect.Lists;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.core.resources.IEncodedStorage;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIPlugin;
import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.TextFallbackCompareViewerCreator;
import org.eclipse.emf.compare.ide.ui.internal.logical.StorageTypedElement;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.team.internal.ui.mapping.AbstractCompareInput;
import org.eclipse.team.internal.ui.mapping.CompareInputChangeNotifier;
import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
/**
* A highly specialized implementation of a compare input that uses {@link TextFallbackCompareInputData text
* input data} to manage the information about the ancestor, left, and right.
*/
@SuppressWarnings("restriction")
public final class TextFallbackCompareInput extends AbstractCompareInput {
/**
* The text input data representation the underlying sides of the input.
*/
private final TextFallbackCompareInputData textInputData;
/**
* The compare input change notifier used by {@link #getChangeNotifier()}.
*/
private final CompareInputChangeNotifier compareInputChangeNotifier = new CompareInputChangeNotifier() {
@Override
protected IResource[] getResources(ICompareInput input) {
return getResources();
}
/**
* Returns an array of resources containing each of{@link #originStorage}, {@link #leftStorage}, and
* {@link #rightStorage} that is an {@link IResource}.
*
* @return an array of the underlying resources of the sides.
* @see
*/
public IResource[] getResources() {
List<IResource> resources = Lists.newArrayList();
if (textInputData.getOriginStorage() instanceof IResource) {
resources.add((IResource)textInputData.getOriginStorage());
}
if (textInputData.getLeftStorage() instanceof IResource) {
resources.add((IResource)textInputData.getLeftStorage());
}
if (textInputData.getRightStorage() instanceof IResource) {
resources.add((IResource)textInputData.getRightStorage());
}
return resources.toArray(new IResource[resources.size()]);
}
};
/**
* Creates an instance of the given kind, using the given text input data, and an indication of whether
* this input is for {@link TextFallbackCompareViewerCreator#SHOW_PREVIEW preview mode}.
*
* @param kind
* the kind of input.
* @param textInputData
* the text input data for this input.
* @param showPreview
* whether this is input for preview mode.
*/
public TextFallbackCompareInput(int kind, TextFallbackCompareInputData textInputData,
boolean showPreview) {
super(kind,
getElement(textInputData.getOriginTypedElement(), textInputData.getOriginResource(),
showPreview),
getElement(textInputData.getLeftTypedElement(), textInputData.getLeftResource(), showPreview),
getElement(textInputData.getRightTypedElement(), textInputData.getRightResource(),
showPreview));
this.textInputData = textInputData;
}
/**
* Returns a transformed typed element appropriate for the given resource and the specified preview mode.
*
* @param typedElement
* the typed element to transform.
* @param resource
* the resource used during the transformation.
* @param showPreview
* whether the result should be used for preview mode.
* @return a transformed typed element, or the original.
*/
private static ITypedElement getElement(ITypedElement typedElement, Resource resource,
boolean showPreview) {
// If we want preview mode and we have a local resource typed element, and the resource is an XML
// resource...
if (showPreview && typedElement instanceof LocalResourceTypedElement
&& resource instanceof XMLResource) {
LocalResourceTypedElement localResourceTypedElement = (LocalResourceTypedElement)typedElement;
final IResource localResource = localResourceTypedElement.getResource();
final XMLResource xmlResource = (XMLResource)resource;
// Create storage that will use the local resource's path information, but fetches contents by
// serializing the XML resource.
IEncodedStorage storage = new EncodedStorage(localResource, xmlResource);
// Created a new storage typed element for the storage.
return new StorageTypedElement(storage, localResource.getFullPath().toString());
}
return typedElement;
}
/**
* {@inheritDoc}
* <p>
* This implementation does nothing.
* </p>
*
* @see AbstractCompareInput#update()
*/
@Override
public void update() {
}
/**
* {@inheritDoc}
* <p>
* This implementation always returns {@code false}.
* </p>
*
* @see AbstractCompareInput#needsUpdate()
*/
@Override
public boolean needsUpdate() {
return false;
}
/**
* {@inheritDoc}
* <p>
* This implementation always returns {@link #compareInputChangeNotifier}.
* </p>
*
* @see AbstractCompareInput#getChangeNotifier()
*/
@Override
protected CompareInputChangeNotifier getChangeNotifier() {
return compareInputChangeNotifier;
}
public TextFallbackCompareInputData getTextInputData() {
return textInputData;
}
private static final class EncodedStorage implements IEncodedStorage {
private final IResource localResource;
private final XMLResource xmlResource;
private EncodedStorage(IResource localResource, XMLResource xmlResource) {
this.localResource = localResource;
this.xmlResource = xmlResource;
}
// Don't use getAdapter(Class<T>) for compatibility with Luna
public Object getAdapter(Class adapter) {
return null;
}
public boolean isReadOnly() {
return true;
}
public String getName() {
return localResource.getName();
}
public IPath getFullPath() {
return localResource.getFullPath();
}
public InputStream getContents() throws CoreException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
xmlResource.save(byteArrayOutputStream, new LinkedHashMap<>());
} catch (IOException e) {
EMFCompareIDEUIPlugin.getDefault().log(e);
}
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
public String getCharset() throws CoreException {
return xmlResource.getEncoding();
}
}
}