/**
* This file is licensed under the University of Illinois/NCSA Open Source License. See LICENSE.TXT for details.
*/
package edu.illinois.codingspectator.refactoringproblems.logger;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Set;
import org.eclipse.core.internal.resources.XMLWriter;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import edu.illinois.codingspectator.saferecorder.SafeRecorder;
/**
* This class contains the two way differences between the set of compilation problems before and
* after a refactoring.
*
* @author Mohsen Vakilian
* @author Balaji Ambresh Rajkumar
*
*/
@SuppressWarnings("restriction")
public class ProblemChanges {
public static final String REFACTORING_PROBLEMS_LOG= "refactoring-problems.log";
public static final String PROBLEM_CHANGES_TAG_NAME= "problem-changes";
public static final String REFACTORING_TIMESTAMP_ATTRIBUTE_NAME= "refactoring-timestamp";
public static final String BEFORE_MINUS_AFTER_TAG_NAME= "before-minus-after";
public static final String AFTER_MINUS_BEFORE_TAG_NAME= "after-minus-before";
public static final String TIMESTAMP_ATTRIBUTE_NAME= "timestamp";
long refactoringTimestamp, beforeTimestamp, afterTimestamp;
Set<DefaultProblemWrapper> afterMinusBefore;
Set<DefaultProblemWrapper> beforeMinusAfter;
public ProblemChanges(long refactoringTimestamp, long afterTimestamp, Set<DefaultProblemWrapper> afterMinusBefore, long beforeTimestamp, Set<DefaultProblemWrapper> beforeMinusAfter) {
this.refactoringTimestamp= refactoringTimestamp;
this.afterTimestamp= afterTimestamp;
this.afterMinusBefore= afterMinusBefore;
this.beforeTimestamp= beforeTimestamp;
this.beforeMinusAfter= beforeMinusAfter;
}
private void startProblemChangesTag(XMLWriter xmlWriter) {
HashMap<String, Object> attributes= new HashMap<String, Object>();
attributes.put(REFACTORING_TIMESTAMP_ATTRIBUTE_NAME, refactoringTimestamp);
xmlWriter.startTag(PROBLEM_CHANGES_TAG_NAME, attributes);
}
private void addTo(Set<DefaultProblemWrapper> problems, String tagName, long timestamp, XMLWriter xmlWriter) throws UnsupportedEncodingException {
HashMap<String, Object> attributes= new HashMap<String, Object>();
attributes.put(TIMESTAMP_ATTRIBUTE_NAME, timestamp);
xmlWriter.startTag(tagName, attributes);
for (DefaultProblemWrapper problem : problems) {
problem.addTo(xmlWriter);
}
xmlWriter.endTag(tagName);
}
@Override
public int hashCode() {
final int prime= 31;
int result= 1;
result= prime * result + ((afterMinusBefore == null) ? 0 : afterMinusBefore.hashCode());
result= prime * result + (int)(afterTimestamp ^ (afterTimestamp >>> 32));
result= prime * result + ((beforeMinusAfter == null) ? 0 : beforeMinusAfter.hashCode());
result= prime * result + (int)(beforeTimestamp ^ (beforeTimestamp >>> 32));
result= prime * result + (int)(refactoringTimestamp ^ (refactoringTimestamp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ProblemChanges other= (ProblemChanges)obj;
if (afterMinusBefore == null) {
if (other.afterMinusBefore != null)
return false;
} else if (!afterMinusBefore.equals(other.afterMinusBefore))
return false;
if (afterTimestamp != other.afterTimestamp)
return false;
if (beforeMinusAfter == null) {
if (other.beforeMinusAfter != null)
return false;
} else if (!beforeMinusAfter.equals(other.beforeMinusAfter))
return false;
if (beforeTimestamp != other.beforeTimestamp)
return false;
if (refactoringTimestamp != other.refactoringTimestamp)
return false;
return true;
}
@Override
public String toString() {
StringBuilder builder= new StringBuilder();
builder.append("ProblemChanges [refactoringTimestamp=");
builder.append(refactoringTimestamp);
builder.append(", beforeTimestamp=");
builder.append(beforeTimestamp);
builder.append(", afterTimestamp=");
builder.append(afterTimestamp);
builder.append(", afterMinusBefore=");
builder.append(afterMinusBefore);
builder.append(", beforeMinusAfter=");
builder.append(beforeMinusAfter);
builder.append("]");
return builder.toString();
}
/**
*
* This method prints out the changes of the problems in the following format:
*
* <problem-changes refactoring-timestamp="...">
*
* <after-minus-before timestamp="...">...</after-minus-before>
*
* <before-minus-after timestamp="...">...</before- minus-after>
*
* </problem-changes>
*
*/
public void log() {
SafeRecorder safeRecorder= new SafeRecorder("refactorings/" + REFACTORING_PROBLEMS_LOG);
ByteArrayOutputStream outputStream= new ByteArrayOutputStream();
try {
XMLWriter xmlWriter= new XMLWriter(outputStream);
startProblemChangesTag(xmlWriter);
addTo(afterMinusBefore, AFTER_MINUS_BEFORE_TAG_NAME, afterTimestamp, xmlWriter);
addTo(beforeMinusAfter, BEFORE_MINUS_AFTER_TAG_NAME, beforeTimestamp, xmlWriter);
xmlWriter.endTag(PROBLEM_CHANGES_TAG_NAME);
xmlWriter.close();
} catch (UnsupportedEncodingException e) {
Activator.getDefault().getLog().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, "CODINGSPECTATOR: Failed to serialize the compilation problems.", e));
}
final String XMLWriter_XML_VERSION= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
safeRecorder.record(outputStream.toString().substring(XMLWriter_XML_VERSION.length()));
}
}