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