package edu.cmu.sv.arinc838.validation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import edu.cmu.sv.arinc838.dao.FileDefinitionDao;
import edu.cmu.sv.arinc838.dao.IntegrityDefinitionDao;
import edu.cmu.sv.arinc838.dao.SoftwareDefinitionFileDao;
import edu.cmu.sv.arinc838.dao.SoftwareDescriptionDao;
import edu.cmu.sv.arinc838.dao.TargetHardwareDefinitionDao;
/**
* Throughout the comparisons a case of this.<obj> == null && other.<obj> ==
* null is not considered an error. Only if they are different.
*
* Order in any lists is maintained. [a,b,c] != [c,a,b]
*
* @author ryan
*/
public class SdfChecker {
/**
* Interface that acts similarly to a function pointer. Allows lists of
* objects to be handled generically but still call back into the sdf
* checker code.
*
* @param <D>
*/
protected interface CompareRef<D> {
public Collection<String> passThru(D mine, D theirs);
}
public List<String> compare(SoftwareDefinitionFileDao mine, SoftwareDefinitionFileDao theirs) {
List<String> results = new ArrayList<String>();
Boolean nc = nullCheck (mine, theirs);
if (nc == null) {
return results;
} else if (nc == true) {
results.add("Can't compare software definitions, null detected. " + mine + ", " + theirs);
return results;
}
if (!compareBytes (mine.getFileFormatVersion(), theirs.getFileFormatVersion())) {
results.add("The file format versions differ");
}
results.addAll(check(mine.getFileDefinitions(), theirs.getFileDefinitions(), "file definition",
new CompareRef<FileDefinitionDao>() {
@Override
public Collection<String> passThru(FileDefinitionDao mine, FileDefinitionDao theirs) {
return compare(mine, theirs);
}
}));
results.addAll(check(mine.getTargetHardwareDefinitions(), theirs.getTargetHardwareDefinitions(),
"target hardware definition", new CompareRef<TargetHardwareDefinitionDao>() {
@Override
public Collection<String> passThru(TargetHardwareDefinitionDao mine,
TargetHardwareDefinitionDao theirs) {
return compare(mine, theirs);
}
}));
results.addAll(compare(mine.getLspIntegrityDefinition(), theirs.getLspIntegrityDefinition()));
results.addAll(compare(mine.getSdfIntegrityDefinition(), theirs.getSdfIntegrityDefinition()));
results.addAll(compare(mine.getSoftwareDescription(), theirs.getSoftwareDescription()));
return results;
}
protected List<String> compare(SoftwareDescriptionDao mine, SoftwareDescriptionDao theirs) {
List<String> results = new ArrayList<String>();
Boolean nc = nullCheck (mine, theirs);
if (nc == null) {
return results;
} else if (nc == true) {
results.add("Can't compare software descriptions, null detected. " + mine + ", " + theirs);
return results;
}
check(mine.getSoftwarePartnumber(), theirs.getSoftwarePartnumber(), "software part number", results);
check(mine.getSoftwareTypeDescription(), theirs.getSoftwareTypeDescription(), "software type description", results);
if (!compareBytes(mine.getSoftwareTypeId(), theirs.getSoftwareTypeId())) {
results.add("The software type ids differ");
}
return results;
}
protected List<String> compare(IntegrityDefinitionDao mine, IntegrityDefinitionDao theirs) {
List<String> results = new ArrayList<String>();
Boolean nc = nullCheck (mine, theirs);
if (nc == null) {
return results;
} else if (nc == true) {
results.add("Can't compare integrity definitions, null detected. " + mine + ", " + theirs);
return results;
}
check (mine.getIntegrityType(), theirs.getIntegrityType(), "integrity type", results);
if (!compareBytes(mine.getIntegrityValue(), theirs.getIntegrityValue())) {
results.add("The integrity values differ");
}
return results;
}
protected List<String> compare(FileDefinitionDao mine, FileDefinitionDao theirs) {
List<String> results = new ArrayList<String>();
Boolean nc = nullCheck (mine, theirs);
if (nc == null) {
return results;
} else if (nc == true) {
results.add("Can't compare file definitions, null detected. " + mine + ", " + theirs);
return results;
}
check (mine.getFileName(), theirs.getFileName(), "filename", results);
check (mine.getFileSize(), theirs.getFileSize(), "file size", results);
check (mine.isFileLoadable(), theirs.isFileLoadable(), "loadable flag", results);
results.addAll(compare (mine.getFileIntegrityDefinition(), theirs.getFileIntegrityDefinition()));
return results;
}
protected List<String> compare(TargetHardwareDefinitionDao mine, TargetHardwareDefinitionDao theirs) {
List<String> results = new ArrayList<String>();
Boolean nc = nullCheck (mine, theirs);
if (nc == null) {
return results;
} else if (nc == true) {
results.add("Can't compare target hardware definitions, null detected. " + mine + ", " + theirs);
return results;
}
check (mine.getThwId(), theirs.getThwId(), "target hardware id", results);
results.addAll(check(mine.getPositions(), theirs.getPositions(),
"positions", new CompareRef<String>() {
@Override
public Collection<String> passThru(String mine,
String theirs) {
List<String> results = new ArrayList<String> ();
check (mine, theirs, "positions", results);
return results;
}
}));
return results;
}
/**
* True iff both are null, or if either one is.
* A message is logged if one is null and the other isn't
* @param mine
* @param theirs
* @param results
* @return
*/
protected <T> Boolean nullCheck (T mine, T theirs) {
if ((mine == null && theirs != null) || (mine != null && theirs== null)) {
return true;
} else if (mine == null && theirs == null) {
return null;
}
return false;
}
/**
* Compares two objects -
* If they are the same (defined above) then nothing is done. TRUE is returned
* Otherwise (e.g. null & !null, not equal) then FALSE is returned;
* @param mine
* @param theirs
* @param type
* @param results
* @return
*/
protected <T> boolean check (T mine, T theirs, String type, List<String> results) {
if ((mine != null && theirs != null && !mine.equals(theirs)) ||
(mine == null && theirs != null) ||
(mine != null && theirs == null)) {
results.add("The " + type + "s differ: " + mine + "," + theirs);
return false;
}
return true;
}
protected boolean compareBytes(byte[] mine, byte[] theirs) {
if (nullCheck (mine, theirs)) {
return false;
}
if (mine.length != theirs.length) {
return false;
}
for (int i = 0; i < mine.length; i++) {
if (mine[i] != theirs[i]) {
return false;
}
}
return true;
}
protected <L extends List<I>, I> List<String> check(L mine, L theirs, String type, CompareRef<I> dc) {
List<String> ret = new ArrayList<String>();
if (mine != null && theirs != null) {
// both exist - compare
if (mine.size() != theirs.size()) {
ret.add("The number of " + type + " differ: " + mine.size() + ", " + theirs.size());
} else {
// they could match
for (int i = 0; i < mine.size(); ++i) {
ret.addAll(dc.passThru(mine.get(i), theirs.get(i)));
}
}
}
if ((mine != null && theirs == null) || mine == null && theirs != null) {
// one of us exists - problem
ret.add("The list of " + type + " differ");
} else {
// we're both null - ok
}
return ret;
}
}