001: /*
002: Copyright © 2006 Stefano Chizzolini. http://clown.stefanochizzolini.it
003:
004: Contributors:
005: * Stefano Chizzolini (original code developer, http://www.stefanochizzolini.it):
006: contributed code is Copyright © 2006 by Stefano Chizzolini.
007:
008: This file should be part of the source code distribution of "PDF Clown library"
009: (the Program): see the accompanying README files for more info.
010:
011: This Program is free software; you can redistribute it and/or modify it under
012: the terms of the GNU General Public License as published by the Free Software
013: Foundation; either version 2 of the License, or (at your option) any later version.
014:
015: This Program is distributed in the hope that it will be useful, but WITHOUT ANY
016: WARRANTY, either expressed or implied; without even the implied warranty of
017: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more details.
018:
019: You should have received a copy of the GNU General Public License along with this
020: Program (see README files); if not, go to the GNU website (http://www.gnu.org/).
021:
022: Redistribution and use, with or without modification, are permitted provided that such
023: redistributions retain the above copyright notice, license and disclaimer, along with
024: this list of conditions.
025: */
026:
027: package it.stefanochizzolini.clown.objects;
028:
029: import it.stefanochizzolini.clown.documents.Document;
030: import it.stefanochizzolini.clown.files.File;
031:
032: /**
033: This is the base high-level representation of a PDF object; all specialized objects
034: (e.g. Document, Page, Pages, ContentStream...) inherit from it.
035: <h3>Remarks</h3>
036: <p>Somebody may wonder why I didn't directly make specialized objects inherit from
037: their low-level counterparts (e.g. Page extends PdfDictionary, ContentStream
038: extends PdfStream and so on): that could have been much smoother anyway, you argue.
039: Yeah, I could agree if there was a plain one-to-one mapping between primitive PDF
040: types and specialized instances, but (you know!) reality is not so polished as
041: theory: the 'Content' entry of Page dictionaries may be a simple reference to a
042: PdfStream or a PdfArray of references to PdfStream-s, Pages collections may be
043: spread across a B-tree instead of a flat PdfArray etc. So: <i>in order to hide all
044: these annoying inner workings, I chose to adopt a composition pattern instead of
045: the apparently-reasonable (but actually awkward!) inheritance pattern</i>.
046: Nonetheless, users are always enabled to navigate through the low-level structure
047: accessing the {@link #getBaseDataObject()} method.</p>
048: */
049: public abstract class PdfObjectWrapper<TDataObject extends PdfDataObject> {
050: // <class>
051: // <dynamic>
052: // <fields>
053: private PdfDirectObject baseObject;
054: private TDataObject baseDataObject;
055: private PdfIndirectObject container;
056:
057: // </fields>
058:
059: // <constructors>
060: protected PdfObjectWrapper(File context, TDataObject baseDataObject) {
061: this (context.getIndirectObjects().add(baseDataObject)
062: .getReference(), null);
063: }
064:
065: /**
066: @param baseObject Base PDF object. MUST be a <see cref="PdfReference"/>
067: everytime available.
068: @param container Indirect object containing the base object.
069: */
070: protected PdfObjectWrapper(PdfDirectObject baseObject,
071: PdfIndirectObject container) {
072: this .baseObject = baseObject;
073: this .baseDataObject = (TDataObject) File.resolve(baseObject);
074:
075: setContainer(container);
076: }
077:
078: // </constructors>
079:
080: // <interface>
081: // <public>
082: /**
083: Gets the underlying data object.
084: */
085: public TDataObject getBaseDataObject() {
086: return baseDataObject;
087: }
088:
089: /**
090: Gets the underlying reference object; if it's not available
091: (non-indirect object), gets the underlying data object.
092: */
093: public PdfDirectObject getBaseObject() {
094: return baseObject;
095: }
096:
097: /**
098: Gets the clone of the object, registered inside the given document context.
099: @param context Which document the clone has to be registered in.
100: */
101: public abstract Object clone(Document context);
102:
103: /**
104: Removes the object from its document context.
105: <h3>Remarks</h3>
106: <p>The object is no more usable after this method returns.</p>
107: @return Whether the object was actually decontextualized (only indirect objects can be
108: decontextualized).
109: */
110: public boolean delete() {
111: // Is the object indirect?
112: if (baseObject instanceof PdfReference) // Indirect object.
113: {
114: ((PdfReference) baseObject).delete();
115: return true;
116: } else // Direct object.
117: {
118: return false;
119: }
120: }
121:
122: /**
123: Gets the indirect object containing the base object.
124: <h3>Remarks</h3>
125: <p>It's used for update purposes.</p>
126: */
127: public PdfIndirectObject getContainer() {
128: return container;
129: }
130:
131: /**
132: Gets the document context.
133: */
134: public Document getDocument() {
135: return container.getFile().getDocument();
136: }
137:
138: /**
139: Gets the file context.
140: */
141: public File getFile() {
142: return container.getFile();
143: }
144:
145: /**
146: Manually update the underlying indirect object.
147: */
148: public void update() {
149: container.update();
150: }
151:
152: // </public>
153:
154: // <protected>
155: protected void setBaseDataObject(TDataObject value) {
156: baseDataObject = value;
157: }
158:
159: protected void setBaseObject(PdfDirectObject value) {
160: baseObject = value;
161: }
162:
163: // </protected>
164:
165: // <internal>
166: /**
167: <h3>Remarks</h3>
168: <p>For internal use only.</p>
169: */
170: public void setContainer(PdfIndirectObject value) {
171: // Is base object indirect (self-contained)?
172: if (baseObject instanceof PdfReference) // Base object is indirect (self-contained).
173: {
174: container = ((PdfReference) baseObject).getIndirectObject();
175: } else // Base object is direct (contained).
176: {
177: container = value;
178: }
179: }
180: // </internal>
181: // </interface>
182: // </dynamic>
183: // </class>
184: }
|