OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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