All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jcamp.parser.AFFNTokenizer Maven / Gradle / Ivy
package org.jcamp.parser;
/**
* tokenizer (parser) that handles numeric data tables in AFFN format.
*
* @author Thomas Weber
*/
public class AFFNTokenizer
implements java.util.Enumeration {
private final DataType type;
private String data;
private final String[] varSymbols;
private int pos;
private int length;
/**
* AFFNTokenizer constructor comment.
*/
public AFFNTokenizer(String[] symbols, String data) throws JCAMPException {
super();
this.type = checkSymbols(symbols);
if (this.type == null)
this.varSymbols = symbols;
else
this.varSymbols = this.type.getSymbols();
this.data = normalizeData(varSymbols.length, data);
this.length = this.data.length();
}
/**
* AFFNTokenizer constructor comment.
*/
public AFFNTokenizer(JCAMPDataRecord ldr) throws JCAMPException {
super();
DataVariableInfo varInfo = new DataVariableInfo(ldr);
this.type = checkSymbols(varInfo.getSymbols());
if (this.type == null)
this.varSymbols = varInfo.getSymbols();
else
this.varSymbols = this.type.getSymbols();
String ldrData = ldr.getContent();
LineTokenizer lt = new LineTokenizer(ldrData);
lt.nextLine(); // skip variable declaration
this.data =
normalizeData(varSymbols.length, ldrData.substring(lt.getPosition()));
this.length = this.data.length();
}
/**
* check for errornous symbols or standard symbols.
*
*/
private static DataType checkSymbols(String[] varSymbols) throws JCAMPException {
if (varSymbols == null || varSymbols.length == 0)
throw new JCAMPException("bad variable declaration");
if (varSymbols.length == 2) {
if (varSymbols[0].equalsIgnoreCase("X") && varSymbols[1].equalsIgnoreCase("Y"))
return DataType.XY;
} else if (varSymbols.length == 3) {
if (varSymbols[0].equalsIgnoreCase("X")
&& varSymbols[1].equalsIgnoreCase("Y")
&& varSymbols[2].equalsIgnoreCase("W"))
return DataType.XYW;
}
return null;
}
/**
* get variable symbols.
*
* @return java.lang.String[]
*/
public final java.lang.String[] getSymbols() {
return varSymbols;
}
/**
* Insert the method's description here.
*
* @return com.creon.chem.jcamp.DataType
*/
public final DataType getType() {
return type;
}
/**
* returns true
if more data is available.
*
* @return boolean
*/
public boolean hasMoreElements() {
return hasMoreGroups();
}
/**
* returns true
if more data is available.
*
* @return boolean
*/
public boolean hasMoreGroups() {
if (pos < length-1)
return true;
return false;
}
/**
* gets next data group.
*
* @return Object
*/
public Object nextElement() {
try {
return nextGroup();
} catch (JCAMPException e) {
throw new java.util.NoSuchElementException(e.getMessage());
}
}
/**
* gets next data group.
*
* @return com.creon.chem.jcamp.AFFNGroup
*/
public AFFNGroup nextGroup() throws JCAMPException {
if (pos >= length)
throw new JCAMPException("parsed beyond end of AFFN block");
if (DataType.XY.equals(type))
return nextXYGroup();
if (DataType.XYW.equals(type))
return nextXYWGroup();
int n = varSymbols.length;
double[] values = new double[n];
for (int i = 0; i < n - 1; i++) {
int p = data.indexOf(",", pos);
if (p < 0)
throw new JCAMPException("missing data in AFFN block");
values[i] = Double.parseDouble(data.substring(pos, p));
pos = p + 1;
}
int p = data.indexOf(";", pos);
if (p < 0)
throw new JCAMPException("extra data in AFFN block");
values[n - 1] = Double.parseDouble(data.substring(pos, p));
pos = p + 1;
return new AFFNGroup(varSymbols, values);
}
/**
* gets next data group.
*
* @return com.creon.chem.jcamp.AFFNGroup
*/
private AFFNGroup nextXYGroup() throws JCAMPException {
double x;
double y;
int p = data.indexOf(',', pos);
if (p < 0) {
throw new JCAMPException("missing x data");
}
x = Double.parseDouble(data.substring(pos, p));
pos = p + 1;
p = data.indexOf(';', pos);
if (p < 0)
throw new JCAMPException("missing y data");
y = Double.parseDouble(data.substring(pos, p));
pos = p + 1;
return new AFFNGroup(x, y);
}
/**
* gets next data group.
*
* @return com.creon.chem.jcamp.AFFNGroup
*/
private AFFNGroup nextXYWGroup() throws JCAMPException {
double x;
double y;
double w;
int p = data.indexOf(',', pos);
if (p < 0)
throw new JCAMPException("missing x data");
x = Double.parseDouble(data.substring(pos, p));
pos = p + 1;
p = data.indexOf(',', pos);
if (p < 0)
throw new JCAMPException("missing y data");
y = Double.parseDouble(data.substring(pos, p));
pos = p + 1;
p = data.indexOf(';', pos);
if (p < 0)
throw new JCAMPException("missing w data");
w = Double.parseDouble(data.substring(pos, p));
pos = p + 1;
return new AFFNGroup(x, y, w);
}
/**
* normalize data block in standard form:
* values are separated by ',', groups are separated by ';'
* whitespace is skipped
*
* @return java.lang.String
* @param orig java.lang.String
*/
private static String normalizeData(int groupLength, String orig)
throws JCAMPException {
StringBuilder normal = new StringBuilder();
boolean inNumber = false;
int j = 0;
for (int i = 0; i < orig.length(); i++) {
char c = orig.charAt(i);
if (Character.isWhitespace(c)) {
if (inNumber) {
inNumber = false;
j++;
if (jgroupLength)
throw new JCAMPException("extra numbers in AFFN data");
normal.append(';');
j=0;
}
continue;
}
if (c == ',') {
if (inNumber) {
inNumber = false;
j++;
if (j>=groupLength)
throw new JCAMPException("extra commas in AFFN data");
normal.append(',');
}
continue;
}
if (Character.isDigit(c)
|| c == '.'
|| c == '+'
|| c == '-'
|| c == 'e'
|| c == 'E') {
normal.append(c);
inNumber = true;
} else {
throw new JCAMPException("unexpected character \'" + c + "\' in AFFN data");
}
}
normal.append(';');
return normal.toString();
}
}