blob: 993be15541910cc652b280f5389d483e0a674001 [file] [log] [blame]
/*****************************************************************************
* (c) Copyright 2016 Telefonaktiebolaget LM Ericsson
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Antonio Campesino (Ericsson) antonio.campesino.robles@ericsson.com - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.gendoc.document.parser.documents.openoffice;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import javax.xml.xpath.XPathExpressionException;
import org.eclipse.core.runtime.Path;
import org.eclipse.gendoc.document.parser.documents.Document.CONFIGURATION;
import org.eclipse.gendoc.document.parser.documents.XMLParser;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public abstract class OpenOfficeParser extends XMLParser {
private OpenOfficeDocument openOfficeDocument;
private XMLParser relationships;
private int relationshipsNextId;
private HashMap<String, XMLParser> partsDocuments;
public OpenOfficeParser(OpenOfficeDocument document, File f) {
super(f);
openOfficeDocument = document;
parse();
}
public OpenOfficeParser(OpenOfficeDocument document, File f, CONFIGURATION conf) {
super(f,conf);
openOfficeDocument = document;
parse();
}
protected abstract OpenOfficeXPathUtils getXPathUtils();
public OpenOfficeDocument getOpenOfficeDocument() {
return this.openOfficeDocument;
}
public String getRelationshipsPath() {
return getPartParentRelativePath()+"/"+"_rels"+"/"+getXmlFile().getName()+".rels";
}
public String getPartParentRelativePath() {
try {
return getXmlFile().getParentFile().getAbsolutePath().replace(
getOpenOfficeDocument().getUnzipLocationDocumentFile().getCanonicalPath(),"").
replace(File.separatorChar, '/');
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public String getPartRelativePath() {
try {
return getXmlFile().getAbsolutePath().replace(
getOpenOfficeDocument().getUnzipLocationDocumentFile().getCanonicalPath(),"").
replace(File.separatorChar, '/');
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected void parse() {
String relpath = getPartRelativePath().replace(getXmlFile().getName(),"")+
"_rels/"+getXmlFile().getName()+".rels" ;
relationships = getOpenOfficeDocument().getSubdocument(relpath);
if (relationships != null) {
relationshipsNextId = getNextRelationId();
}
partsDocuments= new HashMap<String, XMLParser>();
}
public XMLParser loadExplicitPartDocument(String rel, String relId) throws IOException {
return loadPartDocument(relId+":"+rel,"//rel:Relationship[@Type='"+rel+
"' and @Id='"+relId+"']/@Target");
}
public XMLParser loadImplicitPartDocument(String rel) throws IOException {
return loadPartDocument(rel,"//rel:Relationship[@Type='"+rel+"']/@Target");
}
private XMLParser loadPartDocument(String key, String xpath) throws IOException {
XMLParser parser = partsDocuments.get(key);
if (parser == null && relationships != null) {
try {
NodeList nl = getXPathUtils().evaluateNodes(relationships.getDocument(),xpath);
if (nl.getLength() == 0)
return null;
String target = ((Attr)nl.item(0)).getValue();
File f = new File(getOpenOfficeDocument().getUnzipLocationDocumentFile(),
target.replace("/", File.separator));
if (!target.startsWith("/")) {
f = new File(getXmlFile().getParentFile(),target).getCanonicalFile();
}
String relpath = f.getAbsolutePath().replace(
getOpenOfficeDocument().getUnzipLocationDocumentFile().getCanonicalPath(),"");
parser = getOpenOfficeDocument().getSubdocument(relpath);
if (parser != null)
partsDocuments.put(key,parser);
} catch (XPathExpressionException e) {
throw new IllegalArgumentException(e);
}
}
return parser;
}
/**
* Add an explicit relationship of the provided type to the provided target. A new relationship
* is generated and returned to be used to reference new relationship.
*
* @param relationshipType the type of the relationship.
* @param target the target of the relation
* @return
* @throws IOException
*/
public String addRelationship(String relationshipType, String target) throws IOException {
try {
if (relationships == null) {
createRelationshipPart();
}
Element relationshipsEl = (Element)getXPathUtils().evaluateNode(relationships.getDocument(),"/rel:Relationships");
Element rel = (Element)relationshipsEl.appendChild(relationships.getDocument().createElementNS(
OpenOfficeHelper.PACKAGE_RELATIONSHIPS_NAMESPACE, "rel:Relationship"));
String id = "rId"+relationshipsNextId;
rel.setAttribute("Id",id);
rel.setAttribute("Type",relationshipType);
String relTarget = new Path(target).makeRelativeTo(new Path(getPartParentRelativePath())).toString();
rel.setAttribute("Target",relTarget);
relationshipsNextId++;
return id;
} catch (XPathExpressionException e) {
throw new IllegalArgumentException(e);
}
}
private void createRelationshipPart() throws IOException {
relationships = getOpenOfficeDocument().createSubdocument(getRelationshipsPath(),
"<Relationships xmlns=\""+OpenOfficeHelper.PACKAGE_RELATIONSHIPS_NAMESPACE+"\"/>");
relationshipsNextId += 1;
}
public int getNextRelationId() {
try {
List<String> values = getXPathUtils().evaluateValues(relationships.getDocument(),
"/rel:Relationships/rel:Relationship/@Id[starts-with(.,'rId')]");
int nextId = 1;
for (int i=0; i<values.size(); i++) {
String last = values.get(i).substring(3);
try {
nextId = Math.max(nextId, Integer.valueOf(last));
} catch (NumberFormatException e) {}
}
return nextId+1;
} catch (XPathExpressionException e) {
throw new IllegalArgumentException(e);
}
}
}