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