java/sql-dk/src/info/globalcode/sql/dk/batch/BatchDecoder.java
author František Kučera <franta-hg@frantovo.cz>
Wed, 08 Jan 2014 19:18:52 +0100
branchv_0
changeset 146 4f4f515df807
child 148 1b2f40cd432b
permissions -rw-r--r--
BatchDecoder: basic decoder
franta-hg@146
     1
/**
franta-hg@146
     2
 * SQL-DK
franta-hg@146
     3
 * Copyright © 2014 František Kučera (frantovo.cz)
franta-hg@146
     4
 *
franta-hg@146
     5
 * This program is free software: you can redistribute it and/or modify
franta-hg@146
     6
 * it under the terms of the GNU General Public License as published by
franta-hg@146
     7
 * the Free Software Foundation, either version 3 of the License, or
franta-hg@146
     8
 * (at your option) any later version.
franta-hg@146
     9
 *
franta-hg@146
    10
 * This program is distributed in the hope that it will be useful,
franta-hg@146
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
franta-hg@146
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
franta-hg@146
    13
 * GNU General Public License for more details.
franta-hg@146
    14
 *
franta-hg@146
    15
 * You should have received a copy of the GNU General Public License
franta-hg@146
    16
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
franta-hg@146
    17
 */
franta-hg@146
    18
package info.globalcode.sql.dk.batch;
franta-hg@146
    19
franta-hg@146
    20
import info.globalcode.sql.dk.Parameter;
franta-hg@146
    21
import info.globalcode.sql.dk.SQLCommand;
franta-hg@146
    22
import info.globalcode.sql.dk.SQLCommandNumbered;
franta-hg@146
    23
import java.io.DataInputStream;
franta-hg@146
    24
import java.io.InputStream;
franta-hg@146
    25
import static info.globalcode.sql.dk.batch.BatchConstants.*;
franta-hg@146
    26
import static info.globalcode.sql.dk.Functions.toHex;
franta-hg@146
    27
import info.globalcode.sql.dk.SQLType;
franta-hg@146
    28
import java.io.IOException;
franta-hg@146
    29
import java.util.ArrayList;
franta-hg@146
    30
import java.util.Arrays;
franta-hg@146
    31
import java.util.List;
franta-hg@146
    32
franta-hg@146
    33
/**
franta-hg@146
    34
 *
franta-hg@146
    35
 * @author Ing. František Kučera (frantovo.cz)
franta-hg@146
    36
 */
franta-hg@146
    37
public class BatchDecoder {
franta-hg@146
    38
franta-hg@146
    39
	public Batch decode(InputStream in) throws BatchException {
franta-hg@146
    40
		return new BatchFromStream(new DataInputStream(in));
franta-hg@146
    41
franta-hg@146
    42
	}
franta-hg@146
    43
franta-hg@146
    44
	private class BatchFromStream implements Batch {
franta-hg@146
    45
franta-hg@146
    46
		private DataInputStream in;
franta-hg@146
    47
		private boolean hasNext;
franta-hg@146
    48
franta-hg@146
    49
		public BatchFromStream(DataInputStream in) throws BatchException {
franta-hg@146
    50
			this.in = in;
franta-hg@146
    51
			hasNext = verifyHeader();
franta-hg@146
    52
		}
franta-hg@146
    53
franta-hg@146
    54
		@Override
franta-hg@146
    55
		public boolean hasNext() throws BatchException {
franta-hg@146
    56
			return hasNext;
franta-hg@146
    57
		}
franta-hg@146
    58
franta-hg@146
    59
		@Override
franta-hg@146
    60
		public SQLCommand next() throws BatchException {
franta-hg@146
    61
			try {
franta-hg@146
    62
				String sql = readNextString();
franta-hg@146
    63
franta-hg@146
    64
				int paramCount = in.readInt();
franta-hg@146
    65
				List<Parameter> parameters = new ArrayList<>(paramCount);
franta-hg@146
    66
franta-hg@146
    67
				for (int i = 0; i < paramCount; i++) {
franta-hg@146
    68
					SQLType type = SQLType.valueOf(in.readInt());
franta-hg@146
    69
					String value = readNextString();
franta-hg@146
    70
					parameters.add(new Parameter(value, type));
franta-hg@146
    71
				}
franta-hg@146
    72
franta-hg@146
    73
				hasNext = verifyHeader();
franta-hg@146
    74
franta-hg@146
    75
				SQLCommand sqlCommand = new SQLCommandNumbered(sql, parameters);
franta-hg@146
    76
				return sqlCommand;
franta-hg@146
    77
			} catch (IOException e) {
franta-hg@146
    78
				throw new BatchException("Unable to read batch", e);
franta-hg@146
    79
			}
franta-hg@146
    80
		}
franta-hg@146
    81
franta-hg@146
    82
		private String readNextString() throws IOException {
franta-hg@146
    83
			byte[] buffer = new byte[in.readInt()];
franta-hg@146
    84
			in.read(buffer);
franta-hg@146
    85
			return new String(buffer, CHARSET);
franta-hg@146
    86
		}
franta-hg@146
    87
franta-hg@146
    88
		/**
franta-hg@146
    89
		 * @return true if correct batch header was found | false if EOF was found
franta-hg@146
    90
		 * @throws BatchException if unexpected data was found (not batch header nor EOF)
franta-hg@146
    91
		 */
franta-hg@146
    92
		private boolean verifyHeader() throws BatchException {
franta-hg@146
    93
			try {
franta-hg@146
    94
				byte[] buffer = new byte[BATCH_HEADER.length];
franta-hg@146
    95
				int bytesRead = in.read(buffer);
franta-hg@146
    96
franta-hg@146
    97
				if (bytesRead == BATCH_HEADER.length && Arrays.equals(buffer, BATCH_HEADER)) {
franta-hg@146
    98
					return true;
franta-hg@146
    99
				} else if (bytesRead == -1) {
franta-hg@146
   100
					return false;
franta-hg@146
   101
				} else {
franta-hg@146
   102
					throw new BatchException("This is not SQL-DK batch: " + toHex(buffer));
franta-hg@146
   103
				}
franta-hg@146
   104
			} catch (IOException e) {
franta-hg@146
   105
				throw new BatchException("Unable to read batch header", e);
franta-hg@146
   106
			}
franta-hg@146
   107
franta-hg@146
   108
		}
franta-hg@146
   109
	}
franta-hg@146
   110
}