/**
* SQL-DK
* Copyright © 2014 František Kučera (frantovo.cz)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package info.globalcode.sql.dk.batch;
import info.globalcode.sql.dk.Parameter;
import info.globalcode.sql.dk.SQLCommand;
import info.globalcode.sql.dk.SQLCommandNumbered;
import java.io.DataInputStream;
import java.io.InputStream;
import static info.globalcode.sql.dk.batch.BatchConstants.*;
import static info.globalcode.sql.dk.Functions.toHex;
import info.globalcode.sql.dk.SQLType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* @author Ing. František Kučera (frantovo.cz)
*/
public class BatchDecoder {
public Batch decode(InputStream in) throws BatchException {
return new BatchFromStream(new DataInputStream(in));
}
private class BatchFromStream implements Batch {
private DataInputStream in;
private boolean hasNext;
public BatchFromStream(DataInputStream in) throws BatchException {
this.in = in;
hasNext = verifyHeader();
}
@Override
public boolean hasNext() throws BatchException {
return hasNext;
}
@Override
public SQLCommand next() throws BatchException {
try {
String sql = readNextString();
int paramCount = in.readInt();
List<Parameter> parameters = new ArrayList<>(paramCount);
for (int i = 0; i < paramCount; i++) {
SQLType type = SQLType.valueOf(in.readInt());
String value = readNextString();
parameters.add(new Parameter(value, type));
}
hasNext = verifyHeader();
SQLCommand sqlCommand = new SQLCommandNumbered(sql, parameters);
return sqlCommand;
} catch (IOException e) {
throw new BatchException("Unable to read batch", e);
}
}
private String readNextString() throws IOException {
byte[] buffer = new byte[in.readInt()];
in.read(buffer);
return new String(buffer, CHARSET);
}
/**
* @return true if correct batch header was found | false if EOF was found
* @throws BatchException if unexpected data was found (not batch header nor EOF)
*/
private boolean verifyHeader() throws BatchException {
try {
byte[] buffer = new byte[BATCH_HEADER.length];
int bytesRead = in.read(buffer);
if (bytesRead == BATCH_HEADER.length && Arrays.equals(buffer, BATCH_HEADER)) {
return true;
} else if (bytesRead == -1) {
return false;
} else {
throw new BatchException("This is not SQL-DK batch: " + toHex(buffer));
}
} catch (IOException e) {
throw new BatchException("Unable to read batch header", e);
}
}
}
}