blob: 4519cc03e463e998141e894e97dd531b8f743ba0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.j2ee.jpa.refactoring.rename;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.LiteralTree;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import org.netbeans.api.java.source.CancellableTask;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.TreeMaker;
import org.netbeans.api.java.source.TreePathHandle;
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.modules.j2ee.jpa.refactoring.EntityAnnotationReference;
import org.netbeans.modules.j2ee.jpa.refactoring.EntityAssociationResolver;
import org.netbeans.modules.j2ee.jpa.refactoring.RefactoringUtil;
import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
import org.netbeans.modules.j2ee.persistence.api.PersistenceScope;
import org.netbeans.modules.j2ee.persistence.api.PersistenceScopes;
import org.netbeans.modules.j2ee.persistence.api.metadata.orm.EntityMappingsMetadata;
import org.netbeans.modules.refactoring.api.Problem;
import org.netbeans.modules.refactoring.api.RenameRefactoring;
import org.netbeans.modules.refactoring.java.spi.JavaRefactoringPlugin;
import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
import org.openide.filesystems.FileObject;
import org.openide.text.PositionBounds;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
/**
* Handles renaming of properties that are referenced by
* the mappedBy attribute.
*
* @author Erno Mononen
*/
public class EntityRename extends JavaRefactoringPlugin {
private final RenameRefactoring rename;
private TreePathHandle treePathHandle;
public EntityRename(RenameRefactoring rename) {
this.rename = rename;
try {
this.treePathHandle = RefactoringUtil.resolveTreePathHandle(rename);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
@Override
public Problem preCheck() {
return null;
}
@Override
public Problem fastCheckParameters() {
return null;
}
@Override
public Problem checkParameters() {
return null;
}
@Override
protected JavaSource getJavaSource(Phase p) {
return null;
}
private PersistenceScope getPersistenceScope() {
if (treePathHandle == null) {
return null;
}
Project project = FileOwnerQuery.getOwner(treePathHandle.getFileObject());
if (project == null) {
return null;
}
PersistenceScopes scopes = PersistenceScopes.getPersistenceScopes(project);
if (scopes == null) {
return null; // project of this type doesn't provide a list of persistence scopes
}
if (scopes.getPersistenceScopes().length == 0) {
return null;
}
return scopes.getPersistenceScopes()[0];
}
private MetadataModel<EntityMappingsMetadata> getEntityMappingsModel() {
PersistenceScope scope = getPersistenceScope();
// XXX should retrieve the model for each PU (see the javadoc of the
// the scope#getEMM(String) method), but it is currently not supported
// by the persistence scope implementations.
return scope != null ? scope.getEntityMappingsModel(null) : null;
}
@Override
public Problem prepare(RefactoringElementsBag refactoringElementsBag) {
MetadataModel<EntityMappingsMetadata> emModel = getEntityMappingsModel();
if (emModel == null) {
return null;
}
EntityAssociationResolver resolver = new EntityAssociationResolver(treePathHandle, emModel);
try {
List<EntityAnnotationReference> references = resolver.resolveReferences();
for (EntityAnnotationReference ref : references) {
EntityRenameElement element = new EntityRenameElement(ref, rename);
refactoringElementsBag.add(rename, element);
}
} catch (IOException ioe) {
Exceptions.printStackTrace(ioe);
}
return null;
}
private static class EntityRenameElement extends SimpleRefactoringElementImplementation {
private final RenameRefactoring rename;
private final EntityAnnotationReference reference;
public EntityRenameElement(EntityAnnotationReference reference, RenameRefactoring rename) {
this.reference = reference;
this.rename = rename;
}
@Override
public String getText() {
return getDisplayText();
}
@Override
public String getDisplayText() {
Object[] args = new Object[]{reference.getHandle().getFileObject().getNameExt(), reference.getAttributeValue(), rename.getNewName()};
return MessageFormat.format(NbBundle.getMessage(EntityRename.class, "TXT_EntityAnnotationRename"), args);
}
@Override
public void performChange() {
try {
JavaSource source = JavaSource.forFileObject(reference.getHandle().getFileObject());
source.runModificationTask(new CancellableTask<WorkingCopy>() {
@Override
public void cancel() {
}
@Override
public void run(WorkingCopy workingCopy) throws Exception {
workingCopy.toPhase(JavaSource.Phase.RESOLVED);
Element element = reference.getHandle().resolveElement(workingCopy);
for (AnnotationMirror annotation : element.getAnnotationMirrors()) {
if (!annotation.getAnnotationType().toString().equals(reference.getAnnotation())) {
continue;
}
Map<? extends ExecutableElement, ? extends AnnotationValue> values = annotation.getElementValues();
TreeMaker make = workingCopy.getTreeMaker();
AnnotationTree oldAt = (AnnotationTree) workingCopy.getTrees().getTree(element, annotation);
List<? extends ExpressionTree> arguments = oldAt.getArguments();
ArrayList<ExpressionTree> newArguments = new ArrayList<ExpressionTree>();
for (ExpressionTree argument : arguments) {
ExpressionTree tmp = argument;
if (argument instanceof AssignmentTree) {
AssignmentTree assignment = (AssignmentTree) argument;
ExpressionTree expression = assignment.getExpression();
ExpressionTree variable = assignment.getVariable();
if (expression instanceof LiteralTree) {
LiteralTree literal = (LiteralTree) expression;
String value = literal.getValue().toString();
if (reference.getAttributeValue().equals(value)) {
tmp = make.Assignment(variable, make.Literal(rename.getNewName()));
}
}
}
newArguments.add(tmp);
}
TypeElement typeElement = workingCopy.getElements().getTypeElement(reference.getAnnotation());
AnnotationTree newAt = make.Annotation(make.QualIdent(typeElement), newArguments);
workingCopy.rewrite(oldAt, newAt);
}
}
}).commit();
} catch (IOException ioe) {
Exceptions.printStackTrace(ioe);
}
}
@Override
public Lookup getLookup() {
return Lookups.singleton(reference.getHandle().getFileObject());
}
@Override
public FileObject getParentFile() {
return reference.getHandle().getFileObject();
}
@Override
public PositionBounds getPosition() {
return null;
}
}
}