OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 25 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.openoffice;
15
 
16
import static java.util.Arrays.asList;
17
import org.openconcerto.openoffice.ODPackage.RootElement;
57 ilm 18
import org.openconcerto.utils.Tuple2;
17 ilm 19
 
20
import org.jdom.Document;
21
import org.jdom.Element;
22
import org.jdom.Namespace;
23
 
24
/**
25
 * A {@link ContentType} of a certain version.
26
 *
27
 * @author Sylvain
28
 */
29
public enum ContentTypeVersioned {
30
    TEXT_V1(ContentType.TEXT, XMLVersion.OOo, "application/vnd.sun.xml.writer", "text", "sxw") {
31
    },
32
    GRAPHICS_V1(ContentType.GRAPHICS, XMLVersion.OOo, "application/vnd.sun.xml.draw", "drawing", "sxd") {
33
    },
34
    PRESENTATION_V1(ContentType.PRESENTATION, XMLVersion.OOo, "application/vnd.sun.xml.impress", "presentation", "sxi") {
35
    },
36
    SPREADSHEET_V1(ContentType.SPREADSHEET, XMLVersion.OOo, "application/vnd.sun.xml.calc", "spreadsheet", "sxc") {
37
    },
38
    TEXT(ContentType.TEXT, XMLVersion.OD, "application/vnd.oasis.opendocument.text", "text", "odt") {
39
    },
40
    TEXT_TEMPLATE(ContentType.TEXT, XMLVersion.OD, "application/vnd.oasis.opendocument.text-template", "text", "ott") {
41
    },
42
    GRAPHICS(ContentType.GRAPHICS, XMLVersion.OD, "application/vnd.oasis.opendocument.graphics", "drawing", "odg") {
43
    },
44
    GRAPHICS_TEMPLATE(ContentType.GRAPHICS, XMLVersion.OD, "application/vnd.oasis.opendocument.graphics-template", "drawing", "otg") {
45
    },
46
    PRESENTATION(ContentType.PRESENTATION, XMLVersion.OD, "application/vnd.oasis.opendocument.presentation", "presentation", "odp") {
47
    },
48
    PRESENTATION_TEMPLATE(ContentType.PRESENTATION, XMLVersion.OD, "application/vnd.oasis.opendocument.presentation-template", "presentation", "otp") {
49
    },
50
    SPREADSHEET(ContentType.SPREADSHEET, XMLVersion.OD, "application/vnd.oasis.opendocument.spreadsheet", "spreadsheet", "ods") {
51
    },
52
    SPREADSHEET_TEMPLATE(ContentType.SPREADSHEET, XMLVersion.OD, "application/vnd.oasis.opendocument.spreadsheet-template", "spreadsheet", "ots") {
53
    };
54
 
55
    private final ContentType type;
56
    private final XMLVersion version;
57
    private final String mimeType;
58
    // either office:class of the root element for V1
59
    // or the name of the child of office:body for V2
60
    private final String shortName;
61
    private final String extension;
62
 
63
    private ContentTypeVersioned(ContentType type, XMLVersion version, String mimeType, String bodyChildName, String extension) {
64
        this.type = type;
65
        this.mimeType = mimeType;
66
        this.version = version;
67
        this.shortName = bodyChildName;
68
        this.extension = extension;
69
    }
70
 
71
    public final XMLVersion getVersion() {
72
        return this.version;
73
    }
74
 
75
    public final String getShortName() {
76
        return this.shortName;
77
    }
78
 
79
    /**
80
     * Returns the xpath to the body (from below the root element).
81
     *
82
     * @return the xpath to the body, e.g. "./office:body".
83
     */
84
    public final String getBodyPath() {
85
        return this.getVersion() == XMLVersion.OOo ? "./office:body" : "./office:body/office:" + getShortName();
86
    }
87
 
88
    public final Element getBody(final Document doc) {
89
        final Namespace officeNS = this.getVersion().getOFFICE();
90
        final Element body = doc.getRootElement().getChild("body", officeNS);
91
        if (this.getVersion().equals(XMLVersion.OOo))
92
            return body;
93
        else
94
            return body.getChild(getShortName(), officeNS);
95
    }
96
 
97
    public final String getMimeType() {
98
        return this.mimeType;
99
    }
100
 
101
    public final ContentType getType() {
102
        return this.type;
103
    }
104
 
105
    public final String getExtension() {
106
        return this.extension;
107
    }
108
 
57 ilm 109
    public final String getFlatExtension() {
110
        if (this.getVersion() == XMLVersion.OOo)
111
            return null;
112
        return 'f' + this.getExtension();
113
    }
114
 
17 ilm 115
    public final boolean isTemplate() {
116
        return this.getMimeType().endsWith(TEMPLATE_SUFFIX);
117
    }
118
 
119
    public final ContentTypeVersioned getTemplate() {
120
        if (this.isTemplate())
121
            return this;
122
        else
123
            return fromMime(getMimeType() + TEMPLATE_SUFFIX);
124
    }
125
 
126
    public final ContentTypeVersioned getNonTemplate() {
127
        if (this.isTemplate())
128
            return fromMime(getMimeType().substring(0, getMimeType().length() - TEMPLATE_SUFFIX.length()));
129
        else
130
            return this;
131
    }
132
 
133
    /**
134
     * Create a new minimal document using {@link RootElement#CONTENT}.
135
     *
19 ilm 136
     * @param version the version.
17 ilm 137
     * @return the body of the created document.
25 ilm 138
     * @see #createContent(XMLFormatVersion, boolean)
17 ilm 139
     */
19 ilm 140
    public final Element createContent(final XMLFormatVersion version) {
141
        return this.createContent(version, false);
17 ilm 142
    }
143
 
144
    /**
145
     * Create a new minimal document.
146
     *
19 ilm 147
     * @param version the version.
17 ilm 148
     * @param singleXML <code>true</code> for {@link RootElement#SINGLE_CONTENT}, <code>false</code>
149
     *        for {@link RootElement#CONTENT}.
150
     * @return the body of the created document.
25 ilm 151
     * @see #createPackage(XMLFormatVersion)
17 ilm 152
     */
19 ilm 153
    public Element createContent(final XMLFormatVersion version, final boolean singleXML) {
154
        checkVersion(version);
17 ilm 155
        final RootElement rootElement = singleXML ? RootElement.SINGLE_CONTENT : RootElement.CONTENT;
25 ilm 156
        final Document doc = rootElement.createDocument(version);
17 ilm 157
        final Namespace officeNS = getVersion().getOFFICE();
158
        setType(doc, rootElement, officeNS);
159
        // don't forget that, otherwise OO crash
160
        doc.getRootElement().addContent(new Element("automatic-styles", officeNS));
161
 
162
        final Element topBody = new Element("body", officeNS);
163
        final Element body;
164
        if (this.getVersion().equals(XMLVersion.OD)) {
165
            body = new Element(this.getShortName(), officeNS);
166
            topBody.addContent(body);
167
        } else
168
            body = topBody;
169
        doc.getRootElement().addContent(topBody);
170
 
171
        return body;
172
    }
173
 
19 ilm 174
    private final void checkVersion(final XMLFormatVersion version) {
175
        if (version.getXMLVersion() != getVersion())
176
            throw new IllegalArgumentException("Version mismatch : " + version.getXMLVersion());
177
    }
178
 
17 ilm 179
    public void setType(final Document doc) {
25 ilm 180
        this.setType(doc, RootElement.fromDocument(doc), getVersion().getOFFICE());
17 ilm 181
    }
182
 
183
    // not safe
184
    private void setType(final Document doc, final RootElement rootElem, final Namespace officeNS) {
185
        final Element root = doc.getRootElement();
186
        assert root.getName().equals(rootElem.getElementName());
187
        if (rootElem != RootElement.CONTENT && rootElem != RootElement.SINGLE_CONTENT)
188
            throw new IllegalArgumentException("the document is not content : " + rootElem);
189
        if (this.getVersion().equals(XMLVersion.OOo)) {
190
            root.setAttribute("class", this.getShortName(), officeNS);
191
        } else if (this.getVersion().equals(XMLVersion.OD)) {
192
            if (rootElem == RootElement.SINGLE_CONTENT) {
193
                root.setAttribute("mimetype", this.getMimeType(), officeNS);
194
            }
195
            // else ODPackage can use the body to infer the type (office:mimetype is only for single
196
            // xml document)
197
        }
198
    }
199
 
200
    /**
201
     * Create a new minimal document using {@link RootElement#STYLES}.
202
     *
19 ilm 203
     * @param version the version.
17 ilm 204
     * @return the created document.
205
     */
19 ilm 206
    public Document createStyles(final XMLFormatVersion version) {
207
        checkVersion(version);
17 ilm 208
        final Namespace officeNS = getVersion().getOFFICE();
25 ilm 209
        final Document styles = RootElement.STYLES.createDocument(version);
17 ilm 210
        // some consumers demand empty children
211
        styles.getRootElement().addContent(asList(new Element("styles", officeNS), new Element("automatic-styles", officeNS), new Element("master-styles", officeNS)));
212
        return styles;
213
    }
214
 
215
    /**
216
     * Creates an empty package.
217
     *
19 ilm 218
     * @param version the version of the package.
17 ilm 219
     * @return a new package with minimal {@link RootElement#CONTENT} and {@link RootElement#STYLES}
220
     */
19 ilm 221
    public ODPackage createPackage(final XMLFormatVersion version) {
25 ilm 222
        return ODPackage.createFromDocuments(this, this.createContent(version, false).getDocument(), this.createStyles(version), null, null);
17 ilm 223
    }
224
 
225
    // *** static
226
 
227
    private static final String TEMPLATE_SUFFIX = "-template";
228
 
229
    static ContentTypeVersioned fromType(ContentType type, XMLVersion version, final boolean template) {
230
        for (final ContentTypeVersioned t : ContentTypeVersioned.values())
231
            if (t.getType().equals(type) && t.getVersion() == version && t.isTemplate() == template)
232
                return t;
233
        return null;
234
    }
235
 
236
    static public ContentTypeVersioned fromMime(String mime) {
237
        for (final ContentTypeVersioned t : ContentTypeVersioned.values())
238
            if (t.getMimeType().equals(mime))
239
                return t;
240
        return null;
241
    }
242
 
25 ilm 243
    static public ContentTypeVersioned fromMime(byte[] mime) {
244
        return fromMime(new String(mime, ODPackage.MIMETYPE_ENC));
245
    }
246
 
247
    static ContentTypeVersioned fromContent(final ODXMLDocument content) {
248
        final ContentTypeVersioned res;
249
        final XMLVersion vers = content.getVersion();
250
        if (vers.equals(XMLVersion.OOo)) {
251
            final Element contentRoot = content.getDocument().getRootElement();
252
            final String docClass = contentRoot.getAttributeValue("class", contentRoot.getNamespace("office"));
253
            res = ContentTypeVersioned.fromClass(docClass);
254
        } else if (vers.equals(XMLVersion.OD)) {
255
            final Element bodyChild = (Element) content.getChild("body").getChildren().get(0);
256
            res = ContentTypeVersioned.fromBody(bodyChild.getName());
257
        } else {
258
            throw new IllegalStateException("Unknown content version : " + vers);
259
        }
260
        assert !res.isTemplate() : "template status cannot be inferred from content";
261
        return res;
262
    }
263
 
17 ilm 264
    static ContentTypeVersioned fromClass(String name) {
265
        return fromShortName(XMLVersion.OOo, name);
266
    }
267
 
268
    static ContentTypeVersioned fromBody(String name) {
269
        return fromShortName(XMLVersion.OD, name);
270
    }
271
 
272
    static private ContentTypeVersioned fromShortName(XMLVersion version, String name) {
273
        if (name == null)
274
            throw new NullPointerException();
275
 
276
        for (final ContentTypeVersioned t : ContentTypeVersioned.values())
277
            if (t.shortName.equals(name) && t.getVersion() == version)
278
                return t;
279
        return null;
280
    }
57 ilm 281
 
282
    // Boolean : is flat
283
    static Tuple2<ContentTypeVersioned, Boolean> fromExtension(final String extension) {
284
        if (extension != null && extension.length() != 0) {
285
            for (final ContentTypeVersioned t : ContentTypeVersioned.values()) {
286
                if (extension.equals(t.getExtension()))
287
                    return Tuple2.create(t, false);
288
                if (extension.equals(t.getFlatExtension()))
289
                    return Tuple2.create(t, true);
290
            }
291
        }
292
        return Tuple2.nullInstance();
293
    }
17 ilm 294
}