/****************************************************************************** * Copyright (c) 2010-2013, Linagora * * 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: * Linagora - initial API and implementation *******************************************************************************/ package com.ebmwebsourcing.petals.services.su.refactoring; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.CompositeChange; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.TextFileChange; import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; import org.eclipse.ltk.core.refactoring.resource.RenameResourceChange; import com.ebmwebsourcing.petals.common.internal.provisional.refactoring.MavenProjectRefactoringExtension; import com.ebmwebsourcing.petals.common.internal.provisional.refactoring.PetalsRefactoringBean; import com.ebmwebsourcing.petals.common.internal.provisional.utils.PetalsConstants; import com.ebmwebsourcing.petals.common.internal.provisional.utils.PetalsRefactoringUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.ResourceUtils; import com.ebmwebsourcing.petals.services.utils.ServiceProjectRelationUtils; /** * A refactoring handler for SU projects. * <p> * There are two aspects: * </p> * <ul> * <li>The project is renamed. It impacts the SU's POM, and SA projects (POM + jbi.xml).</li> * <li> * The project must respect the SU naming convention, and contain a service name. * This second aspect may impact several kinds of files, depending on the options. * <ul> * <li>The jbi.xml and the WSDL files are impacted by default (just the service name).</li> * <li>If derived names must be updated, then any text containing the service name will be refactored.</li> * <li>If the references must be updated, then this replacement is extended to all the files in the "src" directory.</li> * </ul> * </li> * </ul> * * @author Vincent Zurczak - EBM WebSourcing */ public class RefactoringExtensionForSu extends MavenProjectRefactoringExtension { public final static String UPDATE_SERVICE_NAME = "update_the service_name"; public final static String UPDATE_DERIVED_NAMES = "update_the _derived_names"; /** * Creates the changes in a SU project. * <p> * The following policy is applied: * </p> * <ul> * <li>The project name is updated in all the files of the "src" directory.</li> * <li>If the service name must be updated, it us updated in all the files of the "src" directory.</li> * <li>If derived names must be updated, then all the files are introspected.</li> * <li>Note that the last options are exclusive: it is either one, or the other.</li> * </ul> * * @see com.ebmwebsourcing.petals.common.internal.provisional.refactoring.MavenProjectRefactoringExtension * #createChange(org.eclipse.core.runtime.IProgressMonitor) */ @Override public Change createChange( IProgressMonitor pm ) throws CoreException, OperationCanceledException { // FIXME: do we need to use the progress monitor? See with important files (e.g. BPEL projects) // Get the information to make decisions CompositeChange compositeChange = new CompositeChange( "Intermediary" ); List<Change> resourceChangesList = new ArrayList<Change> (); Boolean updateserviceName = getInfo().getOptions().get( UPDATE_SERVICE_NAME ); Boolean updateDerivations = getInfo().getOptions().get( UPDATE_DERIVED_NAMES ); // Store reusable values String oldServiceName = null; String newServiceName = null; String quotedOldProjectName = Pattern.quote( getInfo().getProject().getName()); // Build the replacements List<PetalsRefactoringBean> beans = new ArrayList<PetalsRefactoringBean> (); PetalsRefactoringBean projectBean = new PetalsRefactoringBean(); projectBean.setLeftRegex( null ); projectBean.setRightRegex( null ); projectBean.setRegex( quotedOldProjectName ); projectBean.setNewValue( getInfo().getNewName()); beans.add( projectBean ); if( updateserviceName ) { oldServiceName = getServiceName( getInfo().getProject().getName()); newServiceName = getServiceName( getInfo().getNewName()); if( ! oldServiceName.equals( newServiceName )) { PetalsRefactoringBean serviceBean = new PetalsRefactoringBean(); serviceBean.setLeftRegex( updateDerivations ? null : "\\W" ); serviceBean.setRightRegex( updateDerivations ? null : "\\W" ); serviceBean.setRegex( Pattern.quote( oldServiceName )); serviceBean.setNewValue( newServiceName ); beans.add( serviceBean ); } } // For all the files in the "src" directory... IContainer container = getInfo().getProject().getFolder( "src" ); for( IFile file : ResourceUtils.getFiles( "*", Arrays.asList( container ))) { // Text file changes TextFileChange textFileChange = PetalsRefactoringUtils.buildTextFileChange( file, beans ); if( textFileChange != null ) compositeChange.add( textFileChange ); // Update a file name too? // => project name RenameResourceChange resourceChange = renameResource( file, quotedOldProjectName, getInfo().getNewName()); if( resourceChange != null ) resourceChangesList.add( resourceChange ); // => Derivation if( updateDerivations ) { resourceChange = renameResource( file, oldServiceName, newServiceName ); if( resourceChange != null ) resourceChangesList.add( resourceChange ); } } // SA appear at the end of the changes list. // SA projects are only impacted by the project name for( IProject project : getInfo().getProject().getReferencingProjects()) { if( project.isAccessible() && ServiceProjectRelationUtils.isSaProject( project )) { // Update the jbi.xml and the POM IFile[] files = new IFile[] { project.getFile( PetalsConstants.LOC_JBI_FILE ), project.getFile( PetalsConstants.LOC_POM_FILE ) }; // Update them for( IFile file : files ) { if( ! file.exists()) continue; TextFileChange textFileChange = PetalsRefactoringUtils.buildTextFileChange( file, Pattern.quote( getInfo().getProject().getName()), null, null, getInfo().getNewName()); if( textFileChange != null ) compositeChange.add( textFileChange ); } } } // Add the resource changes at the end (easier to read) for( Change change : resourceChangesList ) compositeChange.add( change ); return compositeChange; } /* * (non-Javadoc) * @see com.ebmwebsourcing.petals.common.internal.provisional.refactoring.MavenProjectRefactoringExtension * #determineEnablement() */ @Override public void determineEnablement() { boolean enabled = ServiceProjectRelationUtils.isSuProject( getInfo().getProject()); setEnabled( enabled ); } /* * (non-Javadoc) * @see com.ebmwebsourcing.petals.common.internal.provisional.refactoring.MavenProjectRefactoringExtension * #checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor, * org.eclipse.ltk.core.refactoring.RefactoringStatus, * org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext) */ @Override public void checkFinalConditions( IProgressMonitor pm, RefactoringStatus status, CheckConditionsContext context ) throws CoreException, OperationCanceledException { // nothing } /* * (non-Javadoc) * @see com.ebmwebsourcing.petals.common.internal.provisional.refactoring.MavenProjectRefactoringExtension * #checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor, * org.eclipse.ltk.core.refactoring.RefactoringStatus) */ @Override public void checkInitialConditions( IProgressMonitor pm, RefactoringStatus status ) throws CoreException, OperationCanceledException { // nothing } /** * Gets the service name from a SU name. * @param suName * @return */ private String getServiceName( String suName ) { String serviceName = suName; int index = serviceName.lastIndexOf( '-' ); if( index > 0 ) serviceName = serviceName.substring( 0, index ); index = serviceName.lastIndexOf( '-' ); if( index > 0 && index != serviceName.length()) serviceName = serviceName.substring( index + 1 ); return serviceName; } /** * Checks whether a resource should be renamed. * <p> * This method checks whether changing the service name impacts the file name. * If so, a resource change is returned (null otherwise). * </p> * * @param file the file that may have to be renamed * @param oldServiceName the old service name (quoted) * @param newServiceName the new service name * @return a rename resource change if the file must be renamed, null otherwise */ private RenameResourceChange renameResource( IFile file, String oldServiceName, String newServiceName ) { RenameResourceChange resourceChange = null; // Replace the resource with the new project name if( oldServiceName != null && newServiceName != null ) { String newName = file.getName().replaceAll( oldServiceName, newServiceName ); if( ! newName.equals( file.getName())) { resourceChange = new RenameResourceChange( file.getFullPath(), newName ); } } return resourceChange; } }