2 * Copyright (C) 2003 <a href="http://www.lohndirekt.de/">lohndirekt.de</a>
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.
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.
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
19 package de
.lohndirekt
.print
.attribute
;
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
;
28 import java
.util
.TimeZone
;
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
;
39 import de
.lohndirekt
.print
.attribute
.ipp
.Charset
;
40 import de
.lohndirekt
.print
.attribute
.ipp
.NaturalLanguage
;
42 public final class AttributeWriter
{
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();
48 public final static Charset DEFAULT_CHARSET
= Charset
.ISO_8859_1
;
56 private static void fillName(ByteArrayOutputStream out
, Attribute attribute
) {
57 String name
= attribute
.getName();
61 private static void fillName(ByteArrayOutputStream out
, String name
) {
63 writeInt2(name
.length(), out
);
65 writeString(name
, out
);
74 private static void attributeBytes(IntegerSyntax attribute
, ByteArrayOutputStream out
) {
76 out
.write((byte) IppValueTag
.INTEGER
.getValue());
78 fillName(out
, (Attribute
) attribute
);
79 //value length (always 4 bytes)
82 writeInt4(attribute
.getValue(), out
);
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];
98 out
.write((byte) IppValueTag
.RANGE
.getValue());
101 fillName(out
, (Attribute
) attribute
);
105 //value length (always 8 bytes)
108 //(Lower bound first)Integer in 4 bytes
109 writeInt4(lowerBound
, out
);
110 //(Upper bound)Integer in 4 bytes
111 writeInt4(upperBound
, out
);
119 private static void attributeBytes(TextSyntax attribute
, ByteArrayOutputStream out
) {
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());
126 out
.write((byte) IppValueTag
.NAME
.getValue());
129 fillName(out
, (Attribute
) attribute
);
131 writeInt2(attribute
.toString().length(), out
);
132 writeNameAndTextString(attribute
.toString(), out
);
140 private static void attributeBytes(EnumSyntax attribute
, ByteArrayOutputStream out
) {
142 out
.write((byte) IppValueTag
.TEXT
.getValue());
144 fillName(out
, (Attribute
) attribute
);
146 writeInt2(attribute
.toString().length(), out
);
147 writeString(attribute
.toString(), out
);
152 * uses UTC time, not local time zone to encode the date
158 private static void attributeBytes(DateTimeSyntax attribute
, ByteArrayOutputStream out
) {
162 out
.write((byte) IppValueTag
.DATE
.getValue());
164 fillName(out
, (Attribute
) attribute
);
165 //Value length (always 11 bytes)
168 Date date
= attribute
.getValue();
169 TimeZone zone
= TimeZone
.getTimeZone("UTC");
170 Calendar cal
= new GregorianCalendar(zone
);
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) {
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
);
204 private static void attributeBytes(URISyntax attribute
, ByteArrayOutputStream out
) {
206 out
.write((byte) IppValueTag
.URI
.getValue());
208 fillName(out
, (Attribute
) attribute
);
210 writeInt2(attribute
.toString().length(), out
);
211 writeString(attribute
.toString(), out
);
219 private static void attributeBytes(ResolutionSyntax attribute
, ByteArrayOutputStream out
) {
221 out
.write((byte) IppValueTag
.INTEGER
.getValue());
223 fillName(out
, (Attribute
) attribute
);
224 //Value length (always 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
);
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));
243 public static void writeInt2(int value
, ByteArrayOutputStream out
){
244 out
.write((byte) ((value
& 0xff00) >> 8));
245 out
.write((byte) (value
& 0xff));
248 public static void writeString(String value
, ByteArrayOutputStream out
, String charsetName
) {
251 bytes
= value
.getBytes(charsetName
);
252 } catch (UnsupportedEncodingException e
) {
253 throw new IllegalArgumentException(charsetName
+ " encoding not supported by JVM");
255 out
.write(bytes
, 0, bytes
.length
);
258 public static void writeString(String value
, ByteArrayOutputStream out
){
259 writeString(value
, out
, Charset
.US_ASCII
.getValue());
262 public static void writeNameAndTextString(String value
, ByteArrayOutputStream out
) {
263 writeString(value
, out
, DEFAULT_CHARSET
.getValue());
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
);
286 throw new IllegalArgumentException("The given attribute is of an unknown SubType (only IntegerSyntax, TextSyntax, DateTimeSyntax, ResolutionSyntax, SetOfIntegerSyntax, EnumSyntax and URISyntax supported)");