2 * Licensed to the Apache Software Foundation (ASF) under one or more
\r
3 * contributor license agreements. See the NOTICE file distributed with
\r
4 * this work for additional information regarding copyright ownership.
\r
5 * The ASF licenses this file to You under the Apache License, Version 2.0
\r
6 * (the "License"); you may not use this file except in compliance with
\r
7 * the License. You may obtain a copy of the License at
\r
9 * http://www.apache.org/licenses/LICENSE-2.0
\r
11 * Unless required by applicable law or agreed to in writing, software
\r
12 * distributed under the License is distributed on an "AS IS" BASIS,
\r
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
14 * See the License for the specific language governing permissions and
\r
15 * limitations under the License.
\r
17 package org.apache.pdfbox.pdmodel.graphics.optionalcontent;
\r
19 import java.util.Collection;
\r
21 import org.apache.pdfbox.cos.COSArray;
\r
22 import org.apache.pdfbox.cos.COSBase;
\r
23 import org.apache.pdfbox.cos.COSDictionary;
\r
24 import org.apache.pdfbox.cos.COSName;
\r
25 import org.apache.pdfbox.cos.COSObject;
\r
26 import org.apache.pdfbox.pdmodel.common.COSObjectable;
\r
29 * This class represents the optional content properties dictionary.
\r
32 * @version $Revision$
\r
34 public class PDOptionalContentProperties implements COSObjectable
\r
38 * Enumeration for the BaseState dictionary entry on the "D" dictionary.
\r
40 public static enum BaseState
\r
43 /** The "ON" value. */
\r
45 /** The "OFF" value. */
\r
47 /** The "Unchanged" value. */
\r
48 UNCHANGED(COSName.UNCHANGED);
\r
50 private COSName name;
\r
52 private BaseState(COSName value)
\r
58 * Returns the PDF name for the state.
\r
59 * @return the name of the state
\r
61 public COSName getName()
\r
67 * Returns the base state represented by the given {@link COSName}.
\r
68 * @param state the state name
\r
69 * @return the state enum value
\r
71 public static BaseState valueOf(COSName state)
\r
75 return BaseState.ON;
\r
77 return BaseState.valueOf(state.getName().toUpperCase());
\r
82 private COSDictionary dict;
\r
85 * Creates a new optional content properties dictionary.
\r
87 public PDOptionalContentProperties()
\r
89 this.dict = new COSDictionary();
\r
90 this.dict.setItem(COSName.OCGS, new COSArray());
\r
91 this.dict.setItem(COSName.D, new COSDictionary());
\r
95 * Creates a new instance based on a given {@link COSDictionary}.
\r
96 * @param props the dictionary
\r
98 public PDOptionalContentProperties(COSDictionary props)
\r
103 /** {@inheritDoc} */
\r
104 public COSBase getCOSObject()
\r
109 private COSArray getOCGs()
\r
111 COSArray ocgs = (COSArray)this.dict.getItem(COSName.OCGS);
\r
114 ocgs = new COSArray();
\r
115 this.dict.setItem(COSName.OCGS, ocgs); //OCGs is required
\r
120 private COSDictionary getD()
\r
122 COSDictionary d = (COSDictionary)this.dict.getDictionaryObject(COSName.D);
\r
125 d = new COSDictionary();
\r
126 this.dict.setItem(COSName.D, d); //D is required
\r
132 * Returns the optional content group of the given name.
\r
133 * @param name the group name
\r
134 * @return the optional content group or null, if there is no such group
\r
136 public PDOptionalContentGroup getGroup(String name)
\r
138 COSArray ocgs = getOCGs();
\r
139 for (COSBase o : ocgs)
\r
141 COSDictionary ocg = toDictionary(o);
\r
142 String groupName = ocg.getString(COSName.NAME);
\r
143 if (groupName.equals(name))
\r
145 return new PDOptionalContentGroup(ocg);
\r
152 * Adds an optional content group (OCG).
\r
153 * @param ocg the optional content group
\r
155 public void addGroup(PDOptionalContentGroup ocg)
\r
157 COSArray ocgs = getOCGs();
\r
158 ocgs.add(ocg.getCOSObject());
\r
160 //By default, add new group to the "Order" entry so it appears in the user interface
\r
161 COSArray order = (COSArray)getD().getDictionaryObject(COSName.ORDER);
\r
164 order = new COSArray();
\r
165 getD().setItem(COSName.ORDER, order);
\r
171 * Returns the collection of all optional content groups.
\r
172 * @return the optional content groups
\r
174 public Collection<PDOptionalContentGroup> getOptionalContentGroups()
\r
176 Collection<PDOptionalContentGroup> coll = new java.util.ArrayList<PDOptionalContentGroup>();
\r
177 COSArray ocgs = getOCGs();
\r
178 for (COSBase base : ocgs)
\r
180 COSObject obj = (COSObject)base; //Children must be indirect references
\r
181 coll.add(new PDOptionalContentGroup((COSDictionary)obj.getObject()));
\r
187 * Returns the base state for optional content groups.
\r
188 * @return the base state
\r
190 public BaseState getBaseState()
\r
192 COSDictionary d = getD();
\r
193 COSName name = (COSName)d.getItem(COSName.BASE_STATE);
\r
194 return BaseState.valueOf(name);
\r
198 * Sets the base state for optional content groups.
\r
199 * @param state the base state
\r
201 public void setBaseState(BaseState state)
\r
203 COSDictionary d = getD();
\r
204 d.setItem(COSName.BASE_STATE, state.getName());
\r
208 * Lists all optional content group names.
\r
209 * @return an array of all names
\r
211 public String[] getGroupNames()
\r
213 COSArray ocgs = (COSArray)dict.getDictionaryObject(COSName.OCGS);
\r
214 int size = ocgs.size();
\r
215 String[] groups = new String[size];
\r
216 for (int i = 0; i < size; i++)
\r
218 COSBase obj = (COSBase)ocgs.get(i);
\r
219 COSDictionary ocg = toDictionary(obj);
\r
220 groups[i] = ocg.getString(COSName.NAME);
\r
226 * Indicates whether a particular optional content group is found in the PDF file.
\r
227 * @param groupName the group name
\r
228 * @return true if the group exists, false otherwise
\r
230 public boolean hasGroup(String groupName)
\r
232 String[] layers = getGroupNames();
\r
233 for (String layer : layers)
\r
235 if (layer.equals(groupName))
\r
244 * Indicates whether an optional content group is enabled.
\r
245 * @param groupName the group name
\r
246 * @return true if the group is enabled
\r
248 public boolean isGroupEnabled(String groupName)
\r
250 //TODO handle Optional Content Configuration Dictionaries,
\r
251 //i.e. OCProperties/Configs
\r
253 COSDictionary d = getD();
\r
254 COSArray on = (COSArray)d.getDictionaryObject(COSName.ON);
\r
257 for (COSBase o : on)
\r
259 COSDictionary group = toDictionary(o);
\r
260 String name = group.getString(COSName.NAME);
\r
261 if (name.equals(groupName))
\r
268 COSArray off = (COSArray)d.getDictionaryObject(COSName.OFF);
\r
271 for (COSBase o : off)
\r
273 COSDictionary group = toDictionary(o);
\r
274 String name = group.getString(COSName.NAME);
\r
275 if (name.equals(groupName))
\r
282 BaseState baseState = getBaseState();
\r
283 boolean enabled = !baseState.equals(BaseState.OFF);
\r
284 //TODO What to do with BaseState.Unchanged?
\r
288 private COSDictionary toDictionary(COSBase o)
\r
290 if (o instanceof COSObject)
\r
292 return (COSDictionary)((COSObject)o).getObject();
\r
296 return (COSDictionary)o;
\r
301 * Enables or disables an optional content group.
\r
302 * @param groupName the group name
\r
303 * @param enable true to enable, false to disable
\r
304 * @return true if the group already had an on or off setting, false otherwise
\r
306 public boolean setGroupEnabled(String groupName, boolean enable)
\r
308 COSDictionary d = getD();
\r
309 COSArray on = (COSArray)d.getDictionaryObject(COSName.ON);
\r
312 on = new COSArray();
\r
313 d.setItem(COSName.ON, on);
\r
315 COSArray off = (COSArray)d.getDictionaryObject(COSName.OFF);
\r
318 off = new COSArray();
\r
319 d.setItem(COSName.OFF, off);
\r
322 boolean found = false;
\r
323 for (COSBase o : on)
\r
325 COSDictionary group = toDictionary(o);
\r
326 String name = group.getString(COSName.NAME);
\r
327 if (!enable && name.equals(groupName))
\r
336 for (COSBase o : off)
\r
338 COSDictionary group = toDictionary(o);
\r
339 String name = group.getString(COSName.NAME);
\r
340 if (enable && name.equals(groupName))
\r
352 PDOptionalContentGroup ocg = getGroup(groupName);
\r
355 on.add(ocg.getCOSObject());
\r
359 off.add(ocg.getCOSObject());
\r