@Override
public DistanceParsingResult<D> parse(InputStream in) {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int lineNumber = 0;
ModifiableDBIDs ids = DBIDUtil.newHashSet();
Map<DBIDPair, D> distanceCache = new HashMap<DBIDPair, D>();
try {
for(String line; (line = reader.readLine()) != null; lineNumber++) {
if(lineNumber % 10000 == 0 && logger.isDebugging()) {
logger.debugFine("parse " + lineNumber / 10000);
// logger.fine("parse " + lineNumber / 10000);
}
if(!line.startsWith(COMMENT) && line.length() > 0) {
List<String> entries = tokenize(line);
if(entries.size() != 3) {
throw new IllegalArgumentException("Line " + lineNumber + " does not have the " + "required input format: id1 id2 distanceValue! " + line);
}
DBID id1, id2;
try {
id1 = DBIDUtil.importInteger(Integer.parseInt(entries.get(0)));
}
catch(NumberFormatException e) {
throw new IllegalArgumentException("Error in line " + lineNumber + ": id1 is no integer!");
}
try {
id2 = DBIDUtil.importInteger(Integer.parseInt(entries.get(1)));
}
catch(NumberFormatException e) {
throw new IllegalArgumentException("Error in line " + lineNumber + ": id2 is no integer!");
}
try {
D distance = distanceFunction.getDistanceFactory().parseString(entries.get(2));
put(id1, id2, distance, distanceCache);
ids.add(id1);
ids.add(id2);
}
catch(IllegalArgumentException e) {
throw new IllegalArgumentException("Error in line " + lineNumber + ":" + e.getMessage(), e);
}
}
}
}
catch(IOException e) {
throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
}
if(logger.isDebugging()) {
logger.debugFine("check");
}
// check if all distance values are specified
for(DBID id1 : ids) {
for(DBID id2 : ids) {
if(id2.getIntegerID() < id1.getIntegerID()) {
continue;
}
if(!containsKey(id1, id2, distanceCache)) {
throw new IllegalArgumentException("Distance value for " + id1 + " - " + id2 + " is missing!");
}
}
}
if(logger.isDebugging()) {
logger.debugFine("add to objectAndLabelsList");
}
// This is unusual for ELKI, but here we really need an ArrayList, not a
// DBIDs object. So convert.
List<DBID> objects = new ArrayList<DBID>(ids.size());
for(DBID id : ids) {
objects.add(id);
}
return new DistanceParsingResult<D>(MultipleObjectsBundle.makeSimple(TypeUtil.DBID, objects), distanceCache);
}