Dépôt officiel du code source de l'ERP OpenConcerto
Rev 57 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.openoffice;
import static java.util.Arrays.asList;
import org.openconcerto.openoffice.ODPackage.RootElement;
import org.openconcerto.utils.Tuple2;
import java.io.File;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
/**
* A {@link ContentType} of a certain version.
*
* @author Sylvain
*/
public enum ContentTypeVersioned {
TEXT_V1(ContentType.TEXT, XMLVersion.OOo, "application/vnd.sun.xml.writer", "text", "sxw") {
},
GRAPHICS_V1(ContentType.GRAPHICS, XMLVersion.OOo, "application/vnd.sun.xml.draw", "drawing", "sxd") {
},
PRESENTATION_V1(ContentType.PRESENTATION, XMLVersion.OOo, "application/vnd.sun.xml.impress", "presentation", "sxi") {
},
SPREADSHEET_V1(ContentType.SPREADSHEET, XMLVersion.OOo, "application/vnd.sun.xml.calc", "spreadsheet", "sxc") {
},
TEXT(ContentType.TEXT, XMLVersion.OD, "application/vnd.oasis.opendocument.text", "text", "odt") {
},
TEXT_TEMPLATE(ContentType.TEXT, XMLVersion.OD, "application/vnd.oasis.opendocument.text-template", "text", "ott") {
},
GRAPHICS(ContentType.GRAPHICS, XMLVersion.OD, "application/vnd.oasis.opendocument.graphics", "drawing", "odg") {
},
GRAPHICS_TEMPLATE(ContentType.GRAPHICS, XMLVersion.OD, "application/vnd.oasis.opendocument.graphics-template", "drawing", "otg") {
},
PRESENTATION(ContentType.PRESENTATION, XMLVersion.OD, "application/vnd.oasis.opendocument.presentation", "presentation", "odp") {
},
PRESENTATION_TEMPLATE(ContentType.PRESENTATION, XMLVersion.OD, "application/vnd.oasis.opendocument.presentation-template", "presentation", "otp") {
},
SPREADSHEET(ContentType.SPREADSHEET, XMLVersion.OD, "application/vnd.oasis.opendocument.spreadsheet", "spreadsheet", "ods") {
},
SPREADSHEET_TEMPLATE(ContentType.SPREADSHEET, XMLVersion.OD, "application/vnd.oasis.opendocument.spreadsheet-template", "spreadsheet", "ots") {
};
private final ContentType type;
private final XMLVersion version;
private final String mimeType;
// either office:class of the root element for V1
// or the name of the child of office:body for V2
private final String shortName;
private final String extension;
private ContentTypeVersioned(ContentType type, XMLVersion version, String mimeType, String bodyChildName, String extension) {
this.type = type;
this.mimeType = mimeType;
this.version = version;
this.shortName = bodyChildName;
this.extension = extension;
}
public final XMLVersion getVersion() {
return this.version;
}
public final String getShortName() {
return this.shortName;
}
/**
* Returns the xpath to the body (from below the root element).
*
* @return the xpath to the body, e.g. "./office:body".
*/
public final String getBodyPath() {
return this.getVersion() == XMLVersion.OOo ? "./office:body" : "./office:body/office:" + getShortName();
}
public final Element getBody(final Document doc) {
final Namespace officeNS = this.getVersion().getOFFICE();
final Element body = doc.getRootElement().getChild("body", officeNS);
if (this.getVersion().equals(XMLVersion.OOo))
return body;
else
return body.getChild(getShortName(), officeNS);
}
public final String getMimeType() {
return this.mimeType;
}
public final ContentType getType() {
return this.type;
}
public final String getExtension() {
return this.extension;
}
public final String getFlatExtension() {
if (this.getVersion() == XMLVersion.OOo)
return null;
return 'f' + this.getExtension();
}
final File addExt(File f, final boolean flat) {
final String ext = '.' + (flat ? this.getFlatExtension() : this.getExtension());
if (!f.getName().endsWith(ext))
f = new File(f.getParentFile(), f.getName() + ext);
return f;
}
public final boolean isTemplate() {
return this.getMimeType().endsWith(TEMPLATE_SUFFIX);
}
public final ContentTypeVersioned getTemplate() {
if (this.isTemplate())
return this;
else
return fromMime(getMimeType() + TEMPLATE_SUFFIX);
}
public final ContentTypeVersioned getNonTemplate() {
if (this.isTemplate())
return fromMime(getMimeType().substring(0, getMimeType().length() - TEMPLATE_SUFFIX.length()));
else
return this;
}
/**
* Create a new minimal document using {@link RootElement#CONTENT}.
*
* @param version the version.
* @return the body of the created document.
* @see #createContent(XMLFormatVersion, boolean)
*/
public final Element createContent(final XMLFormatVersion version) {
return this.createContent(version, false);
}
/**
* Create a new minimal document.
*
* @param version the version.
* @param singleXML <code>true</code> for {@link RootElement#SINGLE_CONTENT}, <code>false</code>
* for {@link RootElement#CONTENT}.
* @return the body of the created document.
* @see #createPackage(XMLFormatVersion)
*/
public Element createContent(final XMLFormatVersion version, final boolean singleXML) {
checkVersion(version);
final RootElement rootElement = singleXML ? RootElement.SINGLE_CONTENT : RootElement.CONTENT;
final Document doc = rootElement.createDocument(version);
final Namespace officeNS = getVersion().getOFFICE();
setType(doc, rootElement, officeNS);
// don't forget that, otherwise OO crash
doc.getRootElement().addContent(new Element("automatic-styles", officeNS));
final Element topBody = new Element("body", officeNS);
final Element body;
if (this.getVersion().equals(XMLVersion.OD)) {
body = new Element(this.getShortName(), officeNS);
topBody.addContent(body);
} else
body = topBody;
doc.getRootElement().addContent(topBody);
return body;
}
private final void checkVersion(final XMLFormatVersion version) {
if (version.getXMLVersion() != getVersion())
throw new IllegalArgumentException("Version mismatch : " + version.getXMLVersion());
}
public void setType(final Document doc) {
this.setType(doc, RootElement.fromDocument(doc), getVersion().getOFFICE());
}
// not safe
private void setType(final Document doc, final RootElement rootElem, final Namespace officeNS) {
final Element root = doc.getRootElement();
assert root.getName().equals(rootElem.getElementName());
if (rootElem != RootElement.CONTENT && rootElem != RootElement.SINGLE_CONTENT)
throw new IllegalArgumentException("the document is not content : " + rootElem);
if (this.getVersion().equals(XMLVersion.OOo)) {
root.setAttribute("class", this.getShortName(), officeNS);
} else if (this.getVersion().equals(XMLVersion.OD)) {
if (rootElem == RootElement.SINGLE_CONTENT) {
root.setAttribute("mimetype", this.getMimeType(), officeNS);
}
// else ODPackage can use the body to infer the type (office:mimetype is only for single
// xml document)
}
}
/**
* Create a new minimal document using {@link RootElement#STYLES}.
*
* @param version the version.
* @return the created document.
*/
public Document createStyles(final XMLFormatVersion version) {
checkVersion(version);
final Namespace officeNS = getVersion().getOFFICE();
final Document styles = RootElement.STYLES.createDocument(version);
// some consumers demand empty children
styles.getRootElement().addContent(asList(new Element("styles", officeNS), new Element("automatic-styles", officeNS), new Element("master-styles", officeNS)));
return styles;
}
/**
* Creates an empty package.
*
* @param version the version of the package.
* @return a new package with minimal {@link RootElement#CONTENT} and {@link RootElement#STYLES}
*/
public ODPackage createPackage(final XMLFormatVersion version) {
return ODPackage.createFromDocuments(this, this.createContent(version, false).getDocument(), this.createStyles(version), null, null);
}
// *** static
private static final String TEMPLATE_SUFFIX = "-template";
static ContentTypeVersioned fromType(ContentType type, XMLVersion version, final boolean template) {
for (final ContentTypeVersioned t : ContentTypeVersioned.values())
if (t.getType().equals(type) && t.getVersion() == version && t.isTemplate() == template)
return t;
return null;
}
static public ContentTypeVersioned fromMime(String mime) {
for (final ContentTypeVersioned t : ContentTypeVersioned.values())
if (t.getMimeType().equals(mime))
return t;
return null;
}
static public ContentTypeVersioned fromMime(byte[] mime) {
return fromMime(new String(mime, ODPackage.MIMETYPE_ENC));
}
static ContentTypeVersioned fromContent(final ODXMLDocument content) {
final ContentTypeVersioned res;
final XMLVersion vers = content.getVersion();
if (vers.equals(XMLVersion.OOo)) {
final Element contentRoot = content.getDocument().getRootElement();
final String docClass = contentRoot.getAttributeValue("class", contentRoot.getNamespace("office"));
res = ContentTypeVersioned.fromClass(docClass);
} else if (vers.equals(XMLVersion.OD)) {
final Element bodyChild = (Element) content.getChild("body").getChildren().get(0);
res = ContentTypeVersioned.fromBody(bodyChild.getName());
} else {
throw new IllegalStateException("Unknown content version : " + vers);
}
assert !res.isTemplate() : "template status cannot be inferred from content";
return res;
}
static ContentTypeVersioned fromClass(String name) {
return fromShortName(XMLVersion.OOo, name);
}
static ContentTypeVersioned fromBody(String name) {
return fromShortName(XMLVersion.OD, name);
}
static private ContentTypeVersioned fromShortName(XMLVersion version, String name) {
if (name == null)
throw new NullPointerException();
for (final ContentTypeVersioned t : ContentTypeVersioned.values())
if (t.shortName.equals(name) && t.getVersion() == version)
return t;
return null;
}
// Boolean : is flat
static Tuple2<ContentTypeVersioned, Boolean> fromExtension(final String extension) {
if (extension != null && extension.length() != 0) {
for (final ContentTypeVersioned t : ContentTypeVersioned.values()) {
if (extension.equals(t.getExtension()))
return Tuple2.create(t, false);
if (extension.equals(t.getFlatExtension()))
return Tuple2.create(t, true);
}
}
return Tuple2.nullInstance();
}
}