1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.flatfile;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.InputStream;
21
22 import org.apache.commons.flatfile.util.ConcatenatedInputStream;
23 import org.apache.commons.flatfile.util.RepeatingInputStream;
24
25 /**
26 * Support for fields with pad/justify.
27 * @version $Revision: 1301242 $ $Date: 2012-03-15 17:14:40 -0500 (Thu, 15 Mar 2012) $
28 */
29 public abstract class PadJustifyFieldSupport extends FieldSupport {
30 /** Serialization version */
31 private static final long serialVersionUID = -4953059253157670418L;
32
33 /**
34 * Default pad.
35 */
36 public static final byte DEFAULT_PAD = 0x20;
37
38 /**
39 * Justify enumerated type.
40 */
41 public enum Justify implements FieldOption {
42 /** Left-justify */
43 LEFT {
44 /**
45 * {@inheritDoc}
46 */
47 protected InputStream getInputStream(byte[] src, PadJustifyFieldSupport dest) {
48 final InputStream is = new ByteArrayInputStream(src);
49 final int dlen = dest.getPadJustifyLength();
50 return dlen <= src.length ? is : new ConcatenatedInputStream(
51 is, RepeatingInputStream.withLimit(dlen - src.length,
52 dest.getPad()));
53 }
54 },
55
56 /** Right-justify */
57 RIGHT {
58 /**
59 * {@inheritDoc}
60 */
61 protected InputStream getInputStream(byte[] src, PadJustifyFieldSupport dest) {
62 final int dlen = dest.getPadJustifyLength();
63 if (dlen < src.length) {
64 return new ByteArrayInputStream(src, src.length - dlen,
65 dlen);
66 }
67 final InputStream is = new ByteArrayInputStream(src);
68 return dlen == src.length ? is : new ConcatenatedInputStream(
69 RepeatingInputStream.withLimit(dlen - src.length,
70 dest.getPad()), is);
71 }
72 },
73
74 /** Center */
75 CENTER {
76 /**
77 * {@inheritDoc}
78 */
79 protected InputStream getInputStream(byte[] src, PadJustifyFieldSupport dest) {
80 final int dlen = dest.getPadJustifyLength();
81 // it would be odd and therefore hopefully rare to center a
82 // field that allowed overflow, but we'll provide for it:
83 if (dlen < src.length) {
84 return new ByteArrayInputStream(src,
85 (src.length - dlen) / 2, dlen);
86 }
87 final InputStream is = new ByteArrayInputStream(src);
88 if (dlen == src.length) {
89 return is;
90 }
91 final byte pad = dest.getPad();
92 return new ConcatenatedInputStream(
93 RepeatingInputStream
94 .withLimit((dlen - src.length) / 2, pad),
95 is, RepeatingInputStream.of(pad));
96 }
97 };
98
99 /**
100 * Get an InputStream for the specified parameters.
101 * @param src byte[] value
102 * @param dest PadJustifyFieldSupport
103 * @return InputStream
104 */
105 protected abstract InputStream getInputStream(byte[] src, PadJustifyFieldSupport dest);
106 }
107
108 private byte pad = DEFAULT_PAD;
109 private Justify justify;
110
111 /**
112 * Get the justify.
113 * @return Justify
114 */
115 public Justify getJustify() {
116 return justify == null ? Justify.LEFT : justify;
117 }
118
119 /**
120 * Set the justify.
121 * @param justify Justify
122 */
123 public void setJustify(Justify justify) {
124 this.justify = justify;
125 }
126
127 /**
128 * Get the pad.
129 * @return byte
130 */
131 public byte getPad() {
132 return pad;
133 }
134
135 /**
136 * Set the pad.
137 * @param pad byte
138 */
139 public void setPad(byte pad) {
140 this.pad = pad;
141 }
142
143 /**
144 * Implement pad/justify.
145 * @param b value set
146 */
147 public void setValue(byte[] b) {
148 dieOnExceptionRead(getJustify().getInputStream(b, this));
149 }
150
151 /**
152 * Provide the desired target length for padding/justification actions.
153 * @return int
154 */
155 protected abstract int getPadJustifyLength();
156 }