ContextSerializerBurmeister.java
package org.thegalactic.context.io;
/*
* ContextSerializerBurmeister.java
*
* Copyright: 2010-2015 Karell Bertet, France
* Copyright: 2015-2016 The Galactic Organization, France
*
* License: http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html CeCILL-B license
*
* This file is part of java-lattices.
* You can redistribute it and/or modify it under the terms of the CeCILL-B license.
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.TreeSet;
import org.thegalactic.context.Context;
import org.thegalactic.io.Reader;
import org.thegalactic.io.Writer;
/**
* This class defines the way for reading a context from a text file.
*
* ![ContextSerializerBurmeister](ContextSerializerBurmeister.png)
*
* @uml ContextSerializerBurmeister.png
* !include
* resources/org/thegalactic/context/io/ContextSerializerBurmeister.iuml
* !include resources/org/thegalactic/io/Reader.iuml
* !include resources/org/thegalactic/io/Writer.iuml
*
* hide members
* show ContextSerializerBurmeister members
* class ContextSerializerBurmeister #LightCyan
* title ContextSerializerBurmeister UML graph
*/
public final class ContextSerializerBurmeister implements Reader<Context>, Writer<Context> {
/**
* String extension.
*/
private static final String EXTENSION = "cxt";
/**
* Burmeister header.
*/
private static final String HEADER = "B";
/**
* The singleton instance.
*/
private static final ContextSerializerBurmeister INSTANCE = new ContextSerializerBurmeister();
/**
* Return the singleton instance of this class.
*
* @return the singleton instance
*/
public static ContextSerializerBurmeister getInstance() {
return INSTANCE;
}
/**
* Register this class for reading and writing .cxt files.
*/
public static void register() {
ContextIOFactory.getInstance().registerReader(ContextSerializerBurmeister.getInstance(), EXTENSION);
ContextIOFactory.getInstance().registerWriter(ContextSerializerBurmeister.getInstance(), EXTENSION);
}
/**
* This class is not designed to be publicly instantiated.
*/
private ContextSerializerBurmeister() {
}
/**
* Read a context from a file.
*
* The Burmeister cxt format file is respected :
*
* The file format is structured as follows:
*
* The first line consists of a single "B"
* The second line contains the name of the context (note that this is
* ignored)
* The third and fourth line consist of the object and attribute count,
* respectively
* after that, all objects and all attributes are listed, each on a separate
* line
* finally, the context is given as a combination of . and X, each row on a
* separate line.
*
* ~~~
* B
* Example
* 2
* 2
* a
* b
* 1
* 2
* .X
* XX
* ~~~
*
* @param context a context to read
* @param file a file
*
* @throws IOException When an IOException occurs
*/
public void read(final Context context, final BufferedReader file) throws IOException {
// str corresponds to the string "B". First line (Unused).
String str = file.readLine();
// Detect Burmeister magic header
if (!HEADER.equals(str)) {
throw new IOException("Burmeister magic header not found");
}
// Second line (Unused in the code).
file.readLine();
try {
// number of observations. Third line.
final int nbObs = Integer.parseInt(file.readLine());
// number of attributes. Fourth line.
final int nbAtt = Integer.parseInt(file.readLine());
// Now reading observations
// Observations names must be recorded for the reading context phase
String[] obsNames = new String[nbObs];
for (int i = 0; i < nbObs; i++) {
obsNames[i] = this.readNextLine(file);
context.addToObservations(obsNames[i]);
}
// Now reading attributes
// Attributes names must be recorded for the reading context phase
String[] attNames = new String[nbAtt];
for (int i = 0; i < nbAtt; i++) {
attNames[i] = this.readNextLine(file);
context.addToAttributes(attNames[i]);
}
// Now reading context
for (int i = 0; i < nbObs; i++) {
str = this.readNextLine(file);
for (int j = 0; j < nbAtt; j++) {
if (str.charAt(j) == 'X') {
context.addExtentIntent(obsNames[i], attNames[j]);
}
}
}
context.setBitSets();
} catch (NumberFormatException ex) {
throw new IOException(ex.getMessage());
} catch (IndexOutOfBoundsException ex) {
throw new IOException(ex.getMessage());
}
}
/**
* Return the next non-empty line.
*
* @param file a file
*
* @return the next non-empty line
*
* @throws IOException When an IOException occurs
*/
private String readNextLine(final BufferedReader file) throws IOException {
String str;
do {
str = file.readLine();
} while ("".equals(str));
return str;
}
/**
* Write a context to a file.
*
* The Burmeister cxt format file is respected :
*
* The file format is structured as follows:
*
* The first line consists of a single "B"
* The second line contains the name of the context (note that this is
* ignored)
* The third and fourth line consist of the object and attribute count,
* respectively.
* The fifth line is empty.
* After that, all objects and all attributes are listed, each on a separate
* line
* finally, the context is given as a combination of . and X, each row on a
* separate line.
*
* ~~~
* B
* Example
* 2
* 2
*
* a
* b
* 1
* 2
* .X
* XX
* ~~~
*
* @param context a context to write
* @param file a file
*
* @throws IOException When an IOException occurs
*/
@Override
public void write(final Context context, final BufferedWriter file) throws IOException {
// Magic header
file.write(HEADER);
file.newLine();
// Empty name
file.newLine();
final TreeSet<Comparable> attributes = context.getAttributes();
final TreeSet<Comparable> observations = context.getObservations();
// Observation and attributes size
file.write(String.valueOf(observations.size()));
file.newLine();
file.write(String.valueOf(attributes.size()));
file.newLine();
// Observations
for (final Comparable observation : observations) {
file.write(observation.toString());
file.newLine();
}
// Attributes
for (final Comparable attribute : attributes) {
file.write(attribute.toString());
file.newLine();
}
// Extent/Intent
final StringBuilder builder = new StringBuilder();
for (final Comparable observation : observations) {
builder.setLength(0);
for (final Comparable attribute : attributes) {
if (context.getIntent(observation).contains(attribute)) {
builder.append('X');
} else {
builder.append('.');
}
}
file.write(builder.toString());
file.newLine();
}
}
}