package com.yahoo.dtf.range;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import com.yahoo.dtf.range.Range;
import com.yahoo.dtf.range.RangeJoin;
import com.yahoo.dtf.exception.RangeException;
import com.yahoo.dtf.logger.DTFLogger;
public class RangeJoin extends Range {
private DTFLogger _logger = DTFLogger.getLogger(RangeJoin.class);
private ArrayList<Range> _ranges = null;
private String[] elems = null;
public RangeJoin() {
_ranges = new ArrayList<Range>();
}
public synchronized void addRange(Range range) {
_ranges.add(range);
}
public boolean hasMoreElements() {
boolean hasNoMore = true;
for (int i = 0; i < _ranges.size(); i++)
hasNoMore &= !_ranges.get(i).hasMoreElements();
return !hasNoMore;
}
/**
* Push the range group up by 1 starting from the least significant range
*
* @param index
*/
private void nextElement(int index) throws RangeException {
Range range = (Range) _ranges.get(index);
if (!range.hasMoreElements()) {
if (index != 0) {
range.reset();
nextElement(index-1);
}
}
elems[index] = range.nextElement();
}
public String nextElement() throws RangeException {
if (elems == null) {
elems = new String[_ranges.size()];
// initialize
for (int i = 0; i < _ranges.size(); i++) {
if ( _ranges.get(i).hasMoreElements() ) {
elems[i] = _ranges.get(i).nextElement();
}
}
} else {
nextElement(_ranges.size()-1);
}
StringBuffer result = new StringBuffer();
for (int i = 0; i < _ranges.size(); i++) {
result.append(elems[i]);
}
return result.toString();
}
public void reset() throws RangeException {
for (int i = 0; i < _ranges.size(); i++)
((Range)_ranges.get(i)).reset();
}
public int size() {
int result = 1;
for (int i = 0; i < _ranges.size(); i++) {
result *= ((Range) _ranges.get(i)).size();
}
return result;
}
@Override
public void restoreState(DataInputStream dis) throws RangeException {
try {
int ranges = dis.readInt();
_ranges = new ArrayList<Range>();
for (int i = 0; i < ranges; i++) {
String classname = dis.readUTF();
Object obj = Class.forName(classname).newInstance();
if ( !(obj instanceof Range) ) {
throw new RangeException("Serious issue, this isn't even a Range ["
+ obj.getClass().getName() + "]");
}
Range range = (Range)obj;
range.restoreState(dis);
_ranges.add(range);
}
} catch (InstantiationException e) {
throw new RangeException("Error restoring range.",e);
} catch (IllegalAccessException e) {
throw new RangeException("Error restoring range.",e);
} catch (ClassNotFoundException e) {
throw new RangeException("Error restoring range.",e);
} catch (IOException e) {
throw new RangeException("Error restoring range.",e);
}
}
@Override
public void suspendState(DataOutputStream dos) throws RangeException {
try {
dos.writeInt(_ranges.size());
for (int i = 0; i < _ranges.size(); i++) {
Range range = _ranges.get(i);
dos.writeUTF(range.getClass().getName());
_ranges.get(i).suspendState(dos);
}
if ( elems == null ) {
dos.writeInt(0);
} else {
dos.writeInt(elems.length);
for (int i = 0; i < elems.length; i++)
dos.writeUTF(elems[i]);
}
} catch (IOException e) {
throw new RangeException("Error suspending range.",e);
}
}
}