All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.ac.starlink.ecsv.SnakeYamlParser Maven / Gradle / Ivy

package uk.ac.starlink.ecsv;

import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.MarkedYAMLException;
import org.yaml.snakeyaml.error.YAMLException;

/**
 * YamlParser implementation based on the SnakeYAML library
 *
 * 

The current implementation is based on SnakeYAML 1.25, * which in turn claims to understand YAML 1.1. * * @author Mark Taylor * @since 28 Apr 2020 * @see https://bitbucket.org/asomov/snakeyaml/src/ */ public class SnakeYamlParser implements YamlParser { private static final Logger logger_ = Logger.getLogger( "uk.ac.starlink.ecsv" ); public EcsvMeta parseMeta( String[] lines ) throws EcsvFormatException { /* Get SnakeYAML to perform the parse. */ StringBuffer sbuf = new StringBuffer(); for ( String line : lines ) { sbuf.append( line ) .append( '\n' ); } final Object yaml; try { yaml = new Yaml().load( sbuf.toString() ); } catch ( MarkedYAMLException e ) { throw new EcsvFormatException( "YAML parse error: " + e.getProblem(), e ); } catch ( YAMLException e ) { throw new EcsvFormatException( "YAML parse error: " + e.getMessage(), e ); } if ( yaml == null ) { throw new EcsvFormatException( "No YAML content" ); } else if ( ! ( yaml instanceof Map ) ) { throw new EcsvFormatException( "Unexpected YAML content " + yaml.getClass().getName() ); } Map map = (Map) yaml; /* Extract the required information from the parsed structure * and turn it into an EcsvMeta object. */ final char delimiter = getDelimiter( map.get( "delimiter" ) ); final Map tableMeta = getMeta( map.get( "meta" ) ); final EcsvColumn[] columns = getColumns( map.get( "datatype" ) ); final String schema = getStringValue( map, "schema" ); return new EcsvMeta() { public char getDelimiter() { return delimiter; } public EcsvColumn[] getColumns() { return columns; } public Map getTableMeta() { return tableMeta; } public String getSchema() { return schema; } }; } /** * Converts a suitable object to an ECSV delimiter character. * * @param delimObj item that should contain delimiter * @return best guess at delimiter character, hopefully comma or space */ private char getDelimiter( Object delimObj ) { if ( delimObj instanceof String && ((String) delimObj).length() == 1 ) { return ((String) delimObj).charAt( 0 ); } else if ( delimObj instanceof Character ) { return ((Character) delimObj).charValue(); } if ( delimObj != null ) { logger_.warning( "Unexpected ECSV delimiter declaration" + "\"" + delimObj + "\"" ); } return ' '; } /** * Converts a suitable object to a generic table metadata map. * * @param metaObj item that should contain a metadata map * @param metadata map, or null if absent or unsuitable */ private Map getMeta( Object metaObj ) { if ( metaObj == null ) { return null; } else if ( metaObj instanceof Map ) { return (Map) metaObj; } else { logger_.warning( "Ignoring malformed table metadata of type " + metaObj.getClass().getName() ); return null; } } /** * Converts a suitable object to a list of column specifiers. * * @param colsObj item that should contain a list of datatype specifiers * @return array of column metadata objects */ private EcsvColumn[] getColumns( Object colsObj ) throws EcsvFormatException { if ( colsObj instanceof List ) { return getColumnsArray( ((List) colsObj).toArray() ); } else if ( colsObj instanceof Object[] ) { return getColumnsArray( (Object[]) colsObj ); } else if ( colsObj == null ) { throw new EcsvFormatException( "No datatype array in metadata" ); } else { throw new EcsvFormatException( "No comprehensible datatype array " + "in metadata" ); } } /** * Converts an array of suitable objects to a list of column specifiers. * * @param colObjs array of items that should be datatype specifiers * @return array of column metadata objects */ private EcsvColumn[] getColumnsArray( Object[] colObjs ) throws EcsvFormatException { int ncol = colObjs.length; EcsvColumn[] cols = new EcsvColumn[ ncol ]; for ( int ic = 0; ic < ncol; ic++ ) { Object colObj = colObjs[ ic ]; if ( colObj instanceof Map ) { cols[ ic ] = createColumn( (Map) colObj ); } else if ( colObj == null ) { throw new EcsvFormatException( "Null element " + "in column metadata array"); } else { throw new EcsvFormatException( "Unexpected element type " + colObj.getClass().getName() + " in column metadata array" ); } } return cols; } /** * Converts a suitable object to a column specifier. * * @param colMap map that should contain metadata specification * @return corresponding column metadata object */ private EcsvColumn createColumn( Map colMap ) throws EcsvFormatException { final String name = getStringValue( colMap, "name" ); String datatype = getStringValue( colMap, "datatype" ); if ( name == null ) { throw new EcsvFormatException( "Column has no name" ); } if ( datatype == null ) { throw new EcsvFormatException( "Column " + name + " has no datatype" ); } String subtype = getStringValue( colMap, "subtype" ); final EcsvDecoder decoder = EcsvDecoder.createDecoder( datatype, subtype ); if ( decoder == null ) { throw new EcsvFormatException( "Unknown/unsupported datatype " + datatype ); } return createColumn( name, decoder, colMap ); } /** * Creates a typed column metadata object. * * @param name column name * @param decoder value decoder * @param colMap map containing all available parsed column metadata * @return column metadata object */ private static EcsvColumn createColumn( final String name, final EcsvDecoder decoder, Map colMap ) { final String unit = getStringValue( colMap, "unit" ); final String format = getStringValue( colMap, "format" ); final String description = getStringValue( colMap, "description" ); final String datatype = getStringValue( colMap, "datatype" ); Object mapObj = colMap.get( "meta" ); final Map meta = mapObj instanceof Map ? (Map) mapObj : null; return new EcsvColumn() { public String getName() { return name; } public EcsvDecoder getDecoder() { return decoder; } public String getDatatype() { return datatype; } public String getUnit() { return unit; } public String getFormat() { return format; } public String getDescription() { return description; } public Map getMeta() { return meta; } }; } /** * Attempts to acquire a string value from a map. * * @param map map * @param key map key * @return string value corresponding to key, or null */ private static String getStringValue( Map map, String key ) { Object valueObj = map.get( key ); if ( valueObj instanceof String ) { return (String) valueObj; } else if ( valueObj == null ) { return null; } else { logger_.warning( "Non-string value for key \"" + key + "\"" ); return null; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy