blob: 1364e97639eee59be7c69e25f74f2fa4838b14c3 [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2007 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute and Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Please visit http://www.objectteams.org for updates and contact.
*
* Contributors:
* Fraunhofer FIRST - Initial API and implementation
* Technical University Berlin - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.internal.refactoring.adaptor;
import java.util.Collection;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractMethodMappingDeclaration;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CallinMappingDeclaration;
import org.eclipse.jdt.core.dom.CalloutMappingDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.RoleTypeDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.objectteams.otdt.core.ICallinMapping;
import org.eclipse.objectteams.otdt.core.ICalloutMapping;
import org.eclipse.objectteams.otdt.core.ICalloutToFieldMapping;
import org.eclipse.objectteams.otdt.core.IOTJavaElement;
import org.eclipse.objectteams.otdt.core.IOTType;
import org.eclipse.objectteams.otdt.internal.refactoring.corext.OTRefactoringCoreMessages;
import org.eclipse.objectteams.otdt.internal.ui.assist.BaseImportRewriting;
// org.eclipse.jdt.core.manipulation:
import base org.eclipse.jdt.core.manipulation.ImportReferencesCollector;
// org.eclipse.jdt.ui
import base org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgPolicyFactory.SubCuElementReorgPolicy;
import base org.eclipse.jdt.internal.corext.refactoring.reorg.ReadOnlyResourceFinder;
import base org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils;
import base org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
import base org.eclipse.jdt.internal.corext.refactoring.structure.ImportRewriteUtil;
/**
* The team adapts classes from corext.refactoring.{reorg,structure}.
*
* @role OTASTNodeSearchUtil belongs to this team
* in order to facilitate access to state role methods.
*/
@SuppressWarnings({ "restriction", "decapsulation" })
public team class ReorgAdaptor
{
protected class SubCuElementReorgPolicy playedBy SubCuElementReorgPolicy
{
// ========= Callouts: =========
abstract void copyMemberToDestination(IMember member, CompilationUnitRewrite targetRewriter, CompilationUnit sourceCuNode, CompilationUnit targetCuNode, BodyDeclaration newMember)
throws JavaModelException;
copyMemberToDestination -> copyMemberToDestination;
abstract static String getUnindentedSource(ISourceReference sourceReference)
throws JavaModelException;
getUnindentedSource -> getUnindentedSource;
IJavaElement getJavaElementDestination() -> IJavaElement getJavaElementDestination();
// ======== Overrides =========
// this callin dispatches on the element being moved:
copyToDestination <- replace copyToDestination;
@SuppressWarnings("basecall")
callin void copyToDestination(IJavaElement element, CompilationUnitRewrite targetRewriter, CompilationUnit sourceCuNode, CompilationUnit targetCuNode)
throws CoreException
{
AbstractMethodMappingDeclaration newMapping= null;
IMember mapping= null;
switch(element.getElementType()){
// treat OT java model elements
case IOTJavaElement.CALLIN_MAPPING:
mapping= (IMember)element;
newMapping= (CallinMappingDeclaration)targetRewriter.getASTRewrite().createStringPlaceholder(getUnindentedSource(mapping), ASTNode.CALLIN_MAPPING_DECLARATION);
break;
case IOTJavaElement.CALLOUT_MAPPING:
mapping= (IMember)element;
newMapping= (CalloutMappingDeclaration)targetRewriter.getASTRewrite().createStringPlaceholder(getUnindentedSource(mapping), ASTNode.CALLOUT_MAPPING_DECLARATION);
break;
case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
mapping= (IMember)element;
newMapping= (CalloutMappingDeclaration)targetRewriter.getASTRewrite().createStringPlaceholder(getUnindentedSource(mapping), ASTNode.CALLOUT_MAPPING_DECLARATION);
break;
case IOTJavaElement.TEAM:
case IOTJavaElement.ROLE:
element= ((IOTType)element).getCorrespondingJavaElement();
// fall through with real java element
default:
base.copyToDestination(element, targetRewriter, sourceCuNode, targetCuNode);
return;
}
// callout which is again callin-intercepted:
copyMemberToDestination(mapping, targetRewriter, sourceCuNode, targetCuNode, newMapping);
}
// this callin dispatches on the DnD-target:
getDestinationNode <- replace getDestinationNode;
@SuppressWarnings("basecall")
callin ASTNode getDestinationNode(IJavaElement destination, CompilationUnit target)
throws JavaModelException
{
switch (destination.getElementType()) {
case IOTJavaElement.CALLIN_MAPPING:
return OTASTNodeSearchUtil.getCallinMappingDeclarationNode((ICallinMapping)destination, target);
case IOTJavaElement.CALLOUT_MAPPING:
return OTASTNodeSearchUtil.getCalloutMappingDeclarationNode((ICalloutMapping)destination, target);
case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
return OTASTNodeSearchUtil.getCalloutToFieldMappingDeclarationNode((ICalloutToFieldMapping)destination, target);
case IOTJavaElement.TEAM:
case IOTJavaElement.ROLE:
destination = (((IOTType)destination).getCorrespondingJavaElement());
// fall through with real java element
default:
return base.getDestinationNode(destination, target);
}
}
}
protected class ReadOnlyResourceFinder playedBy ReadOnlyResourceFinder
{
@SuppressWarnings("basecall")
static callin boolean hasReadOnlyResourcesAndSubResources(IJavaElement javaElement)
throws CoreException
{
switch(javaElement.getElementType()){
// consider OT-specific elements
case IOTJavaElement.TEAM:
case IOTJavaElement.ROLE:
case IOTJavaElement.CALLIN_MAPPING:
case IOTJavaElement.CALLOUT_MAPPING:
case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
return false;
default:
return base.hasReadOnlyResourcesAndSubResources(javaElement);
}
}
boolean hasReadOnlyResourcesAndSubResources(IJavaElement javaElement)
<- replace boolean hasReadOnlyResourcesAndSubResources(IJavaElement javaElement);
}
final static int[] OT_MEMBERS = new int[]{IOTJavaElement.CALLIN_MAPPING, IOTJavaElement.CALLOUT_MAPPING, IOTJavaElement.CALLOUT_TO_FIELD_MAPPING};
/** Patch a few hard coded switch statements in ReorgUtils. */
protected class ReorgUtils playedBy ReorgUtils {
boolean hasOnlyExpectedOrOTTypes(int[] types) <- replace boolean hasOnlyElementsOfType(IJavaElement[] javaElements, int[] types)
with { types <- types }
static callin boolean hasOnlyExpectedOrOTTypes(int[] types) {
// pseudo switch: base uses set comparison.
if (types[0] == IJavaElement.FIELD) {
// when expecting fields also accept ot members:
int l= types.length;
int[] newTypes = new int[l+OT_MEMBERS.length];
System.arraycopy(types, 0, newTypes, 0, l);
System.arraycopy(OT_MEMBERS, 0, newTypes, l, OT_MEMBERS.length);
return base.hasOnlyExpectedOrOTTypes(newTypes);
}
return base.hasOnlyExpectedOrOTTypes(types);
}
String createNamePattern(IJavaElement element)
<- replace String createNamePattern(IJavaElement element);
@SuppressWarnings("basecall")
static callin String createNamePattern(IJavaElement element)
throws JavaModelException
{
switch (element.getElementType()) {
case IOTJavaElement.TEAM:
return OTRefactoringCoreMessages.getString("ReorgUtils.21"); //$NON-NLS-1$
case IOTJavaElement.ROLE:
return OTRefactoringCoreMessages.getString("ReorgUtils.23"); //$NON-NLS-1$
case IOTJavaElement.CALLOUT_MAPPING:
return OTRefactoringCoreMessages.getString("ReorgUtils.24"); //$NON-NLS-1$
case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:
return OTRefactoringCoreMessages.getString("ReorgUtils.25"); //$NON-NLS-1$
case IOTJavaElement.CALLIN_MAPPING:
return OTRefactoringCoreMessages.getString("ReorgUtils.26"); //$NON-NLS-1$
default:
return base.createNamePattern(element);
}
}
// createNameArguments now uses JavaElementLabels.getElementLabel()
// nothing to adapt in ReorgUtils.
}
/**
* When reorg updates a CU's imports, activate additional analysis
* for creating base imports if needed.
*/
protected class ImportRewriteUtil playedBy ImportRewriteUtil {
void addImports(CompilationUnitRewrite rewrite, ImportRewriteContext context)
<- replace
void addImports(CompilationUnitRewrite rewrite,
ImportRewriteContext context, ASTNode node,
Map<Name, String> typeImports, Map<Name, String> staticImports,
Collection<IBinding> excludeBindings, boolean declarations);
static callin void addImports(CompilationUnitRewrite rewrite, ImportRewriteContext context) {
within (new BaseImporting(rewrite))
base.addImports(rewrite, context);
}
}
/**
* Mediate between {@link org.eclipse.jdt.internal.corext.codemanipulation.ImportReferencesCollector}
* and our {@link BaseImportRewriting} (from <code>org.eclipse.objectteams.otdt.jdt.ui</code>).
* This team is activated only temporarily when reorg is adding imports.
*
* @since 2.1
*/
protected team class BaseImporting {
ImportRewrite rewrite;
public BaseImporting(CompilationUnitRewrite rewrite) {
this.rewrite = rewrite.getImportRewrite();
}
protected class BaseImportReferencesCollector playedBy ImportReferencesCollector {
void typeRefFound(Name node) <- after void typeRefFound(Name node)
base when (node != null);
private void typeRefFound(Name node) {
SimpleName name = (node instanceof QualifiedName)
? ((QualifiedName)node).getName()
: (SimpleName)node;
String baseName = name.getIdentifier();
// find this type's location in parent:
ASTNode parent = node.getParent();
StructuralPropertyDescriptor location = node.getLocationInParent();
while (parent instanceof Type) {
location = parent.getLocationInParent();
parent = parent.getParent();
}
// if its the reference in a playedBy clause ...
@SuppressWarnings("deprecation")
StructuralPropertyDescriptor baseClassProperty = (node.getAST().apiLevel() == AST.JLS2)
? RoleTypeDeclaration.BASECLASS_PROPERTY
: RoleTypeDeclaration.BASECLASS_TYPE_PROPERTY;
if (location == baseClassProperty)
// ... let BaseImportRewriting know that it may need a base import:
BaseImportRewriting.instance().markForBaseImport(rewrite, baseName);
}
}
}
}