| /***************************************************************************** |
| * (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); |
| } |
| } |
| } |