source: trunk/docx4j/src/main/java/org/docx4j/openpackaging/Base.java @ 1649

Revision 1649, 8.1 KB checked in by jharrop, 5 months ago (diff)

Improved control over what addTargetPart does in the event of a part name collision.

  • Property svn:eol-style set to native
Line 
1/*
2 *  Copyright 2007-2008, Plutext Pty Ltd.
3 *   
4 *  This file is part of docx4j.
5
6    docx4j is licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18
19 */
20
21
22package org.docx4j.openpackaging;
23
24
25import org.apache.log4j.Logger;
26import org.docx4j.openpackaging.contenttype.CTDefault;
27import org.docx4j.openpackaging.contenttype.ContentType;
28import org.docx4j.openpackaging.contenttype.ObjectFactory;
29import org.docx4j.openpackaging.exceptions.Docx4JException;
30import org.docx4j.openpackaging.exceptions.InvalidFormatException;
31import org.docx4j.openpackaging.packages.OpcPackage;
32import org.docx4j.openpackaging.parts.Part;
33import org.docx4j.openpackaging.parts.PartName;
34import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
35import org.docx4j.openpackaging.parts.relationships.RelationshipsPart.AddPartBehaviour;
36import org.docx4j.relationships.Relationship;
37
38
39
40public abstract class Base {
41
42        protected static Logger log = Logger.getLogger(Base.class);
43
44        public abstract OpcPackage getPackage();       
45
46       
47        /**
48         * relationships - the package and each part can have one of these
49         * See eg 11. WordprocessingML [11.2 Package Structure].
50         * (Each Part is also the _target_ of a RelationshipPart,
51         * so see Part for definition of a corresponding field.)
52         */
53        public RelationshipsPart relationships;
54
55        /**
56         * Get the relationship part.
57         * From 2.7.1, the part will be created if it
58         * doesn't exist.  (SaveToZipFile will only
59         * save it if it contains rels)
60         *
61         * @return The relationship part name.
62         */
63        public RelationshipsPart getRelationshipsPart() {
64                return getRelationshipsPart(true);
65        }
66       
67        /**
68         * Get the relationship part.
69         * @since 2.7.1
70         *
71         * @param create  whether to create it if it doesn't exist
72         * @return
73         */
74        public RelationshipsPart getRelationshipsPart(boolean createIfAbsent) {
75//                      throws InvalidOperationException {
76                if (this instanceof org.docx4j.openpackaging.parts.relationships.RelationshipsPart) {
77                        // a relationship part can't have a relationship part
78                        // but should we throw an error here?
79                        //throw new InvalidOperationException();
80                        return null;
81                }
82               
83                if (relationships == null
84                                && createIfAbsent) {
85                        relationships = RelationshipsPart.createRelationshipsPartForPart(this);
86                }
87               
88                return relationships;
89        }
90
91        public void setRelationships(RelationshipsPart relationships) {
92                               
93                if (relationships!=null) {
94                        relationships.setPackage( getPackage() );
95                }
96               
97                this.relationships = relationships;
98        }
99       
100       
101        protected ContentType contentType;
102
103        public String getContentType() {
104                if (contentType!=null ) {
105                        return contentType.toString();
106                } else {
107                        log.warn("WARNING: content type was null. " +
108                                        "You should set this before adding the part.");
109                        return null;
110                }
111        }
112
113        public void setContentType(ContentType contentType) {
114                log.debug("\nSet contentType " + contentType + " on part " + this.getPartName().getName() +"\n\n");
115                this.contentType = contentType;
116        }
117       
118
119        /**
120         * The part name. (required by the specification [M1.1])
121         *
122         * Note that in docx4J, part names should be resolved,
123         * before being set, so that they are absolute
124         * (ie start with '/').
125         *
126         * We will assume the Package has a part name of "/"
127         *
128         */
129        public PartName partName;
130
131        /**
132         * @return the uri
133         */
134        public PartName getPartName() {
135                if (partName==null) {
136                        log.error("PartName was null!");
137                        try {
138                                return new PartName("/null");
139                        } catch (Exception e) {
140                                log.error(e.getMessage());
141                                // TODO: handle exception
142                        }
143                }
144                return partName;
145        }
146       
147       
148        /** Tell the source Part about this target Part, so the
149         *  source can use this part via a convenience method.
150         * @param part
151         * @param relationshipType
152         * @return true if the source Part does use the target Part
153         * in a convenience method.
154         */
155        public abstract boolean setPartShortcut(Part part, String relationshipType);
156
157//      /**
158//       * Flag if a modification has been made. 
159//       * The semantics are as follows:
160//       * - on a Part: the Part, its relationships part, or a target part
161//       *   has been modified
162//       * - on the Package: its relationships part, or a target part
163//       *   has been modified.
164//       */
165//      protected boolean isDirty = false;
166//     
167//      public boolean isDirty() {
168//              return isDirty;
169//      }
170//
171//      public void setDirty(boolean isDirty) {
172//              this.isDirty = isDirty;
173//      }
174
175        /**
176         * Convenience method to add a part to this Part's
177         * relationships.  The package must be set on this
178         * part in order for this to work.
179         *
180         * @since 2.7.1
181         *
182         * @param targetpart The part to add to this part's relationships
183         * @param mode whether to overwrite, rename or abort if the part name already exists
184         * @param proposedRelId
185         * @return
186         * @throws InvalidFormatException
187         */     
188        public Relationship addTargetPart(Part targetpart, AddPartBehaviour mode
189                        ) throws InvalidFormatException {
190                return addTargetPart(targetpart, mode, null);
191        }
192       
193        /**
194         * Convenience method to add a part to this Part's
195         * relationships.  The package must be set on this
196         * part in order for this to work.
197         *
198         * The added part will replace any existing part
199         * with the same name (ie same target in the rels
200         * part).  In other words, if you want to use the
201         * one image as the target of 2 rels, don't use
202         * this method.
203         *
204         * @param targetpart
205         *            The part to add to this part's relationships
206         */
207        public Relationship addTargetPart(Part targetpart) throws InvalidFormatException {
208                return this.addTargetPart(targetpart, AddPartBehaviour.OVERWRITE_IF_NAME_EXISTS, null);
209        }
210
211        /**
212         * Convenience method to add a part to this Part's
213         * relationships.  The package must be set on this
214         * part in order for this to work.
215         *
216         * The added part will replace any existing part
217         * with the same name (ie same target in the rels
218         * part).  In other words, if you want to use the
219         * one image as the target of 2 rels, don't use
220         * this method.
221         *
222         * @param targetpart
223         *            The part to add to this part's relationships
224         */
225        public Relationship addTargetPart(Part targetpart, String proposedRelId
226                        ) throws InvalidFormatException {
227               
228                return addTargetPart( targetpart, AddPartBehaviour.OVERWRITE_IF_NAME_EXISTS, proposedRelId);
229        }
230       
231       
232        /**
233         * Convenience method to add a part to this Part's
234         * relationships.  The package must be set on this
235         * part in order for this to work.
236         *
237         * The added part will replace any existing part
238         * with the same name (ie same target in the rels
239         * part).  In other words, if you want to use the
240         * one image as the target of 2 rels, don't use
241         * this method.
242         *
243         * @since 2.7.1
244         *
245         * @param targetpart The part to add to this part's relationships
246         * @param mode whether to overwrite, rename or abort if the part name already exists
247         * @param proposedRelId
248         * @return
249         * @throws InvalidFormatException
250         */
251        public Relationship addTargetPart(Part targetpart, AddPartBehaviour mode, String proposedRelId
252                        ) throws InvalidFormatException {
253               
254                if ( this.getPackage()==null ) {                                               
255                        throw new InvalidFormatException("Package not set; if you are adding part2 to part1, make sure part1 is added first.");
256                }
257                if ( this instanceof RelationshipsPart ) {                     
258                        throw new InvalidFormatException("You should add your part to the target part, not the target part's relationships part.");
259                }
260               
261                // Now add the targetpart to the relationships
262                Relationship rel = this.getRelationshipsPart().addPart(targetpart, mode,
263                                getPackage().getContentTypeManager(), proposedRelId);
264               
265                // Finally, set part shortcut if there is one to set
266                boolean shortcutSet = setPartShortcut(targetpart, targetpart.getRelationshipType());
267                if (shortcutSet) {
268                        log.info("shortcut was set");                   
269                }
270               
271                return rel;
272               
273        }
274       
275}
Note: See TracBrowser for help on using the repository browser.