
it.bancaditalia.oss.sdmx.api.PortableDataSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sdmx Show documentation
Show all versions of sdmx Show documentation
Sdmx Connectors for Statistical Software
/* Copyright 2010,2015 Bank Of Italy
*
* Licensed under the EUPL, Version 1.1 or - as soon they
* will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the
* Licence.
* You may obtain a copy of the Licence at:
*
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in
* writing, software distributed under the Licence is
* distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the Licence for the specific language governing
* permissions and limitations under the Licence.
*/
package it.bancaditalia.oss.sdmx.api;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
import javax.swing.table.DefaultTableModel;
import it.bancaditalia.oss.sdmx.exceptions.DataStructureException;
import it.bancaditalia.oss.sdmx.util.Configuration;
/**
* Java container for a dataset/table. In the various statistical tools it will be transformed by a converter into a
* native dataset.
*
* @author Attilio Mattiocco
*
*/
public class PortableDataSet implements Serializable
{
private static final long serialVersionUID = 1L;
public static final String TIME_LABEL = "TIME_PERIOD";
public static final String OBS_LABEL = "OBS_VALUE";
public static final String ID_LABEL = "ID";
private static final String sourceClass = PortableDataSet.class.getSimpleName();
protected static Logger logger = Configuration.getSdmxLogger();
private boolean errorFlag = false;
private boolean numeric = false;
private String errorObjects = null;
private DefaultTableModel model = null;
/**
* Creates an empty dataset.
*/
public PortableDataSet()
{
model = new DefaultTableModel();
}
/**
* Creates a dataset from a list of series.
*
* @param tslist A list of series to add to this dataset.
* @throws DataStructureException if there is an error adding series.
*/
public PortableDataSet(List> tslist) throws DataStructureException
{
this();
setTimeSeries(tslist);
}
/**
* Returns the index of a column in this dataset given its name.
*
* @param name A column name
* @return The index of a column with given name in this dataset.
* @throws DataStructureException if the column doesn't exists.
*/
public int getColumnIndex(String name) throws DataStructureException
{
int n = model.getColumnCount();
for (int i = 0; i < n; i++)
{
if (model.getColumnName(i).equals(name))
{
return (i);
}
}
throw new DataStructureException("Error: column " + name + " does not exist.");
}
/**
* @return The number of rows in this dataset.
*/
public int getRowCount()
{
return model.getRowCount();
}
/**
* @return The number of columns in this dataset.
*/
public int getColumnCount()
{
return model.getColumnCount();
}
/**
* Returns the name of a column in this dataset given its index.
*
* @param idx A column index.
* @return The name of the column with given index.
* @throws DataStructureException If the column index is out of bounds.
*/
public String getColumnName(int idx) throws DataStructureException
{
if (idx >= 0 && idx < getColumnCount())
{
return model.getColumnName(idx);
}
else
{
throw new DataStructureException("Error: index exceeds number of actual columns");
}
}
/**
* Gets the value of a dataset cell with specified coordinates.
*
* @param row The row index
* @param column The column index
* @return An object corresponding to a cell in this dataset with given coordinates.
* @throws DataStructureException If row or column indexes are out of bounds.
*/
public Object getValueAt(int row, int column) throws DataStructureException
{
if (row >= 0 && column >= 0 && row < getRowCount() && column < getColumnCount())
{
return model.getValueAt(row, column);
}
else
{
throw new DataStructureException("Error: index exceeds number of actual rows or columns");
}
}
/**
* @return A flattened array containing all observations timestamps for all series in this dataset.
* @throws DataStructureException If any error occurs
*/
public String[] getTimeStamps() throws DataStructureException
{
int rows = getRowCount();
String[] result = new String[rows];
int timeCol = getColumnIndex(TIME_LABEL);
for (int i = 0; i < rows; i++)
{
result[i] = (String) getValueAt(i, timeCol);
}
return (result);
}
/**
* @return A flattened array containing all observations values for all series in this dataset.
* @throws DataStructureException If any error occurs
*/
public Object[] getObservations() throws DataStructureException
{
int rows = getRowCount();
Object[] result = new Object[rows];
int obsCol = getColumnIndex(OBS_LABEL);
for (int i = 0; i < rows; i++)
{
result[i] = getValueAt(i, obsCol);
}
return result;
}
/**
* @param name The name of a metadata attribute.
* @return A flattened array containing all metadata with given name for all series in this dataset, or an empty
* array if the attribute is not found.
*/
public String[] getMetadata(String name)
{
int rows = getRowCount();
String[] result = new String[rows];
try
{
int obsCol = getColumnIndex(name);
for (int i = 0; i < rows; i++)
{
result[i] = (String) getValueAt(i, obsCol);
}
}
catch (DataStructureException e)
{
result = new String[0];
}
return (result);
}
/**
* @return An array containing all metadata attribute names.
* @throws DataStructureException if an error occurs
*/
public String[] getMetadataNames() throws DataStructureException
{
int cols = getColumnCount();
List result = new ArrayList<>();
for (int i = 0; i < cols; i++)
{
String colName = getColumnName(i);
if (!colName.equals(OBS_LABEL) && !colName.equals(TIME_LABEL))
result.add(colName);
}
return result.toArray(new String[0]);
}
/**
* Adds a list of series to this dataset.
*
* @param tslist The list of series to add to this dataset.
* @throws DataStructureException if an error occurs adding the series.
*/
public void setTimeSeries(List> tslist) throws DataStructureException
{
final String sourceMethod = "putTimeSeries";
logger.entering(sourceClass, sourceMethod);
// check if all time series are numeric. Otherwise, convert everything to string
boolean allNumeric = true;
for (PortableTimeSeries> series : tslist)
if (allNumeric && !series.isNumeric())
allNumeric = false;
for (PortableTimeSeries> ts : tslist)
putTimeSeries(ts, allNumeric);
logger.exiting(sourceClass, sourceMethod);
}
/**
* Sets a value for an element in this dataset with given coordinates, expanding the dataset as needed.
*
* @param row The row index of the element which is to receive the value.
* @param columnName The name of the column of the element which is to receive the value.
* @param value The value to set.
* @throws DataStructureException if an error occurs
*/
public void addValue(int row, String columnName, Object value) throws DataStructureException
{
if (row >= model.getRowCount())
{
model.setRowCount(row + 1);
}
int idx = -1;
try
{
idx = getColumnIndex(columnName);
}
catch (DataStructureException e)
{
model.addColumn(columnName);
try
{
idx = getColumnIndex(columnName);
}
catch (DataStructureException e1)
{
logger.severe(e1.getMessage());
throw new DataStructureException("Unexpected error while adding column: " + columnName);
}
}
model.setValueAt(value, row, idx);
}
/**
* @return if any series in this dataset contain an error.
*/
public boolean isErrorFlag()
{
return errorFlag;
}
/**
* @param errorFlag the new error flag status
*/
public void setErrorFlag(boolean errorFlag)
{
this.errorFlag = errorFlag;
}
/**
* @return The concatenated error messages.
*/
public String getErrorObjects()
{
return errorObjects;
}
/**
* @param text a text to concatenate to the error message of this dataset.
*/
public void addErrorObjects(String text)
{
if (this.errorObjects == null || this.errorObjects.isEmpty())
this.errorObjects = text;
else
this.errorObjects += ", " + text;
}
/**
* @return true if all the series in this dataset are numeric.
*/
public boolean isNumeric()
{
return numeric;
}
/**
* @param numeric the new numeric status
*/
public void setNumeric(boolean numeric)
{
this.numeric = numeric;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
int rows = model.getRowCount();
int cols = model.getColumnCount();
String buffer = "";
for (int j = 0; j < cols; j++)
{
if (j != 0)
{
buffer += ";";
}
buffer += model.getColumnName(j);
}
buffer += "\n";
for (int i = 0; i < rows; i++)
{
if (i != 0)
{
buffer += "\n";
}
for (int j = 0; j < cols; j++)
{
if (j != 0)
{
buffer += ";";
}
buffer += model.getValueAt(i, j);
}
}
return buffer;
}
private void putTimeSeries(PortableTimeSeries> ts, boolean allNumeric) throws DataStructureException
{
final String sourceMethod = "putTimeSeries";
logger.entering(sourceClass, sourceMethod);
int row = model.getRowCount();
setNumeric(allNumeric);
Set attrNames = ts.getObsLevelAttributesNames();
String tsName = ts.getName();
// check errors
if (ts.isErrorFlag())
{
errorFlag = true;
addErrorObjects(tsName);
}
// model.setRowCount(row + n);
for (BaseObservation> obs : ts)
{
Object val = allNumeric && ts.isNumeric() ? obs.getValueAsDouble() : obs.getValue();
addValue(row, TIME_LABEL, obs.getTimeslot());
addValue(row, OBS_LABEL, val);
if (tsName != null && !tsName.isEmpty())
addValue(row, ID_LABEL, tsName);
// set obs level attributes
for (String attrName : attrNames)
addValue(row, attrName, obs.getAttributeValue(attrName));
// set dimensions
for (Entry dim : ts.getDimensionsMap().entrySet())
addValue(row, dim.getKey(), dim.getValue());
// set attributes
for (Entry dim : ts.getAttributesMap().entrySet())
addValue(row, dim.getKey(), dim.getValue());
row++;
}
logger.exiting(sourceClass, sourceMethod);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy