/** * Copyright (c) 2011-2012 Eclipse contributors 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 */ package org.eclipse.emf.ecore.xcore.ui.contentassist; import java.util.List; import org.eclipse.emf.codegen.ecore.genmodel.GenFeature; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.xcore.XReference; import org.eclipse.emf.ecore.xcore.XcorePackage; import org.eclipse.emf.ecore.xcore.mappings.XcoreMapper; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.xtext.conversion.IValueConverter; import org.eclipse.xtext.naming.IQualifiedNameConverter; import org.eclipse.xtext.nodemodel.INode; import org.eclipse.xtext.nodemodel.util.NodeModelUtils; import org.eclipse.xtext.resource.IEObjectDescription; import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.ui.editor.contentassist.ConfigurableCompletionProposal; import org.eclipse.xtext.ui.editor.contentassist.ReplacementTextApplier; public class OppositeReplacementTextApplier extends ReplacementTextApplier { protected XReference xReference; protected ITextViewer viewer; protected IScope scope; protected XcoreMapper mapper; protected IQualifiedNameConverter qualifiedNameConverter; protected IValueConverter<String> qualifiedNameValueConverter; public OppositeReplacementTextApplier( XReference xReference, ITextViewer viewer, IScope scope, XcoreMapper mapper, IQualifiedNameConverter qualifiedNameConverter, IValueConverter<String> qualifiedNameValueConverter) { this.xReference = xReference; this.viewer = viewer; this.scope = scope; this.mapper = mapper; this.qualifiedNameConverter = qualifiedNameConverter; this.qualifiedNameValueConverter = qualifiedNameValueConverter; } @Override public void apply(IDocument document, ConfigurableCompletionProposal proposal) throws BadLocationException { String replacementString = getActualReplacementString(proposal); proposal.setCursorPosition(replacementString.length()); int replacementOffset = proposal.getReplacementOffset(); IEObjectDescription oppositeDescription = scope.getSingleElement(qualifiedNameConverter.toQualifiedName(qualifiedNameValueConverter.toValue( replacementString, null))); EObject opposite = oppositeDescription.getEObjectOrProxy(); if (opposite instanceof GenFeature && opposite.eResource() == xReference.eResource()) { XReference oppositeXReference = (XReference)mapper.getToXcoreMapping(opposite).getXcoreElement(); if (oppositeXReference.getOpposite() == null) { List<INode> nodes = NodeModelUtils.findNodesForFeature(oppositeXReference, XcorePackage.Literals.XNAMED_ELEMENT__NAME); if (!nodes.isEmpty()) { INode node = nodes.get(nodes.size() - 1); int offset = node.getOffset(); String oppositeReplacement = " opposite " + qualifiedNameValueConverter.toString(xReference.getName()); if (replacementOffset > offset) { document.replace(replacementOffset, proposal.getReplacementLength(), replacementString); document.replace(offset + node.getLength(), 0, oppositeReplacement); } else { document.replace(offset + node.getLength(), 0, oppositeReplacement); document.replace(replacementOffset, proposal.getReplacementLength(), replacementString); } return; } } } document.replace(replacementOffset, proposal.getReplacementLength(), replacementString); } @Override public String getActualReplacementString(ConfigurableCompletionProposal proposal) { return proposal.getReplacementString(); } }