Initial import.
[clinton/mirror/jspi/.git] / jspi / src / main / java / de / lohndirekt / print / attribute / AttributeWriter.java
1 /**
2 * Copyright (C) 2003 <a href="http://www.lohndirekt.de/">lohndirekt.de</a>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19 package de.lohndirekt.print.attribute;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.UnsupportedEncodingException;
23 import java.util.Calendar;
24 import java.util.Date;
25 import java.util.GregorianCalendar;
26 import java.util.HashMap;
27 import java.util.Map;
28 import java.util.TimeZone;
29
30 import javax.print.attribute.Attribute;
31 import javax.print.attribute.DateTimeSyntax;
32 import javax.print.attribute.EnumSyntax;
33 import javax.print.attribute.IntegerSyntax;
34 import javax.print.attribute.ResolutionSyntax;
35 import javax.print.attribute.SetOfIntegerSyntax;
36 import javax.print.attribute.TextSyntax;
37 import javax.print.attribute.URISyntax;
38
39 import de.lohndirekt.print.attribute.ipp.Charset;
40 import de.lohndirekt.print.attribute.ipp.NaturalLanguage;
41
42 public final class AttributeWriter {
43
44 private final static int MILIS_IN_MINUTE = 1000*60;
45 private final static int MILIS_IN_HOUR =MILIS_IN_MINUTE*60;
46 private static Map encodings = new HashMap();
47
48 public final static Charset DEFAULT_CHARSET = Charset.ISO_8859_1;
49
50 /**
51 * @param bytes
52 * @param byteNr
53 * @param attribute
54 * @return
55 */
56 private static void fillName(ByteArrayOutputStream out, Attribute attribute) {
57 String name = attribute.getName();
58 fillName(out, name);
59 }
60
61 private static void fillName(ByteArrayOutputStream out, String name) {
62 //name length
63 writeInt2(name.length(), out);
64 //name of attribute
65 writeString(name, out);
66
67 }
68
69 /**
70 * @param attribute
71 * @param bytes
72 * @return
73 */
74 private static void attributeBytes(IntegerSyntax attribute, ByteArrayOutputStream out) {
75 //value tag
76 out.write((byte) IppValueTag.INTEGER.getValue());
77 //name
78 fillName(out, (Attribute) attribute);
79 //value length (always 4 bytes)
80 writeInt2(4, out);
81 //value
82 writeInt4(attribute.getValue(), out);
83 }
84
85 /**
86 * @param attribute
87 * @param bytes
88 * @return
89 */
90 private static void attributeBytes(SetOfIntegerSyntax attribute, ByteArrayOutputStream out) {
91 int[][] members = attribute.getMembers();
92 for (int i = 0; i < members.length; i++) {
93 int[] range = members[i];
94 int lowerBound = range[0];
95 int upperBound = range[1];
96
97 //value tag
98 out.write((byte) IppValueTag.RANGE.getValue());
99 //name
100 if (i == 0) {
101 fillName(out, (Attribute) attribute);
102 } else {
103 fillName(out, "");
104 }
105 //value length (always 8 bytes)
106 writeInt2(8, out);
107
108 //(Lower bound first)Integer in 4 bytes
109 writeInt4(lowerBound, out);
110 //(Upper bound)Integer in 4 bytes
111 writeInt4(upperBound, out);
112 }
113 }
114 /**
115 * @param attribute
116 * @param bytes
117 * @return
118 */
119 private static void attributeBytes(TextSyntax attribute, ByteArrayOutputStream out) {
120 // value tag
121 if (attribute instanceof Charset) {
122 out.write((byte) IppValueTag.CHARSET.getValue());
123 } else if (attribute instanceof NaturalLanguage) {
124 out.write((byte) IppValueTag.LANGUAGE.getValue());
125 } else {
126 out.write((byte) IppValueTag.NAME.getValue());
127 }
128 //name
129 fillName(out, (Attribute) attribute);
130 //value length
131 writeInt2(attribute.toString().length(), out);
132 writeNameAndTextString(attribute.toString(), out);
133 }
134
135 /**
136 * @param attribute
137 * @param bytes
138 * @return
139 */
140 private static void attributeBytes(EnumSyntax attribute, ByteArrayOutputStream out) {
141 // Value tag
142 out.write((byte) IppValueTag.TEXT.getValue());
143 // Name
144 fillName(out, (Attribute) attribute);
145 // value length
146 writeInt2(attribute.toString().length(), out);
147 writeString(attribute.toString(), out);
148 }
149
150 /**
151 *
152 * uses UTC time, not local time zone to encode the date
153 *
154 * @param attribute
155 * @param bytes
156 * @return
157 */
158 private static void attributeBytes(DateTimeSyntax attribute, ByteArrayOutputStream out) {
159
160
161 //Value tag
162 out.write((byte) IppValueTag.DATE.getValue());
163 //Name
164 fillName(out, (Attribute) attribute);
165 //Value length (always 11 bytes)
166 writeInt2(11, out);
167
168 Date date = attribute.getValue();
169 TimeZone zone = TimeZone.getTimeZone("UTC");
170 Calendar cal = new GregorianCalendar(zone);
171 cal.setTime(date);
172
173 int year = cal.get(GregorianCalendar.YEAR);
174 int month = cal.get(Calendar.MONTH) + 1;
175 int day = cal.get(Calendar.DAY_OF_MONTH);
176 int hour = cal.get(Calendar.HOUR_OF_DAY);
177 int minute = cal.get(Calendar.MINUTE);
178 int second = cal.get(Calendar.SECOND);
179 int deci = cal.get(Calendar.MILLISECOND) / 100;
180 int offset = zone.getOffset(cal.getTimeInMillis());
181 int hoursFromUtc = offset / MILIS_IN_HOUR;
182 int minutesFromUtc = offset % MILIS_IN_HOUR / MILIS_IN_MINUTE;
183 char direction = '+';
184 if (hoursFromUtc < 0) {
185 direction = '-';
186 hoursFromUtc *= -1;
187 }
188 writeInt2(year, out);
189 out.write((byte) month);
190 out.write((byte) day);
191 out.write((byte) hour);
192 out.write((byte) minute);
193 out.write((byte) second);
194 out.write((byte) deci);
195 out.write((byte) direction);
196 out.write((byte) hoursFromUtc);
197 out.write((byte) minutesFromUtc);
198 }
199 /**
200 * @param attribute
201 * @param bytes
202 * @return
203 */
204 private static void attributeBytes(URISyntax attribute, ByteArrayOutputStream out) {
205 //Value tag
206 out.write((byte) IppValueTag.URI.getValue());
207 //Name
208 fillName(out, (Attribute) attribute);
209 //value length
210 writeInt2(attribute.toString().length(), out);
211 writeString(attribute.toString(), out);
212 }
213
214 /**
215 * @param attribute
216 * @param bytes
217 * @return
218 */
219 private static void attributeBytes(ResolutionSyntax attribute, ByteArrayOutputStream out) {
220 //Value tag
221 out.write((byte) IppValueTag.INTEGER.getValue());
222 //Name
223 fillName(out, (Attribute) attribute);
224 //Value length (always 9)
225 out.write((byte) 0);
226 out.write((byte) 9);
227 int feedResolution = attribute.getFeedResolution(ResolutionSyntax.DPI);
228 int crossFeedResolution = attribute.getCrossFeedResolution(ResolutionSyntax.DPI);
229 //(Lower bound first)Integer in 4 bytes
230 writeInt4(crossFeedResolution, out);
231 //(Upper bound)Integer in 4 bytes
232 writeInt4(feedResolution, out);
233 out.write((byte) ResolutionSyntax.DPI);
234 }
235
236 public static void writeInt4(int value, ByteArrayOutputStream out){
237 out.write((byte) ((value & 0xff000000) >> 24));
238 out.write((byte) ((value & 0xff0000) >> 16));
239 out.write((byte) ((value & 0xff00) >> 8));
240 out.write((byte) (value & 0xff));
241 }
242
243 public static void writeInt2(int value, ByteArrayOutputStream out){
244 out.write((byte) ((value & 0xff00) >> 8));
245 out.write((byte) (value & 0xff));
246 }
247
248 public static void writeString(String value, ByteArrayOutputStream out, String charsetName) {
249 byte[] bytes;
250 try {
251 bytes = value.getBytes(charsetName);
252 } catch (UnsupportedEncodingException e) {
253 throw new IllegalArgumentException(charsetName + " encoding not supported by JVM");
254 }
255 out.write(bytes, 0, bytes.length);
256 }
257
258 public static void writeString(String value, ByteArrayOutputStream out){
259 writeString(value, out, Charset.US_ASCII.getValue());
260 }
261
262 public static void writeNameAndTextString(String value, ByteArrayOutputStream out) {
263 writeString(value, out, DEFAULT_CHARSET.getValue());
264 }
265
266 /**
267 * @param attribute
268 * @return
269 */
270 public static void attributeBytes(Attribute attribute, ByteArrayOutputStream out) {
271 if (attribute instanceof IntegerSyntax) {
272 attributeBytes((IntegerSyntax) attribute, out);
273 } else if (attribute instanceof TextSyntax) {
274 attributeBytes((TextSyntax) attribute, out);
275 } else if (attribute instanceof DateTimeSyntax) {
276 attributeBytes((DateTimeSyntax) attribute, out);
277 } else if (attribute instanceof ResolutionSyntax) {
278 attributeBytes((ResolutionSyntax) attribute, out);
279 } else if (attribute instanceof SetOfIntegerSyntax) {
280 attributeBytes((SetOfIntegerSyntax) attribute, out);
281 } else if (attribute instanceof EnumSyntax) {
282 attributeBytes((EnumSyntax) attribute, out);
283 } else if (attribute instanceof URISyntax) {
284 attributeBytes((URISyntax) attribute, out);
285 } else {
286 throw new IllegalArgumentException("The given attribute is of an unknown SubType (only IntegerSyntax, TextSyntax, DateTimeSyntax, ResolutionSyntax, SetOfIntegerSyntax, EnumSyntax and URISyntax supported)");
287 }
288 }
289
290 }