package cideplus.model;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.dom.ASTNode;
import cideplus.automation.Util;
import cideplus.model.ast.utils.NodeFinder;
import cideplus.model.exceptions.FeatureNotFoundException;
import cideplus.ui.configuration.FeaturesConfigurationUtil;
import cideplus.ui.configuration.ICompilationUnitFeaturesManager;
import cideplus.ui.configuration.IFeaturesManager;
import cideplus.utils.PluginUtils;
/**
* Classe utilit�ria para trabalhar com as features.
* As funcionalidades dessa classe s�o independentes da interface gr�fica
* @author rogel
*
*/
public class FeaturesUtil {
private static final String BYTES_OFFSET_SEPARATOR = "@";
private static final String NUMBER_INFORMATION_SEPARATOR = "@@";
private static final String FEATURES_END = "\06<<<";
private static final String FEATURES_SEPARATOR = "\06>>>FEATURES:";
/**
* L� as features de determinado arquivo
* @param contents
* @return
* @throws IOException
*/
public static Set<Feature> readFeatures(InputStream contents) throws IOException {
Set<Feature> features = new TreeSet<Feature>();
BufferedReader reader = new BufferedReader(new InputStreamReader(contents));
try {
String featureLine;
while ((featureLine = reader.readLine()) != null) {
try {
String[] properties = featureLine.split(Feature.FEATURE_PROPERTY_DELIMITER);
Integer id = new Integer(properties[0]);
String name = properties[1];
RGB rgb = RGB.fromString(properties[2]);
features.add(new Feature(id, name, rgb));
} catch (RuntimeException e) {
throw new RuntimeException("Invalid feature: '"+featureLine+"'. \nFeature should have the folowing pattern: [id]::[name]::([red],[green],[blue])");
}
}
} finally {
reader.close();
}
return features;
}
/**
* Salva as features em determinado arquivo
* @param out
* @param features
*/
public static void saveFeatures(OutputStream out, Set<Feature> features) {
PrintWriter writer = new PrintWriter(out);
try {
for (Feature feature : features) {
writer.println(feature.toString());
}
writer.flush();
} finally {
writer.close();
}
}
public static CompilationUnitFeaturesModel loadFeaturesForCompilationUnit(Set<Feature> projectFeatures, InputStream in) throws IOException, FeatureNotFoundException {
CompilationUnitFeaturesModel model = new CompilationUnitFeaturesModel();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String linha = null;
ByteArrayOutputStream astOut = new ByteArrayOutputStream();
PrintWriter astWriter = new PrintWriter(astOut);
int[] features = null;
while((linha = reader.readLine()) != null){
String numberInformation = linha.substring(0, linha.indexOf(NUMBER_INFORMATION_SEPARATOR));
String[] bytesOffset = numberInformation.split(BYTES_OFFSET_SEPARATOR);
int bytes = Integer.parseInt(bytesOffset[0]);
int offset = Integer.parseInt(bytesOffset[1]);
linha = linha.substring(linha.indexOf(NUMBER_INFORMATION_SEPARATOR) + NUMBER_INFORMATION_SEPARATOR.length());
if(linha.contains(FEATURES_SEPARATOR) && linha.contains(FEATURES_END)){
String featuresString = linha.substring(linha.indexOf(FEATURES_SEPARATOR) + FEATURES_SEPARATOR.length(), linha.length() - FEATURES_END.length() - 1);
String[] featuresSplit = featuresString.split(",");
features = new int[featuresSplit.length];
for (int i = 0; i < featuresSplit.length; i++) {
features[i] = Integer.parseInt(featuresSplit[i]);
}
linha = linha.substring(0, linha.indexOf(FEATURES_SEPARATOR));
}
astWriter.print(linha);
if(features != null){
astWriter.flush();
String astString = new String(astOut.toByteArray());
for (int featureId : features) {
Feature featureObj = new Feature(featureId);
if(!projectFeatures.contains(featureObj)){
throw new FeatureNotFoundException(featureId);
}
//pegar o feature completo do projeto, não apenas com o ID
for (Feature feature : projectFeatures) {
if(featureObj.equals(feature)){
featureObj = feature;
break;
}
}
model.getFeatures(new ASTNodeReference(astString, bytes, offset)).add(featureObj);
}
astOut.reset();
}
}
return model;
}
public static void saveFeaturesForCompilationUnit(OutputStream out, CompilationUnitFeaturesModel model){
PrintWriter writer = new PrintWriter(out);
try {
for (ASTNodeReference nodeReference : model.getNodeReferences()) {
Set<Feature> features = model.getFeatures(nodeReference);
if (features.size() > 0) {
writer.print(nodeReference.bytes);
writer.print(BYTES_OFFSET_SEPARATOR);
writer.print(nodeReference.offset);
writer.print(NUMBER_INFORMATION_SEPARATOR);
writer.print(nodeReference);
writer.print(FEATURES_SEPARATOR);
for (Feature feature : features) {
writer.print(feature.getId());
writer.print(",");
}
writer.println(FEATURES_END);
}
}
} finally {
writer.close();
}
}
// TODO: Dar um merge nesses métodos!
/* Marca uma feature a partir de um offset e um length */
public static void markFeature(int featureId, int offset, int length) throws CoreException, IOException, FeatureNotFoundException {
IProject project = PluginUtils.getCurrentProject();
ICompilationUnit compUnit = PluginUtils.getCurrentCompilationUnit();
IFeaturesManager manager = FeaturesConfigurationUtil.getFeaturesManager(project);
ICompilationUnitFeaturesManager managerForFile = manager.getManagerForFile(compUnit);
ASTNode node = NodeFinder.perform(Util.getAst(compUnit), offset, length);
if (node == null) {
System.out.println("No node found...");
}
else {
Feature feature = FeaturesConfigurationUtil.getFeature(project, featureId);
managerForFile.setFeature(node, feature);
managerForFile.commitChanges();
}
}
/* Desmarca uma feature a partir de um offset e um length */
public static void unmarkFeature(int featureId, int offset, int length) throws CoreException, IOException, FeatureNotFoundException {
IProject project = PluginUtils.getCurrentProject();
ICompilationUnit compUnit = PluginUtils.getCurrentCompilationUnit();
IFeaturesManager manager = FeaturesConfigurationUtil.getFeaturesManager(project);
ICompilationUnitFeaturesManager managerForFile = manager.getManagerForFile(compUnit);
ASTNode node = NodeFinder.perform(Util.getAst(compUnit), offset, length);
if (node == null) {
System.out.println("No node found...");
}
else {
Feature feature = FeaturesConfigurationUtil.getFeature(project, featureId);
managerForFile.removeFeature(node, feature);
managerForFile.commitChanges();
}
}
}