/**
*
*/
package edu.cmu.sphinx.fst;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Arrays;
import edu.cmu.sphinx.fst.semiring.Semiring;
/**
* An immutable finite state transducer implementation.
*
* Holds a fixed size array of {@link edu.cmu.sphinx.fst.ImmutableState} objects
* not allowing additions/deletions
*
* @author John Salatas
*/
public class ImmutableFst extends Fst {
// fst states
private ImmutableState[] states = null;
// number of states
private int numStates;
/**
* Default private constructor.
*
* An ImmutableFst cannot be created directly. It needs to be deserialized.
*
* @see edu.cmu.sphinx.fst.ImmutableFst#loadModel(String)
*/
private ImmutableFst() {
}
/**
* Private Constructor specifying the capacity of the states array
*
* An ImmutableFst cannot be created directly. It needs to be deserialized.
*
* @see edu.cmu.sphinx.fst.ImmutableFst#loadModel(String)
*
* @param numStates
* the number of fst's states
*/
private ImmutableFst(int numStates) {
super(0);
this.numStates = numStates;
this.states = new ImmutableState[numStates];
}
/*
* (non-Javadoc)
*
* @see edu.cmu.sphinx.fst.Fst#getNumStates()
*/
@Override
public int getNumStates() {
return this.numStates;
}
/*
* (non-Javadoc)
*
* @see edu.cmu.sphinx.fst.Fst#getState(int)
*/
@Override
public ImmutableState getState(int index) {
return states[index];
}
/*
* (non-Javadoc)
*
* @see edu.cmu.sphinx.fst.Fst#addState(edu.cmu.sphinx.fst.State)
*/
@Override
public void addState(State state) {
throw new IllegalArgumentException("You cannot modify an ImmutableFst.");
}
/*
* (non-Javadoc)
*
* @see edu.cmu.sphinx.fst.Fst#saveModel(java.lang.String)
*/
@Override
public void saveModel(String filename) throws IOException {
throw new IllegalArgumentException(
"You cannot serialize an ImmutableFst.");
}
/**
* Deserializes an ImmutableFst from an ObjectInputStream
*
* @param in
* the ObjectInputStream. It should be already be initialized by
* the caller.
* @return Created FST
* @throws IOException
* @throws ClassNotFoundException
*/
private static ImmutableFst readImmutableFst(ObjectInputStream in)
throws IOException, ClassNotFoundException {
String[] is = readStringMap(in);
String[] os = readStringMap(in);
int startid = in.readInt();
Semiring semiring = (Semiring) in.readObject();
int numStates = in.readInt();
ImmutableFst res = new ImmutableFst(numStates);
res.isyms = is;
res.osyms = os;
res.semiring = semiring;
for (int i = 0; i < numStates; i++) {
int numArcs = in.readInt();
ImmutableState s = new ImmutableState(numArcs + 1);
float f = in.readFloat();
if (f == res.semiring.zero()) {
f = res.semiring.zero();
} else if (f == res.semiring.one()) {
f = res.semiring.one();
}
s.setFinalWeight(f);
s.id = in.readInt();
res.states[s.getId()] = s;
}
res.setStart(res.states[startid]);
numStates = res.states.length;
for (int i = 0; i < numStates; i++) {
ImmutableState s1 = res.states[i];
for (int j = 0; j < s1.initialNumArcs - 1; j++) {
Arc a = new Arc();
a.setIlabel(in.readInt());
a.setOlabel(in.readInt());
a.setWeight(in.readFloat());
a.setNextState(res.states[in.readInt()]);
s1.setArc(j, a);
}
}
return res;
}
/**
* Deserializes an ImmutableFst from an InputStream
*
* @param inputStream
* the InputStream. It should be already be initialized by the
* caller.
* @return Immutable FST structure
* @throws IOException IO went wrong
* @throws ClassNotFoundException serialization had issues
*/
public static ImmutableFst loadModel(InputStream inputStream)
throws IOException, ClassNotFoundException {
ImmutableFst obj;
BufferedInputStream bis = null;
ObjectInputStream ois = null;
bis = new BufferedInputStream(inputStream);
ois = new ObjectInputStream(bis);
obj = readImmutableFst(ois);
ois.close();
bis.close();
inputStream.close();
return obj;
}
/**
* Deserializes an ImmutableFst from disk
*
* @param filename
* the binary model filename
* @return loaded FST
*/
public static ImmutableFst loadModel(String filename) {
ImmutableFst obj;
try {
FileInputStream fis = null;
BufferedInputStream bis = null;
ObjectInputStream ois = null;
fis = new FileInputStream(filename);
bis = new BufferedInputStream(fis);
ois = new ObjectInputStream(bis);
obj = readImmutableFst(ois);
ois.close();
bis.close();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
return obj;
}
/*
* (non-Javadoc)
*
* @see edu.cmu.sphinx.fst.Fst#deleteState(edu.cmu.sphinx.fst.State)
*/
@Override
public void deleteState(State state) {
throw new IllegalArgumentException("You cannot modify an ImmutableFst.");
}
/*
* (non-Javadoc)
*
* @see edu.cmu.sphinx.fst.Fst#toString()
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Fst(start=" + start + ", isyms=" + Arrays.toString(isyms) + ", osyms="
+ Arrays.toString(osyms) + ", semiring=" + semiring + ")\n");
int numStates = states.length;
for (int i = 0; i < numStates; i++) {
State s = states[i];
sb.append(" " + s + "\n");
int numArcs = s.getNumArcs();
for (int j = 0; j < numArcs; j++) {
Arc a = s.getArc(j);
sb.append(" " + a + "\n");
}
}
return sb.toString();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
ImmutableFst other = (ImmutableFst) obj;
if (!Arrays.equals(states, other.states))
return false;
if (!super.equals(obj))
return false;
return true;
}
@Override
public int hashCode() {
return Arrays.hashCode(states) + super.hashCode();
}
}