package il.co.topq.refactor.refactorUtil;
import il.co.topq.refactor.infra.ConfigurationHandler;
import il.co.topq.refactor.infra.MyClassLoader;
import il.co.topq.refactor.model.JSystemProject;
import il.co.topq.refactor.model.MultipleScenarioSuiteFile;
import il.co.topq.refactor.model.ScenarioPairFiles;
import il.co.topq.refactor.model.ScenarioPropertiesFile;
import il.co.topq.refactor.model.ScenarioXMLFile;
import il.co.topq.refactor.utils.SerializedBeanUtils;
import il.co.topq.refactor.utils.StringUtils;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import jsystem.extensions.sourcecontrol.SourceControlI;
/**
* @author Itai Agmon
*/
public class JSystemUtilImpl implements JSystemUtilI {
private final JSystemProject jsystemProject;
SourceControlI sourceControHandler;
// Mostly for unit testing. Keep it package protected
int numberOfFilesAffected = 0;
final File configFile = new File("JSystemUtilImpl.properties");
private Logger log = Logger.getLogger(this.getClass().getSimpleName());
public JSystemUtilImpl(File projectDir) {
jsystemProject = new JSystemProject(projectDir);
ConfigurationHandler config = new ConfigurationHandler(configFile);
loadSourceControlPlugin(config.getString("jar.path"), config.getString("class.name"));
}
public JSystemUtilImpl(File projectDir, SourceControlI sourceControlHandler) {
jsystemProject = new JSystemProject(projectDir);
this.sourceControHandler = sourceControlHandler;
}
/**
* Adds the external plugin jar to the class path and creating new instance
* of the source control plugin object.
*
* @param jarLocation
* @param className
*/
@SuppressWarnings("unchecked")
private void loadSourceControlPlugin(final String jarLocation, final String className) {
if (StringUtils.isEmpty(jarLocation) || StringUtils.isEmpty(className)) {
return;
}
URLClassLoader loader = (URLClassLoader) ClassLoader.getSystemClassLoader();
MyClassLoader l = new MyClassLoader(loader.getURLs());
Class<SourceControlI> c = null;
try {
l.addURL(new URL("file:" + jarLocation));
c = (Class<SourceControlI>) l.loadClass(className);
sourceControHandler = c.newInstance();
} catch (Exception e) {
log.log(Level.WARNING, "Failed to create instance of source control plugin", e);
}
}
/**
*
* @param scenarioSourceNamePath
* The old scenario name. for example: scenarios/simpleScenario
* @param scenarioTargetNamePath
* The new name the scenario will be renamed to. for example:
* scenarios/newScenario
*
* @return
* @throws Exception
*/
@Override
public boolean renameScenario(final String scenarioSourceNamePath, final String scenarioTargetNamePath)
throws Exception {
boolean changed = false;
log.info("About to rename " + scenarioSourceNamePath + " with " + scenarioTargetNamePath);
List<ScenarioPairFiles> pairFilesList = jsystemProject.getProjectScenariosFiles();
for (ScenarioPairFiles pairFile : pairFilesList) {
if (pairFile.getXmlFile().getScenarioName().equals(scenarioSourceNamePath)) {
log.info("Found scenario " + pairFile.getXmlFile());
// We have found the scenario we want to rename.
pairFile.backup();
pairFile.getXmlFile().rename(scenarioTargetNamePath, sourceControHandler);
pairFile.getPropertiesFile().rename(scenarioTargetNamePath, sourceControHandler);
pairFile.save(sourceControHandler);
numberOfFilesAffected = numberOfFilesAffected + 2;
changed = true;
} else {
// The that we want to rename can still be inside the current
// scenario
if (pairFile.getXmlFile().isSubScenarioExists(scenarioSourceNamePath)) {
log.info("Found scenario as sub scenario in " + pairFile.getXmlFile());
pairFile.getXmlFile().backup();
pairFile.getXmlFile().renameSubScenario(scenarioSourceNamePath, scenarioTargetNamePath);
pairFile.getXmlFile().save(sourceControHandler);
numberOfFilesAffected++;
changed = true;
}
}
}
return changed;
}
/**
*
* @param testSourceNamePath
* The old test full name. For example:
* com.aqua.services.multiuser
* .TestParamsIncludeExample.testCompareFolder
* @param testTargetNamePath
* The new test name to rename to.For example:
* com.aqua.services.multiuser
* .TestParamsIncludeExample.testCompareFile
* @return
* @throws Exception
*/
@Override
public boolean renameTest(String testSourceNamePath, String testTargetNamePath) throws Exception {
boolean changed = false;
log.info("About to rename " + testSourceNamePath + " with " + testTargetNamePath);
List<ScenarioXMLFile> xmlFilesList = jsystemProject.getScenariosXMLFiles();
for (ScenarioXMLFile xmlFile : xmlFilesList) {
if (xmlFile.isTestExists(testSourceNamePath)) {
log.info("Found test " + testSourceNamePath + " in scenario " + xmlFile.toString());
xmlFile.backup();
xmlFile.renameTest(testSourceNamePath, testTargetNamePath);
xmlFile.save(sourceControHandler);
numberOfFilesAffected++;
changed = true;
}
}
return changed;
}
/**
*/
@Override
public boolean renameTestsParameters(String testQualifiedName, String oldParameterName, String newParameterName)
throws Exception {
// JSystem when saving the property capitalize the first letter for GUI
// reason, therefore
// we capitalize the first letter of the new parameter name given by the
// user.
oldParameterName = StringUtils.firstCharToUpper(oldParameterName);
newParameterName = StringUtils.firstCharToUpper(newParameterName);
log.info("About to rename " + oldParameterName + " with " + newParameterName + " in test " + testQualifiedName);
boolean changed = false; // If any property file will change after this
// method this flag will be true
// Collect all test UUIDs for a specific test
List<ScenarioPairFiles> pairFilesList = jsystemProject.getProjectScenariosFiles();
//We select the disjoint set data structure to prevent duplication of uuid that will cause multiple
//changes in each entry instead of single change for each entry
Set<UUID> allUUIDs = new HashSet<UUID>();
// Collect the uuid of the test from the whole project
for (ScenarioPairFiles pairFile : pairFilesList) {
List<UUID> singleFileUUIDs = pairFile.getXmlFile().getTestUUIDs(testQualifiedName);
allUUIDs.addAll(singleFileUUIDs);
}
for (ScenarioPairFiles pairFile : pairFilesList) {
boolean fileChange = false;
log.finer("In file " + pairFile.getPropertiesFile());
long start = System.currentTimeMillis();
for (UUID uuid : allUUIDs) {
boolean changedNow = pairFile.getPropertiesFile().replacePropertyName(uuid, oldParameterName, newParameterName);
fileChange = fileChange || changedNow;
}
log.finer("Finished finding all uuid's in " + (System.currentTimeMillis() - start) / 1000 + " seconds");
start = System.currentTimeMillis();
if (fileChange) {
// We know that the test exists in the file and has the
// parameter we want to rename.
changed = true;
pairFile.getPropertiesFile().backup();
pairFile.getPropertiesFile().save(sourceControHandler);
log.info("Found and replaced parameter name in " + pairFile.getPropertiesFile());
numberOfFilesAffected++;
}
pairFile.getPropertiesFile().close();
log.finer("Finished writing properties to file " + (System.currentTimeMillis() - start) / 1000 + " seconds");
}
return changed;
}
/**
*
* @param beanSourceNamePath
* The full name of the bean. For example:
* com.aqua.services.multiuser.SimpleBean
*
* @param currentParameterName
* The current name of the bean parameter. For example: name
* @param newParameterName
* The new name for the parameter. For example: personName
* @return
* @throws Exception
*/
@Override
public boolean renameTestsBeanParametersNames(String beanSourceNamePath, String currentParameterName,
String newParameterName) throws Exception {
log.info(String.format("Renaming bean %s parameter %s to %s", beanSourceNamePath, currentParameterName,
newParameterName));
boolean changed = false;
List<ScenarioPropertiesFile> propertiesFilesList = jsystemProject.getScenariosPropertiesFiles();
for (ScenarioPropertiesFile propertiesFile : propertiesFilesList) {
log.fine("In file " + propertiesFile);
boolean backedUp = false;
Map<String, String> content = propertiesFile.getContent();
for (String prop : content.keySet()) {
if (SerializedBeanUtils.isBeanExists(content.get(prop), beanSourceNamePath)) {
log.info("Found bean in " + propertiesFile);
String newBean = SerializedBeanUtils.renameBeanParameter(content.get(prop), currentParameterName,
newParameterName);
if (newBean.equals(content.get(prop))) {
log.fine("Bean exists but no change was done");
continue;
}
if (!backedUp) {
log.fine("Creating backup of " + propertiesFile);
numberOfFilesAffected++;
propertiesFile.backup();
backedUp = true;
}
propertiesFile.put(prop, newBean);
propertiesFile.save(sourceControHandler);
changed = true;
}
}
propertiesFile.close();
}
return changed;
}
/**
*
* @param multipleSuiteAbsolutePathFileName
* The absolute location of the XML file
* @param scenarioSourceNamePath
* The old name of the scenario. For example:
* scenarios/flowControl
* @param scenarioTargetNamePath
* The new name for the scenario. For example:
* scenarios/flowControl2
* @return
* @throws Exception
*/
@Override
public boolean renameMultipleScenariosSuiteExecutionScenarioName(String multipleSuiteAbsolutePathFileName,
String scenarioSourceNamePath, String scenarioTargetNamePath) throws Exception {
log.info("About to rename scenario " + scenarioSourceNamePath + " to " + scenarioTargetNamePath + " in "
+ multipleSuiteAbsolutePathFileName);
if (!(new File(multipleSuiteAbsolutePathFileName).exists())) {
log.severe("File " + multipleSuiteAbsolutePathFileName + " is not exist");
return false;
}
scenarioSourceNamePath = StringUtils.frontSlashToBackSlash(scenarioSourceNamePath);
scenarioTargetNamePath = StringUtils.frontSlashToBackSlash(scenarioTargetNamePath);
MultipleScenarioSuiteFile suiteFile = new MultipleScenarioSuiteFile(multipleSuiteAbsolutePathFileName);
if (!suiteFile.isScenarioExists(scenarioSourceNamePath)) {
log.warning("Scenario " + scenarioSourceNamePath + " not exist in " + multipleSuiteAbsolutePathFileName);
return false;
}
suiteFile.backup();
suiteFile.renameScenario(scenarioSourceNamePath, scenarioTargetNamePath);
suiteFile.save(sourceControHandler);
numberOfFilesAffected++;
return true;
}
@Override
public int getNumberOfAffectedFiles() {
return numberOfFilesAffected;
}
}