package edu.cmu.sv.arinc838.builder;
import java.io.IOException;
import java.util.List;
import com.arinc.arinc838.FileDefinition;
import com.arinc.arinc838.IntegrityDefinition;
import com.arinc.arinc838.SdfFile;
import com.arinc.arinc838.SoftwareDescription;
import com.arinc.arinc838.ThwDefinition;
import edu.cmu.sv.arinc838.binary.BdfFile;
import edu.cmu.sv.arinc838.crc.CrcCalculator;
import edu.cmu.sv.arinc838.dao.FileDefinitionDao;
import edu.cmu.sv.arinc838.dao.IntegrityDefinitionDao;
import edu.cmu.sv.arinc838.dao.IntegrityDefinitionDao.IntegrityType;
import edu.cmu.sv.arinc838.dao.SoftwareDefinitionFileDao;
import edu.cmu.sv.arinc838.dao.SoftwareDescriptionDao;
import edu.cmu.sv.arinc838.dao.TargetHardwareDefinitionDao;
public class SoftwareDefinitionFileBuilder implements
Builder<SoftwareDefinitionFileDao, SdfFile> {
private final BuilderFactory builderFactory;
public SoftwareDefinitionFileBuilder(BuilderFactory builderFact) {
this.builderFactory = builderFact;
}
@Override
public SdfFile buildXml(SoftwareDefinitionFileDao softwareDefinitionFileDao) {
SdfFile file = new SdfFile();
file.setFileFormatVersion(softwareDefinitionFileDao
.getFileFormatVersion());
// we have to re-validate this as a LIST1 since it can be modified
// without a set method to verify its validity prior to building
List<FileDefinitionDao> fileDefsValidated = softwareDefinitionFileDao
.getFileDefinitions();
Builder<FileDefinitionDao, FileDefinition> fileDefBuilder = builderFactory
.getBuilder(FileDefinitionDao.class, FileDefinition.class);
for (FileDefinitionDao fileDef : fileDefsValidated) {
file.getFileDefinitions().add(fileDefBuilder.buildXml(fileDef));
}
Builder<TargetHardwareDefinitionDao, ThwDefinition> thwDefBuilder = builderFactory
.getBuilder(TargetHardwareDefinitionDao.class,
ThwDefinition.class);
for (TargetHardwareDefinitionDao thwDef : softwareDefinitionFileDao
.getTargetHardwareDefinitions()) {
file.getThwDefinitions().add(thwDefBuilder.buildXml(thwDef));
}
Builder<IntegrityDefinitionDao, IntegrityDefinition> integDefBuilder = builderFactory
.getBuilder(IntegrityDefinitionDao.class,
IntegrityDefinition.class);
file.setLspIntegrityDefinition(integDefBuilder
.buildXml(softwareDefinitionFileDao.getLspIntegrityDefinition()));
file.setSdfIntegrityDefinition(integDefBuilder
.buildXml(softwareDefinitionFileDao.getSdfIntegrityDefinition()));
file.setSoftwareDescription(builderFactory.getBuilder(
SoftwareDescriptionDao.class, SoftwareDescription.class)
.buildXml(softwareDefinitionFileDao.getSoftwareDescription()));
return file;
}
@Override
public int buildBinary(SoftwareDefinitionFileDao softwareDefinitionFileDao,
BdfFile file) throws IOException, IllegalArgumentException {
if (file.length() != 0) {
throw new IllegalArgumentException();
}
file.seek(0);
// write the header
file.writePlaceholder(); // file size
file.writeHexbin32(softwareDefinitionFileDao.getFileFormatVersion());
file.writePlaceholder(); // software description pointer
file.writePlaceholder(); // target hardware definition pointer
file.writePlaceholder(); // file definition pointer
file.writePlaceholder(); // SDF integrity definition pointer
file.writePlaceholder(); // LSP integrity definition pointer
Builder<SoftwareDescriptionDao, SoftwareDescription> swDescBuilder = builderFactory
.getBuilder(SoftwareDescriptionDao.class,
SoftwareDescription.class);
swDescBuilder.buildBinary(
softwareDefinitionFileDao.getSoftwareDescription(), file);
// Write the target hardware definitions
int size = softwareDefinitionFileDao.getTargetHardwareDefinitions()
.size();
file.writeTargetDefinitionsPointer();
file.writeUint32(size);
Builder<TargetHardwareDefinitionDao, ThwDefinition> targetHardwareDefinitionBuilder = builderFactory
.getBuilder(TargetHardwareDefinitionDao.class,
ThwDefinition.class);
if (size > 0) {
softwareDefinitionFileDao.getTargetHardwareDefinitions()
.get(size - 1).setIsLast(true);
for (int i = 0; i < size; i++) {
targetHardwareDefinitionBuilder.buildBinary(
softwareDefinitionFileDao
.getTargetHardwareDefinitions().get(i), file);
}
}
// write the file definitions
size = softwareDefinitionFileDao.getFileDefinitions().size();
file.writeFileDefinitionsPointer();
file.writeUint32(size);
softwareDefinitionFileDao.getFileDefinitions().get(size - 1)
.setIsLast(true);
Builder<FileDefinitionDao, FileDefinition> fileDefBuilder = builderFactory
.getBuilder(FileDefinitionDao.class, FileDefinition.class);
for (int i = 0; i < size; i++) {
fileDefBuilder.buildBinary(softwareDefinitionFileDao
.getFileDefinitions().get(i), file);
}
Builder<IntegrityDefinitionDao, IntegrityDefinition> integDefBuilder = builderFactory
.getBuilder(IntegrityDefinitionDao.class,
IntegrityDefinition.class);
// write the SDF integrity def
file.writeSdfIntegrityDefinitionPointer();
int sdfCrcByteCount = IntegrityType.fromLong(
softwareDefinitionFileDao.getSdfIntegrityDefinition()
.getIntegrityType()).getByteCount();
softwareDefinitionFileDao.getSdfIntegrityDefinition()
.setIntegrityValue(new byte[sdfCrcByteCount]);
integDefBuilder.buildBinary(
softwareDefinitionFileDao.getSdfIntegrityDefinition(), file);
// write the LSP integrity def
file.writeLspIntegrityDefinitionPointer();
int lspCrcByteCount = IntegrityType.fromLong(
softwareDefinitionFileDao.getLspIntegrityDefinition()
.getIntegrityType()).getByteCount();
softwareDefinitionFileDao.getLspIntegrityDefinition()
.setIntegrityValue(new byte[lspCrcByteCount]);
integDefBuilder.buildBinary(
softwareDefinitionFileDao.getLspIntegrityDefinition(), file);
// write the file size
file.seek(0);
file.writeUint32(file.length());
file.seek(file.length());
writeSdfIntegrityDefinitionCrc(softwareDefinitionFileDao, file);
writeLspIntegrityDefinitionCrc(softwareDefinitionFileDao, file);
return (int) file.length();
}
private void writeSdfIntegrityDefinitionCrc(SoftwareDefinitionFileDao sdf,
BdfFile bdf) throws IOException {
byte[] crc = CrcCalculator.calculateSdfCrc(sdf, bdf);
sdf.getSdfIntegrityDefinition().setIntegrityValue(crc);
// Seek to the SDF integrity pointer, plus 6 bytes (4 for type + 2 for
// size)
bdf.seek(bdf.readSdfIntegrityDefinitionPointer() + 6);
bdf.write(sdf.getSdfIntegrityDefinition().getIntegrityValue());
}
private void writeLspIntegrityDefinitionCrc(SoftwareDefinitionFileDao sdf,
BdfFile bdf) throws IOException {
byte[] crc = CrcCalculator.calculateLspCrc(sdf, bdf);
sdf.getLspIntegrityDefinition().setIntegrityValue(crc);
// Seek to the LSP integrity pointer, plus 6 bytes (4 for type + 2 for
// size)
bdf.seek(bdf.readLspIntegrityDefinitionPointer() + 6);
bdf.write(sdf.getLspIntegrityDefinition().getIntegrityValue());
}
}