blob: cb475f54a21f6be2fcd5b80b3bf7e33a1cb03848 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.trevni;
import java.io.IOException;
import java.io.Closeable;
import java.io.File;
import java.util.Arrays;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
/** Reads data from a column file. */
public class ColumnFileReader implements Closeable {
private Input file;
private long rowCount;
private int columnCount;
private ColumnFileMetaData metaData;
private ColumnDescriptor[] columns;
private Map<String,ColumnDescriptor> columnsByName;
/** Construct reading from the named file. */
public ColumnFileReader(File file) throws IOException {
this(new InputFile(file));
}
/** Construct reading from the provided input. */
public ColumnFileReader(Input file) throws IOException {
this.file = file;
readHeader();
}
/** Return the number of rows in this file. */
public long getRowCount() { return rowCount; }
/** Return the number of columns in this file. */
public long getColumnCount() { return columnCount; }
/** Return this file's metadata. */
public ColumnFileMetaData getMetaData() { return metaData; }
/** Return all columns' metadata. */
public ColumnMetaData[] getColumnMetaData() {
ColumnMetaData[] result = new ColumnMetaData[columnCount];
for (int i = 0; i < columnCount; i++)
result[i] = columns[i].metaData;
return result;
}
/** Return root columns' metadata. Roots are columns that have no parent. */
public List<ColumnMetaData> getRoots() {
List<ColumnMetaData> result = new ArrayList<ColumnMetaData>();
for (int i = 0; i < columnCount; i++)
if (columns[i].metaData.getParent() == null)
result.add(columns[i].metaData);
return result;
}
/** Return a column's metadata. */
public ColumnMetaData getColumnMetaData(int number) {
return columns[number].metaData;
}
/** Return a column's metadata. */
public ColumnMetaData getColumnMetaData(String name) {
return getColumn(name).metaData;
}
private <T extends Comparable> ColumnDescriptor<T> getColumn(String name) {
ColumnDescriptor column = columnsByName.get(name);
if (column == null)
throw new TrevniRuntimeException("No column named: "+name);
return (ColumnDescriptor<T>)column;
}
private void readHeader() throws IOException {
InputBuffer in = new InputBuffer(file, 0);
readMagic(in);
this.rowCount = in.readFixed64();
this.columnCount = in.readFixed32();
this.metaData = ColumnFileMetaData.read(in);
this.columnsByName = new HashMap<String,ColumnDescriptor>(columnCount);
columns = new ColumnDescriptor[columnCount];
readColumnMetaData(in);
readColumnStarts(in);
}
private void readMagic(InputBuffer in) throws IOException {
byte[] magic = new byte[ColumnFileWriter.MAGIC.length];
try {
in.readFully(magic);
} catch (IOException e) {
throw new IOException("Not a data file.");
}
if (!(Arrays.equals(ColumnFileWriter.MAGIC, magic)
|| !Arrays.equals(ColumnFileWriter.MAGIC_1, magic)
|| !Arrays.equals(ColumnFileWriter.MAGIC_0, magic)))
throw new IOException("Not a data file.");
}
private void readColumnMetaData(InputBuffer in) throws IOException {
for (int i = 0; i < columnCount; i++) {
ColumnMetaData meta = ColumnMetaData.read(in, this);
meta.setDefaults(this.metaData);
ColumnDescriptor column = new ColumnDescriptor(file, meta);
columns[i] = column;
meta.setNumber(i);
columnsByName.put(meta.getName(), column);
}
}
private void readColumnStarts(InputBuffer in) throws IOException {
for (int i = 0; i < columnCount; i++)
columns[i].start = in.readFixed64();
}
/** Return an iterator over values in the named column. */
public <T extends Comparable> ColumnValues<T> getValues(String columnName)
throws IOException {
return new ColumnValues<T>(getColumn(columnName));
}
/** Return an iterator over values in a column. */
public <T extends Comparable> ColumnValues<T> getValues(int column)
throws IOException {
return new ColumnValues<T>(columns[column]);
}
@Override public void close() throws IOException {
file.close();
}
}