All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.inria.prophet4j.utility.Structure Maven / Gradle / Ivy

package fr.inria.prophet4j.utility;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;

import org.apache.commons.io.FileUtils;

import com.google.gson.Gson;

import fr.inria.prophet4j.feature.Feature;
import fr.inria.prophet4j.feature.FeatureCross;
import fr.inria.prophet4j.feature.S4R.S4RFeature;
import fr.inria.prophet4j.feature.S4RO.S4ROFeature;
import fr.inria.prophet4j.feature.enhanced.EnhancedFeature;
import fr.inria.prophet4j.feature.extended.ExtendedFeature;
import fr.inria.prophet4j.feature.original.OriginalFeature;
import fr.inria.prophet4j.utility.Option.FeatureOption;
import spoon.reflect.declaration.CtElement;

public interface Structure {
	class Sample { // namely TrainingCase
		private String filePath;
		private List featureMatrices;

		public Sample(String filePath) {
			this.filePath = filePath;
			this.featureMatrices = new ArrayList<>();
		}

		public List getFeatureMatrices() {
			return featureMatrices;
		}

		public void loadFeatureMatrices() {
			try {
				FileInputStream fis = new FileInputStream(filePath);
				ObjectInputStream ois = new ObjectInputStream(fis);
				featureMatrices = (List) ois.readObject();
				/*
				 * // if we need to try on merged feature-vector // however it usually not
				 * performances better List tmpFeatureMatrices = new
				 * ArrayList<>(); for (FeatureMatrix featureMatrix: featureMatrices) {
				 * FeatureVector tmpFeatureVector = new FeatureVector(); for (FeatureVector
				 * featureVector: featureMatrix.featureVectors) {
				 * tmpFeatureVector.merge(featureVector); } List
				 * tmpFeatureVectors = new ArrayList<>();
				 * tmpFeatureVectors.add(tmpFeatureVector); tmpFeatureMatrices.add(new
				 * FeatureMatrix(featureMatrix.marked, featureMatrix.fileKey,
				 * tmpFeatureVectors)); } featureMatrices = tmpFeatureMatrices;
				 */
				ois.close();
				fis.close();
			} catch (ClassNotFoundException | IOException e) {
				e.printStackTrace();
			}
		}

		public void saveFeatureMatrices(List featureMatrices) {
			try {
				File file = new File(filePath);
				if (!file.exists()) {
					file.getParentFile().mkdirs();
				}
				FileOutputStream fos = new FileOutputStream(filePath);
				ObjectOutputStream oos = new ObjectOutputStream(fos);
				oos.writeObject(featureMatrices);
				oos.flush();
				oos.close();
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		// as we do not utilize json-format data, we have no loadJson method
		// the root reason is that prophet4j owns sub-features
		public void saveAsJson(FeatureOption featureOption) {
			int arraySize = 0;
			switch (featureOption) {
			case ENHANCED:
				arraySize = EnhancedFeature.FEATURE_SIZE;
				break;
			case EXTENDED:
				arraySize = ExtendedFeature.FEATURE_SIZE;
				break;
			case ORIGINAL:
				arraySize = OriginalFeature.FEATURE_SIZE;
				break;
			case S4R:
				arraySize = S4RFeature.FEATURE_SIZE;
				break;
			case S4RO:
				arraySize = S4ROFeature.FEATURE_SIZE;
				break;
			}

			Map> featureMatrixList = new HashMap<>();
			for (FeatureMatrix featureMatrix : featureMatrices) {
				List featureVectorList = new ArrayList<>();
				// always skip this loop when we meet invalid patches
				for (FeatureVector featureVector : featureMatrix.getFeatureVectors()) {
					double[] featureCrossArray = new double[arraySize];
					for (FeatureCross featureCross : featureVector.getFeatureCrosses()) {
						featureCrossArray[featureCross.getId()] = featureCross.getDegree();
					}
					featureVectorList.add(featureCrossArray);
				}
				featureMatrixList.put(featureMatrix.fileKey, featureVectorList);
			}
			String json = new Gson().toJson(featureMatrixList);
			String jsonPath = filePath.replace("prophet4j/_BIN/", "prophet4j/_JSON/");
			jsonPath = jsonPath.replace(".bin", ".json");
			try {
				File file = new File(jsonPath);
				if (!file.exists()) {
					file.getParentFile().mkdirs();
				}
				Files.write(Paths.get(jsonPath), json.getBytes());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public String toString() {
			return filePath;
		}
	}

	// entity which contains feature-crosses to express characteristics of each
	// diff-operation
	class FeatureVector implements Serializable {
		static final long serialVersionUID = 1L;
		private Set featureCrosses;

		public FeatureVector() {
			this.featureCrosses = new HashSet<>();
		}

		public boolean containFeature(Feature feature) {
			for (FeatureCross featureCross : featureCrosses) {
				if (featureCross.containFeature(feature)) {
					return true;
				}
			}
			return false;
		}

		public void addFeatureCross(FeatureCross featureCross) {
			featureCrosses.add(featureCross);
		}

		// if we return set directly, results would be unpredictable. DO NOT return set
		// directly
		public List getFeatureCrosses() {
			List list = new ArrayList<>(featureCrosses);
			list.sort(Comparator.comparingInt(FeatureCross::getId));
			return list;
		}

		public List getNonSortedFeatureCrosses() {
			List list = new ArrayList<>(featureCrosses);
			return list;
		}

		public void merge(FeatureVector featureVector) {
			this.featureCrosses.addAll(featureVector.getFeatureCrosses());
		}

		public double score(ParameterVector parameterVector) {
			// scores means values of phi dotProduct theta
			return parameterVector.dotProduct(this);
		}

		@Override
		public String toString() {
			return "FeatureCrosses: " + featureCrosses;
		}
	}

	// entity which contains feature-vectors to express multi-diff-operations of
	// each patch
	class FeatureMatrix implements Serializable {
		static final long serialVersionUID = 1L;
		private boolean marked; // for human patch or not
		private String fileKey;
		private List featureVectors;

		public FeatureMatrix(boolean marked, String fileKey, List featureVectors) {
			this.marked = marked;
			this.fileKey = fileKey;
			this.featureVectors = featureVectors;
		}

		public boolean containFeature(Feature feature) {
			for (FeatureVector featureVector : featureVectors) {
				if (featureVector.containFeature(feature)) {
					return true;
				}
			}
			return false;
		}

		public List getFeatureVectors() {
			return featureVectors;
		}

		public boolean isMarked() {
			return this.marked;
		}

		// to mark generated patches false
		public void correctMarked() {
			this.marked = false;
		}

		public double score(ParameterVector parameterVector) {
			double score = 0;
			// we compute the sum as the whole score
			for (FeatureVector featureVector : featureVectors) {
				score += featureVector.score(parameterVector);
			}
			return score;
		}

		@Override
		public String toString() {
			return "FeatureVectors: " + featureVectors;
		}

	}

	// entity which contains weights for all feature-crosses
	class ParameterVector {
		public double gamma = 0;
		private int arraySize = 0;
		private double[] parameterArray;

		public ParameterVector(FeatureOption featureOption) {
			switch (featureOption) {
			case ENHANCED:
				this.arraySize = EnhancedFeature.FEATURE_SIZE;
				break;
			case EXTENDED:
				this.arraySize = ExtendedFeature.FEATURE_SIZE;
				break;
			case ORIGINAL:
				this.arraySize = OriginalFeature.FEATURE_SIZE;
				break;
			case S4R:
				this.arraySize = S4RFeature.FEATURE_SIZE;
				break;
			case S4RO:
				this.arraySize = S4ROFeature.FEATURE_SIZE;
				break;
			}
			this.parameterArray = new double[arraySize];
		}

		public int size() {
			return parameterArray.length;
		}

		public double get(int index) {
			return parameterArray[index];
		}

		// +=
		public void inc(int index, double value) {
			parameterArray[index] += value;
		}

		// -=
		public void dec(int index, double value) {
			parameterArray[index] -= value;
		}

		// /=
		public void div(int index, double value) {
			parameterArray[index] /= value;
		}

		public void clone(ParameterVector parameterVector) {
			this.arraySize = parameterVector.arraySize;
			this.parameterArray = parameterVector.parameterArray.clone();
		}

		public double dotProduct(FeatureVector featureVector) {
			double res = 0;
			for (FeatureCross featureCross : featureVector.getFeatureCrosses()) {
				int featureCrossId = featureCross.getId();
				res += parameterArray[featureCrossId];
			}
			return res;
		}

		public void load(String filePath) {
			try {
				File vectorFile = new File(filePath);
				String content = "";

				if (vectorFile.exists())

					content = FileUtils.readFileToString(vectorFile, Charset.defaultCharset());

				else {
					InputStream inputStream = this.getClass().getClassLoader()
							.getResourceAsStream(vectorFile.getAbsolutePath());

					StringBuilder textBuilder = new StringBuilder();
					try (Reader reader = new BufferedReader(
							new InputStreamReader(inputStream, Charset.defaultCharset()))) {
						int c = 0;
						while ((c = reader.read()) != -1) {
							textBuilder.append((char) c);
						}
					}
					content = textBuilder.toString();

				}

				if (content != null && !content.isEmpty()) {

					String[] substrings = content.split(" ");
					parameterArray = Arrays.stream(substrings).mapToDouble(Double::valueOf).toArray();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		public void save(String filePath) {
			try {
				StringJoiner stringJoiner = new StringJoiner(" ");
				for (double parameter : parameterArray) {
					stringJoiner.add(String.valueOf(parameter));
				}
				File vectorFile = new File(filePath);
				FileUtils.writeStringToFile(vectorFile, stringJoiner.toString(), Charset.defaultCharset(), false);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	enum DiffType {
		DeleteType, InsertType, UpdateType,
		// Delete and Move
		PartialDeleteType,
	}

	enum RepairKind { // implementation is at RepairGenerator.java
		// INSERT_CONTROL_RF
		IfExitKind, // genAddIfExit()
		// INSERT_GUARD_RF
		GuardKind, // genAddIfGuard()
		SpecialGuardKind, // genAddIfGuard()
		// INSERT_STMT_RF
		AddInitKind, // Inapplicable to Java
		AddAndReplaceKind, // genAddStatement()
		// REPLACE_COND_RF
		TightenConditionKind, // genTightCondition()
		LoosenConditionKind, // genLooseCondition()
		// REPLACE_STMT_RF
		ReplaceKind, // genReplaceStmt()
		ReplaceStringKind, // genReplaceStmt()
		// code deletion related features
		RemovePartialIFKind, RemoveSTMTKind, RemoveWholeIFKind, RemoveWholeBlockKind,
	}

	class DiffEntry { // DiffResultEntry
		// the reason why CtElement is used here is because clang::Expr isa clang::Stmt
		public DiffType type;
		public CtElement srcNode, dstNode;

		public DiffEntry(DiffType type, CtElement srcNode, CtElement dstNode) {
			this.type = type;
			this.srcNode = srcNode;
			this.dstNode = dstNode;
		}
	}

	class Repair {
		public RepairKind kind;
		public boolean isReplace;
		public CtElement srcElem, dstElem; // from RepairAction
		public List atoms; // from RepairAction
		public CtElement oldRExpr, newRExpr; // only for UpdateType

		public Repair() {
			this.kind = null;
			this.isReplace = false;
			this.srcElem = null;
			this.dstElem = null;
			this.atoms = new ArrayList<>();
			this.oldRExpr = null;
			this.newRExpr = null;
		}

		public Set getCandidateAtoms() {
			Set ret = new HashSet<>();
			ret.add(null); // ?
			ret.addAll(atoms);
			return ret;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy