/*
* Copyright (C) 2015 by Array Systems Computing Inc. http://www.array.ca
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.s1tbx.io.sentinel1;
import org.esa.s1tbx.io.FileImageInputStreamExtImpl;
import org.esa.s1tbx.io.binary.BinaryFileReader;
import org.esa.s1tbx.io.binary.IllegalBinaryFormatException;
import org.esa.snap.core.datamodel.MetadataAttribute;
import org.esa.snap.core.datamodel.MetadataElement;
import org.esa.snap.core.datamodel.ProductData;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.imageio.stream.ImageInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* TBD
*/
public class Sentinel1Level0Reader {
private final String SUPPORT_FOLDER_NAME = "support";
private final String ANNOT_SCHEMA_FILENAME = "s1-level-0-annot.xsd";
private final String INDEX_SCHEMA_FILENAME = "s1-level-0-index.xsd";
// Prefixes used in filename
private final String ANNOT_PREFIX = "-annot";
private final String INDEX_PREFIX = "-index";
// Content of attribute "name" in tag "xs:complexType"
private final String ANNOT_RECORD_NAME = "annotRecordType";
private final String INDEX_RECORD_NAME = "block";
// Tag names
private final String SIMPLE_TYPE_TAG_NAME = "xs:simpleType";
private final String COMPLEX_TYPE_TAG_NAME = "xs:complexType";
private final String SEQUENCE_TAG_NAME = "xs:sequence";
private final String ELEMENT_TAG_NAME = "xs:element";
private final String RESTRICTION_TAG_NAME = "xs:restriction";
private final String ANNOTATION_TAG_NAME = "xs:annotation";
private final String APPINFO_TAG_NAME = "xs:appinfo";
private final String BLOCK_TAG_NAME = "sdf:block";
private final String LENGTH_TAG_NAME = "sdf:length";
private final String OCCURRENCE_TAG_NAME = "sdf:occurrence";
// Base types
private final String BOOLEAN_TAG_NAME = "xs:boolean"; // 1 byte
private final String UNSIGNED_BYTE_TAG_NAME = "xs:unsignedByte"; // 1 byte
private final String UNSIGNED_SHORT_TAG_NAME = "xs:unsignedShort"; // 2 bytes
private final String UNSIGNED_INT_TAG_NAME = "xs:unsignedInt"; // 4 bytes
private final String UNSIGNED_LONG_TAG_NAME = "xs:unsignedLong"; // 8 bytes
private final String DOUBLE_TAG_NAME = "xs:double"; // 8 bytes
private final List<String> baseTypeTagNameList = Arrays.asList(BOOLEAN_TAG_NAME,
UNSIGNED_BYTE_TAG_NAME,
UNSIGNED_SHORT_TAG_NAME,
UNSIGNED_INT_TAG_NAME,
UNSIGNED_LONG_TAG_NAME,
DOUBLE_TAG_NAME);
private final String BIT_BASE_TYPE = "BIT_BASE_TYPE";
// Attributes in tags
private final String NAME_ATTRIBUTE = "name";
private final String TYPE_ATTRIBUTE = "type";
private final String BASE_ATTRIBUTE = "base";
private final String UNIT_ATTRIBUTE = "unit";
private final class DataElement {
private final String name; // content of attribute "name"
private final String type; // content of attribute "type"
private final String baseType; // must be one of what are in baseTypeTagNameList or BIT_BASE_TYPE
private final int numBytes; // number of bytes in this data element (should agree with baseType);
// if baseType == BIT_BASE_TYPE, then numBytes is number of bits
private final int startBit; // applicable only if baseType == BIT_BASE_TYPE
private final int numOccurrences; // number of occurrences of this data element
DataElement(final String name, final String type, final String baseType, final int numBytes, final int startBit, final int numOccurrences) {
this.name = name;
this.type = type;
this.baseType = baseType;
this.numBytes = numBytes;
this.startBit = startBit;
this.numOccurrences = numOccurrences;
}
private void dump() {
System.out.println(" name = " + name + "; type = " + type + "; baseType = " + baseType + "; numBytes = " + numBytes + "; startBit = " + startBit + "; numOccurrences = " + numOccurrences);
}
}
private ArrayList<DataElement> annotElemList = new ArrayList<>();
private ArrayList<DataElement> indexElemList = new ArrayList<>();
private class DataComponent {
private final BinaryFileReader reader;
private final ArrayList<DataElement> elemList;
private final MetadataElement parentMetadataElem;
private final long numRecords;
DataComponent(final BinaryFileReader reader, final ArrayList<DataElement> elemList, final MetadataElement parentMetadataElem, final long numRecords) {
this.reader = reader;
this.elemList = elemList;
this.parentMetadataElem = parentMetadataElem;
this.numRecords = numRecords;
}
}
private ArrayList<DataComponent> dataComponents = new ArrayList<>();
public Sentinel1Level0Reader(final File baseDir, final MetadataElement originalProductMetadata) {
readXMLSchema(buildSchemaFilename(baseDir, ANNOT_SCHEMA_FILENAME), ANNOT_RECORD_NAME, annotElemList);
readXMLSchema(buildSchemaFilename(baseDir, INDEX_SCHEMA_FILENAME), INDEX_RECORD_NAME, indexElemList);
// Metadata > Original_Product_Metadata > XFDU > dataObjectSection >
// dataObject > byteStream > fileLocation
final MetadataElement dataObjectSection = originalProductMetadata.getElement("XFDU").getElement("dataObjectSection");
final MetadataElement annotElem = new MetadataElement("Annotation Data Components");
originalProductMetadata.addElement(annotElem);
final MetadataElement indexElem = new MetadataElement("Index Data Components");
originalProductMetadata.addElement(indexElem);
final MetadataElement measurementDataElem = new MetadataElement("Measurement Data Components");
originalProductMetadata.addElement(measurementDataElem);
int numElem = dataObjectSection.getNumElements();
for (int i = 0; i < numElem; i++) {
MetadataElement elem = dataObjectSection.getElementAt(i).getElement("byteStream");
String dataFilename = elem.getElement("fileLocation").getAttributeString("href");
MetadataElement recordElem = dataFilename.contains(INDEX_PREFIX) ? new MetadataElement("blocks") : new MetadataElement("records");
//System.out.println("Sentinel1Level0Reader: " + dataFilename);
MetadataElement componentElem;
if (dataFilename.contains(ANNOT_PREFIX)) {
componentElem = new MetadataElement(extractPolarization(dataFilename) + "annotation");
annotElem.addElement(componentElem);
} else if (dataFilename.contains(INDEX_PREFIX)) {
componentElem = new MetadataElement(extractPolarization(dataFilename) + "index");
indexElem.addElement(componentElem);
} else {
componentElem = new MetadataElement(extractPolarization(dataFilename) + "measurement_data");
measurementDataElem.addElement(componentElem);
}
final MetadataAttribute nameAttr = new MetadataAttribute("filename", ProductData.TYPE_ASCII);
componentElem.addAttribute(nameAttr);
nameAttr.getData().setElems(dataFilename);
final MetadataAttribute numRecsAttr = new MetadataAttribute("number of " + recordElem.getName(), ProductData.TYPE_UINT32);
componentElem.addAttribute(numRecsAttr);
componentElem.addElement(recordElem);
if (dataFilename.contains(ANNOT_PREFIX) || dataFilename.contains(INDEX_PREFIX)) {
final long numRecs = createBinaryReader(baseDir, dataFilename, recordElem);
numRecsAttr.getData().setElemUInt(numRecs);
}
// TODO handle measurement data
}
}
private long createBinaryReader(final File baseDir, final String binDataFilename, MetadataElement metadataElement) {
final File binDataFile = new File(baseDir.getAbsolutePath() + binDataFilename);
long numRecs = 0;
try {
ImageInputStream imageInputStream = FileImageInputStreamExtImpl.createInputStream(binDataFile);
final BinaryFileReader binaryReader = new BinaryFileReader(imageInputStream);
// According to Product Specs, binary data is stored in Big Endian format.
binaryReader.setByteOrder(ByteOrder.BIG_ENDIAN);
DataComponent dataComponent = null;
final long filesize = binDataFile.length(); // bytes
if (binDataFilename.contains(ANNOT_PREFIX)) {
numRecs = filesize / getTotalNumberOfBytes(annotElemList);
dataComponent = new DataComponent(binaryReader, annotElemList, metadataElement, numRecs);
} else if (binDataFilename.contains(INDEX_PREFIX)) {
numRecs = filesize / getTotalNumberOfBytes(indexElemList);
dataComponent = new DataComponent(binaryReader, indexElemList, metadataElement, numRecs);
}
dataComponents.add(dataComponent);
} catch (IOException e) {
System.out.println("Sentinel1Level0Reader.createBinaryReader: IOException " + e.getMessage());
}
return numRecs;
}
private String buildSchemaFilename(final File baseDir, final String schemaName) {
return baseDir.getAbsolutePath() + File.separator + SUPPORT_FOLDER_NAME + File.separator + schemaName;
}
private void readXMLSchema(final String filename, final String recordName, ArrayList<DataElement> elemList) {
final File xmlFile = new File(filename);
try {
DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
Document doc = documentBuilder.parse(xmlFile);
if (doc == null) {
System.out.println("Sentinel1Level0Reader.readXMLSchema: ERROR failed to create Document for XML schema");
return;
}
doc.getDocumentElement().normalize();
org.w3c.dom.Node recNode;
// Look for a complexType tag in the XML file with name attribute == recordName
// Inside this tag, there should be a sequence tag containing all the elements in one record of the
// data component.
recNode = getNodeFromDocument(doc, COMPLEX_TYPE_TAG_NAME, recordName);
if (recNode == null) {
System.out.println("Sentinel1Level0Reader.readXMLSchema: ERROR failed to find " + COMPLEX_TYPE_TAG_NAME + " in schema");
return;
}
org.w3c.dom.Node sequenceNode = getNodeFromNode(recNode, SEQUENCE_TAG_NAME);
if (sequenceNode == null) {
System.out.println("Sentinel1Level0Reader.readXMLSchema: ERROR failed to find " + SEQUENCE_TAG_NAME + " in schema");
return;
}
getElementsInRecord(sequenceNode, elemList);
//dumpElemList(recordName, elemList);
} catch (IOException e) {
System.out.println("Sentinel1Level0Reader.readXMLSchema: IOException " + e.getMessage());
} catch (ParserConfigurationException e) {
System.out.println("Sentinel1Level0Reader.readXMLSchema: ParserConfigurationException " + e.getMessage());
} catch (SAXException e) {
System.out.println("Sentinel1Level0Reader.readXMLSchema: SAXException " + e.getMessage());
}
}
private org.w3c.dom.Node getNodeFromDocument(final Document doc, final String nodeType, final String nodeName) {
// Will look for tag with name == nodeType whose attribute name == nodeName.
// This will return a list of all tags with name == nodeType
NodeList nodeList = doc.getElementsByTagName(nodeType);
org.w3c.dom.Node recNode = null;
// Then we loop each tag with the same tag name which is nodeType
for (int i = 0; i < nodeList.getLength(); i++) {
org.w3c.dom.Node node = nodeList.item(i);
//System.out.println(" Record name " + node.getNodeName());
// Get all the attributes in the tag
NamedNodeMap attr = node.getAttributes();
// Loop through each attribute to look for NAME_ATTRIBUTE and check if it is equal to nodeName
for (int j = 0; j < attr.getLength(); j++) {
if (attr.item(j).getNodeName().equals(NAME_ATTRIBUTE) && attr.item(j).getTextContent().contains(nodeName)) {
//System.out.println(" found : " + attr.item(j).getTextContent());
if (recNode == null) {
recNode = node;
} else {
System.out.println("Sentinel1Level0Reader.getNodeFromDocument: WARNING more than one " + nodeName + " of type " + nodeType + " in " + doc.getDocumentURI());
}
}
}
}
return recNode;
}
private org.w3c.dom.Node getNodeFromNode(final org.w3c.dom.Node parentNode, final String nodeName) {
// Will look for node with tag name == nodeName in parentNode
org.w3c.dom.Node node = null;
NodeList childNodes = parentNode.getChildNodes();
// Loop through all child nodes and look for the child whose name == nodeName
for (int i = 0; i < childNodes.getLength(); i++) {
org.w3c.dom.Node child = childNodes.item(i);
//System.out.println(" child name " + child.getNodeName());
if (child.getNodeName().equals(nodeName)) {
if (node == null) {
//System.out.println("Sentinel1Level0Reader: found " + nodeName + " in " + parentNode.getNodeName());
node = child;
} else {
System.out.println("Sentinel1Level0Reader.getNodeFromNode: WARNING more than one " + nodeName + " in " + parentNode.getNodeName());
}
}
}
return node;
}
private org.w3c.dom.Node getNodeFromNode(final org.w3c.dom.Node parentNode, final String[] nodeNames) {
// Will look for node at the end of a branch defined by a sequence of nodes.
org.w3c.dom.Node node = parentNode;
for (String n : nodeNames) {
node = getNodeFromNode(node, n);
}
return node;
}
private org.w3c.dom.Node getAttributeFromNode(final org.w3c.dom.Node node, final String attrName) {
// Will look for attribute called attrName in the given node
NamedNodeMap attr = node.getAttributes();
org.w3c.dom.Node attrNode = null;
for (int j = 0; j < attr.getLength(); j++) {
//System.out.println(" attribute = " + attr.item(j).getNodeName());
if (attr.item(j).getNodeName().equals(attrName)) {
if (attrNode == null) {
attrNode = attr.item(j);
} else {
// Should not be possible
System.out.println("Sentinel1Level0Reader.getAttributeFromNode: WARNING more than one " + attrName + " in " + node.getNodeName());
}
}
}
return attrNode;
}
private boolean isBaseType(final org.w3c.dom.Node node, final String type, final int[] numBytes, final int[] numOccurrence) {
if (baseTypeTagNameList.contains(type)) {
numBytes[0] = -1;
numOccurrence[0] = 1;
String[] nodeNames = {ANNOTATION_TAG_NAME, APPINFO_TAG_NAME, BLOCK_TAG_NAME};
org.w3c.dom.Node blockNode = getNodeFromNode(node, nodeNames);
if (blockNode == null) {
System.out.println("Sentinel1Level0Reader.getOccurrencesAndLength: no block in " + node.getNodeName());
return true;
}
org.w3c.dom.Node occurrenceNode = getNodeFromNode(blockNode, OCCURRENCE_TAG_NAME);
if (occurrenceNode != null) {
numOccurrence[0] = Integer.parseInt(occurrenceNode.getTextContent());
} else {
System.out.println("Sentinel1Level0Reader.getOccurrencesAndLength: no occurrence in " + node.getNodeName());
}
org.w3c.dom.Node lengthNode = getNodeFromNode(blockNode, LENGTH_TAG_NAME);
if (lengthNode != null) {
numBytes[0] = Integer.parseInt(lengthNode.getTextContent());
} else {
System.out.println("Sentinel1Level0Reader.getOccurrencesAndLength: no length in " + node.getNodeName());
}
return true;
}
return false;
}
private String getBaseType(final Document doc, String type, final int[] numBytes) {
// Returns base type and output numBytes
String baseType = "";
numBytes[0] = -1;
org.w3c.dom.Node typeNode;
// Look for simpleType whose name == type in schema
typeNode = getNodeFromDocument(doc, SIMPLE_TYPE_TAG_NAME, type);
if (typeNode != null) {
org.w3c.dom.Node restrictionNode = getNodeFromNode(typeNode, RESTRICTION_TAG_NAME);
if (restrictionNode == null) {
System.out.println("Sentinel1Level0Reader.getBaseType: failed to find " + RESTRICTION_TAG_NAME + " in " + typeNode.getNodeName());
return baseType;
}
org.w3c.dom.Node baseTypeNode = getAttributeFromNode(restrictionNode, BASE_ATTRIBUTE);
if (baseTypeNode == null) {
System.out.println("Sentinel1Level0Reader.getBaseType: failed to find " + BASE_ATTRIBUTE + " in " + restrictionNode.getNodeName());
return baseType;
}
baseType = baseTypeNode.getTextContent();
String[] nodeNames = {ANNOTATION_TAG_NAME, APPINFO_TAG_NAME, BLOCK_TAG_NAME, LENGTH_TAG_NAME};
org.w3c.dom.Node lengthNode = getNodeFromNode(typeNode, nodeNames);
if (lengthNode == null) {
System.out.println("Sentinel1Level0Reader.getBaseType: failed to find " + LENGTH_TAG_NAME + " in branch of " + typeNode.getNodeName());
return baseType;
}
numBytes[0] = Integer.parseInt(lengthNode.getTextContent());
org.w3c.dom.Node unitNode = getAttributeFromNode(lengthNode, UNIT_ATTRIBUTE);
// It is valid for unitNode to be null in which case unit of length is bytes
if (unitNode != null && unitNode.getTextContent().equals("bit")) {
baseType = BIT_BASE_TYPE;
}
} else {
System.out.println("Sentinel1Level0Reader.getBaseType: ERROR missing " + SIMPLE_TYPE_TAG_NAME + " in " + doc.getDocumentURI());
}
return baseType;
}
private void getElementsInRecord(final org.w3c.dom.Node sequenceNode, final ArrayList<DataElement> elemList) {
NodeList childNodes = sequenceNode.getChildNodes();
DataElement prevDataElem = null;
for (int i = 0; i < childNodes.getLength(); i++) {
org.w3c.dom.Node child = childNodes.item(i);
//System.out.println(" child name " + child.getNodeName());
if (child.getNodeName().equals(ELEMENT_TAG_NAME)) {
String elemName = "";
String elemType = "";
String elemBaseType = "";
int[] elemNumOccurrences = new int[1];
int[] elemNumBytes = new int[1];
int startBit = -1;
NamedNodeMap attr = child.getAttributes();
for (int j = 0; j < attr.getLength(); j++) {
//System.out.println(" attribute = " + attr.item(j).getNodeName());
if (attr.item(j).getNodeName().equals(NAME_ATTRIBUTE)) {
elemName = attr.item(j).getTextContent();
} else if (attr.item(j).getNodeName().equals(TYPE_ATTRIBUTE)) {
elemType = attr.item(j).getTextContent();
}
}
if (isBaseType(child, elemType, elemNumBytes, elemNumOccurrences)) {
elemBaseType = elemType;
} else {
elemNumOccurrences[0] = 1;
elemBaseType = getBaseType(sequenceNode.getOwnerDocument(), stripNamespace(elemType), elemNumBytes);
}
if (elemBaseType.equals(BIT_BASE_TYPE)) {
if (prevDataElem == null) {
startBit = 0;
} else if (prevDataElem.baseType.equals(BIT_BASE_TYPE)) {
final int prevEndBit = prevDataElem.startBit + prevDataElem.numBytes - 1;
if (prevEndBit >= 7) {
startBit = 0;
} else {
startBit = prevEndBit + 1;
}
} else {
startBit = 0;
}
}
DataElement dataElement = new DataElement(elemName, elemType, elemBaseType, elemNumBytes[0], startBit, elemNumOccurrences[0]);
elemList.add(dataElement);
prevDataElem = dataElement;
}
}
}
private String stripNamespace(final String name) {
return name.substring(name.lastIndexOf(":") + 1);
}
private void dumpElemList(final String listName, final ArrayList<DataElement> elemList) {
System.out.println("Start of " + listName);
for (DataElement dataElement : elemList) {
dataElement.dump();
}
System.out.println("End of " + listName);
}
public void readData() {
//System.out.println("Sentinel1Level0Reader.readData: called");
for (DataComponent d : dataComponents) {
//System.out.println("Sentinel1Level0Reader.readData: read one data component");
readBinaryData(d);
}
}
private byte readOneBinaryElement(final BinaryFileReader reader,
final DataElement elem,
final DataElement prevElem,
final byte prevByte,
MetadataElement parentMetadataElem) {
//System.out.println("Sentinel1Level0Reader.readOneBinaryElement: read " + elem.name + " " + elem.baseType);
byte lastByteRead = 0;
try {
switch (elem.baseType) {
case BOOLEAN_TAG_NAME:
case UNSIGNED_BYTE_TAG_NAME: {
final int val = reader.readUB1();
//System.out.println(elem.name + " = " + val + "; " + elem.baseType + " (unsigned byte); pos = " + reader.getCurrentPos());
MetadataAttribute attr = new MetadataAttribute(elem.name, ProductData.TYPE_UINT8);
ProductData productData = attr.getData();
productData.setElemInt(val);
parentMetadataElem.addAttribute(attr);
}
break;
case UNSIGNED_SHORT_TAG_NAME: {
final int val = reader.readUB2();
//System.out.println(elem.name + " = " + val + "; " + elem.baseType + " (unsigned short); pos = " + reader.getCurrentPos());
MetadataAttribute attr = new MetadataAttribute(elem.name, ProductData.TYPE_UINT16);
ProductData productData = attr.getData();
productData.setElemInt(val);
parentMetadataElem.addAttribute(attr);
}
break;
case UNSIGNED_INT_TAG_NAME: {
final long val = getUnsignedInt(reader.readB4());
//System.out.println(elem.name + " = " + val + "; " + elem.baseType + " (unsigned int); pos = " + reader.getCurrentPos());
MetadataAttribute attr = new MetadataAttribute(elem.name, ProductData.TYPE_UINT32);
ProductData productData = attr.getData();
productData.setElemUInt(val);
parentMetadataElem.addAttribute(attr);
}
break;
case UNSIGNED_LONG_TAG_NAME: {
final byte[] bytes = new byte[8];
reader.read(bytes);
final BigInteger val = new BigInteger(bytes);
final String valStr = String.valueOf(val);
//System.out.println(elem.name + " = " + val + "; " + elem.baseType + " (unsigned long); pos = " + reader.getCurrentPos());
MetadataAttribute attr = new MetadataAttribute(elem.name, ProductData.TYPE_ASCII);
ProductData productData = attr.getData();
productData.setElems(valStr);
parentMetadataElem.addAttribute(attr);
// To get back the unsigned long value, one can get the String back and create a BigInteger with it.
// Constructor of BigInteger takes a String.
}
break;
case DOUBLE_TAG_NAME: {
final double val = (double) reader.readB8();
//System.out.println(elem.name + " = " + val + "; " + elem.baseType + " (double); pos" + reader.getCurrentPos());
MetadataAttribute attr = new MetadataAttribute(elem.name, ProductData.TYPE_FLOAT64);
ProductData productData = attr.getData();
productData.setElemDouble(val);
parentMetadataElem.addAttribute(attr);
}
break;
case BIT_BASE_TYPE: {
if (prevElem == null || elem.startBit == 0) {
final byte[] oneByte = new byte[1];
reader.read(oneByte);
lastByteRead = oneByte[0];
//System.out.println(elem.name + " = " + Integer.toBinaryString(getInteger(lastByteRead)) + "; " + elem.baseType + " (unsigned int); pos = " + reader.getCurrentPos());
} else {
lastByteRead = prevByte;
}
final byte val = extract(lastByteRead, elem.startBit, elem.numBytes);
MetadataAttribute attr = new MetadataAttribute(elem.name, ProductData.TYPE_UINT8);
ProductData productData = attr.getData();
productData.setElemInt(getInteger(val));
parentMetadataElem.addAttribute(attr);
}
break;
default: {
System.out.println("Sentinel1Level0Reader.readOneBinaryElement: ERROR Unknown baseType = " + elem.baseType);
}
break;
}
} catch (IOException e) {
System.out.println("Sentinel1Level0Reader.readOneBinaryElement: IOException " + e.getMessage());
} catch (IllegalBinaryFormatException e) {
System.out.println("Sentinel1Level0Reader.readOneBinaryElement: IllegalBinaryFormatException " + e.getMessage());
}
return lastByteRead;
}
private void readBinaryData(DataComponent dataComponent) {
final BinaryFileReader reader = dataComponent.reader;
final ArrayList<DataElement> elemList = dataComponent.elemList;
final MetadataElement parentMetadataElem = dataComponent.parentMetadataElem;
for (long i = 0; i < dataComponent.numRecords; i++) {
final String parentName = parentMetadataElem.getName();
final MetadataElement recMetaElem = new MetadataElement(parentName.substring(0, parentName.length() - 1) + i);
parentMetadataElem.addElement(recMetaElem);
/*
try {
System.out.println("readBinaryData: file pos = " + reader.getCurrentPos());
} catch (IOException e) {
System.out.println("readBinaryData: file pos = ERROR " + e.getMessage());
}
*/
DataElement prevDataElem = null;
byte prevByte = 0;
for (DataElement elem : elemList) {
for (int j = 0; j < elem.numOccurrences; j++) {
prevByte = readOneBinaryElement(reader, elem, prevDataElem, prevByte, recMetaElem);
prevDataElem = elem;
}
}
}
}
private static long getUnsignedInt(final int x) {
return x & 0x00000000ffffffffL;
}
private static int getInteger(final byte b) {
return b & 0xFF;
}
private static byte extract(final byte b, final int startBit, final int numBits) {
// Assume int is 32-bit, byte is 8-bit
int result = getInteger(b) << startBit + 24;
result = result >>> (32 - numBits);
return (byte) result;
}
private static String extractPolarization(String filename) {
final int idx = filename.lastIndexOf("raw") + 6;
final String pp = filename.substring(idx, idx + 2);
if (pp.equals("hh") || pp.equals("hv") || pp.equals("vv") || pp.equals("vh")) {
return pp + "_";
} else {
return "";
}
}
private int getTotalNumberOfBytes(ArrayList<DataElement> elemList) {
int total = 0;
for (DataElement elem : elemList) {
if (!elem.baseType.equals(BIT_BASE_TYPE)) {
total += (elem.numBytes * elem.numOccurrences);
} else if (elem.startBit == 0) {
total += 1;
}
}
return total;
}
}