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 
18 /* $Id: MapPageOverlay.java 1761020 2016-09-16 11:17:35Z ssteiner $ */
19 
20 package org.apache.fop.afp.modca;
21 
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.io.UnsupportedEncodingException;
25 import java.util.List;
26 
27 import org.apache.fop.afp.AFPConstants;
28 import org.apache.fop.afp.util.BinaryUtils;
29 
30 /**
31  * The Map Page Overlay structured field maps a Resource Local ID to the name of
32  * a Begin Overlay structured field. A Map Page Overlay structured field may
33  * contain from one to 254 repeating groups.
34  */
35 public class MapPageOverlay extends AbstractAFPObject {
36 
37     private static final int MAX_SIZE = 253;
38 
39     /**
40      * The collection of overlays (maximum of 254 stored as byte[])
41      */
42     private List overLays;
43 
44     /**
45      * Constructor for the Map Page Overlay
46      */
MapPageOverlay()47     public MapPageOverlay() {
48     }
49 
getOverlays()50     private List getOverlays() {
51         if (overLays == null) {
52             this.overLays = new java.util.ArrayList();
53         }
54         return this.overLays;
55     }
56 
57     /**
58      * Add an overlay to to the map page overlay object.
59      *
60      * @param name
61      *            The name of the overlay.
62      * @throws MaximumSizeExceededException if the maximum size is reached
63      */
addOverlay(String name)64     public void addOverlay(String name) throws MaximumSizeExceededException {
65         if (getOverlays().size() > MAX_SIZE) {
66             throw new MaximumSizeExceededException();
67         }
68         if (name.length() != 8) {
69             throw new IllegalArgumentException("The name of overlay " + name
70                 + " must be 8 characters");
71         }
72         if (LOG.isDebugEnabled()) {
73             LOG.debug("addOverlay():: adding overlay " + name);
74         }
75         try {
76             byte[] data = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
77             getOverlays().add(data);
78         } catch (UnsupportedEncodingException usee) {
79             LOG.error("addOverlay():: UnsupportedEncodingException translating the name "
80                 + name);
81         }
82     }
83 
84     /** {@inheritDoc} */
writeToStream(OutputStream os)85     public void writeToStream(OutputStream os) throws IOException {
86         int oLayCount = getOverlays().size();
87         int recordlength = oLayCount * 18;
88 
89         byte[] data = new byte[recordlength + 9];
90 
91         data[0] = 0x5A;
92 
93         // Set the total record length
94         byte[] rl1 = BinaryUtils.convert(recordlength + 8, 2); //Ignore the
95         // first byte in
96         // the length
97         data[1] = rl1[0];
98         data[2] = rl1[1];
99 
100         // Structured field ID for a MPO
101         data[3] = (byte) 0xD3;
102         data[4] = Type.MAP;
103         data[5] = Category.PAGE_OVERLAY;
104 
105         data[6] = 0x00; // Reserved
106         data[7] = 0x00; // Reserved
107         data[8] = 0x00; // Reserved
108 
109         int pos = 8;
110 
111         //For each overlay
112         byte olayref = 0x00;
113 
114         for (int i = 0; i < oLayCount; i++) {
115             olayref = (byte) (olayref + 1);
116 
117             data[++pos] = 0x00;
118             data[++pos] = 0x12; //the length of repeating group
119 
120             data[++pos] = 0x0C; //Fully Qualified Name
121             data[++pos] = 0x02;
122             data[++pos] = (byte) 0x84;
123             data[++pos] = 0x00;
124 
125             //now add the name
126             byte[] name = (byte[]) overLays.get(i);
127 
128             for (byte aName : name) {
129                 data[++pos] = aName;
130             }
131 
132             data[++pos] = 0x04; //Resource Local Identifier (RLI)
133             data[++pos] = 0x24;
134             data[++pos] = 0x02;
135 
136             //now add the unique id to the RLI
137             data[++pos] = olayref;
138         }
139         os.write(data);
140     }
141 }
142