package br.uff.ic.oceano.core.tools.metrics.extractors.dependometer.util;
import br.uff.ic.oceano.core.model.Metric;
import br.uff.ic.oceano.core.model.Revision;
import br.uff.ic.oceano.core.model.SoftwareProject;
import br.uff.ic.oceano.core.model.transiente.Language;
import br.uff.ic.oceano.core.tools.compiler.CompilerService;
import br.uff.ic.oceano.core.tools.metrics.extractors.dependometer.DependometerException;
import br.uff.ic.oceano.core.tools.metrics.util.XMLUtil;
import br.uff.ic.oceano.core.tools.revision.RevisionUtil;
import br.uff.ic.oceano.util.file.FileUtils;
import br.uff.ic.oceano.util.file.PathUtil;
import br.uff.ic.oceano.util.SystemUtil;
import com.valtech.source.dependometer.app.core.common.MetricEnum;
import com.valtech.source.dependometer.app.core.provider.ProviderFactory;
import com.valtech.source.dependometer.ui.console.Dependometer;
import java.io.File;
import java.util.List;
import java.util.Set;
import org.jdom2.Document;
/**
*
*
* @author Daniel
*/
public class Adapter {
private final Revision revision;
private String outputPath;
private Document document;
public Adapter(Revision revision) {
this.revision = revision;
}
public Double getMetric(Metric metric, String path) throws DependometerException {
try {
return DependomenterDocumentReader.getMetric(metric, path, getDocument());
} catch (Exception ex) {
throw new DependometerException("Fail to get metric " + metric.getName() + " from " + path, ex);
}
}
private synchronized Document getDocument() throws DependometerException {
if (document == null) {
document = processRevision();
}
return this.document;
}
/**
* Allow checking results on tests
*
* @param path
* @throws DependometerException
*/
public synchronized void writeMetricsToXML(String path) throws DependometerException {
try {
final String encoding = "ISO-8859-1";
XMLUtil.writeXML(getDocument(), path, encoding);
} catch (Exception e) {
throw new DependometerException(e);
}
}
/**
*
* @param metric
* @param revision
* @param path
* @return
* @throws DependometerException
*/
private Document processRevision() throws DependometerException {
try {
//Validate parameters
validateParameter();
//Set up output path
prepareOutputPath();
//Compile Java project if necessary
Language language = getRevision().getProject().getLanguage();
if (Language.JAVA.equals(language)) {
CompilerService.compile(getRevision());
}
//create xml config file from revision software project
File config = ConfigurationFactory.createConfigFile(getRevision(), getOutputXmlPath(), getConfigXmlPath());
File outputFile = execDependometer(config);
//read output xml
Document result = readOutputXml(outputFile);
//clean output path
deleteOutputPath();
return result;
} catch (Exception ex) {
throw new DependometerException(ex);
}
}
private Document readOutputXml(File resultFile) throws DependometerException {
try {
return XMLUtil.readXml(resultFile.getPath());
} catch (Exception ex) {
throw new DependometerException(ex);
}
}
private String getOutputXmlPath() throws Exception {
return getOutputPath() + SystemUtil.FILESEPARATOR + "output.xml";
}
private String getConfigXmlPath() throws Exception {
return getOutputPath() + "config.xml";
}
private String createOutputPath() throws Exception {
String path = SystemUtil.getTempDirectory();
path += SystemUtil.FILESEPARATOR;
//allow mult threading
path += "dependometer_" + System.currentTimeMillis();
path += SystemUtil.FILESEPARATOR;
return path;
}
private String getOutputPath() throws Exception {
if(this.outputPath == null){
this.outputPath = createOutputPath();
}
return this.outputPath;
}
/**
* Clear output directory.
*
* @param revision
*/
private void prepareOutputPath() throws DependometerException {
try {
String path = getOutputPath();
File file = new File(path);
//clear previous run
boolean dirExisted = false;
if (file.exists()) {
dirExisted = true;
deleteOutputPath();
}
//Create output path
//one try is not enough
PathUtil.mkDirs(path);
//verify
if (!file.exists()) {
System.out.println("Existed: " + dirExisted);
throw new DependometerException("Fail to prepare output path. Directory not created.");
}
} catch (Exception ex) {
throw new DependometerException("Fail to prepare output path.", ex);
}
}
/**
* Delete output directory
*
* @param revision
*/
private void deleteOutputPath() throws Exception {
FileUtils.deleteDirectory(new File(getOutputPath()));
}
/**
* Validate necessary parameter for processing.
*
* @throws DependometerException
*/
private void validateParameter() throws DependometerException {
//check Parameter
if (getRevision() == null) {
throw new DependometerException("Null parameter 'revision'");
} else if (getRevision().getProject() == null) {
throw new DependometerException("SoftwareProject not set on revision");
}
SoftwareProject project = getRevision().getProject();
Language lang = project.getLanguage();
if (!Language.CPP.equals(lang) && !Language.JAVA.equals(lang)) {
throw new DependometerException("Unsupported language: " + lang);
} else if (Language.JAVA.equals(lang)) {
if (!project.isMavenProject()) {
throw new DependometerException("Unsupported non Maven java projects");
}
Set col = null;
try {
col = RevisionUtil.get().getCompilationFolders(getRevision());
} catch (Exception ex) {
throw new DependometerException(ex);
}
if (col.size() > 1) {
throw new DependometerException("Unsupported Maven module projects");
}
}
}
/**
* @return the revision
*/
public Revision getRevision() {
return revision;
}
private synchronized File execDependometer(File configFile) throws Exception {
Dependometer dependometer = new Dependometer();
setLanguageTypeProvider();
dependometer.startAnalysis(configFile);
return new File(getOutputXmlPath());
}
/**
* Set system property which dependometer uses to parse project
*
* @throws DependometerException
*/
private void setLanguageTypeProvider() throws DependometerException {
Language language = getRevision().getProject().getLanguage();
String typedefProviderClass = "";
if (Language.CPP.equals(language)) {
typedefProviderClass = com.valtech.source.dependometer.app.typedefprovider.filebased.cpp.TypeDefinitionProvider.class.getName();
} else if (Language.JAVA.equals(language)) {
typedefProviderClass = com.valtech.source.dependometer.app.typedefprovider.filebased.java.TypeDefinitionProvider.class.getName();
} else {
throw new DependometerException("Unsupported language for TypeDefinitionProvider");
}
System.setProperty(ProviderFactory.TYPE_DEFINITION_PROVIDER_KEY, typedefProviderClass);
}
public List<Double> getCompilationUnitValues(MetricEnum metric) throws DependometerException {
Document doc = getDocument();
return DependomenterDocumentReader.getCompilationUnitValues(metric,doc);
}
public List<Double> getTypeValues(MetricEnum metric) throws DependometerException{
Document doc = getDocument();
return DependomenterDocumentReader.getTypeValues(metric,doc);
}
}