001package com.hfg.xml.msofficexml.part;
002
003import java.io.File;
004import java.io.Writer;
005import java.net.URL;
006import java.util.ArrayList;
007import java.util.List;
008
009import com.hfg.util.StringUtil;
010import com.hfg.util.collection.CollectionUtil;
011import com.hfg.util.FileUtil;
012import com.hfg.xml.XMLTag;
013import com.hfg.xml.msofficexml.OfficeOpenXmlDocument;
014import com.hfg.xml.msofficexml.OfficeOpenXmlRelationship;
015import com.hfg.xml.msofficexml.OfficeXML;
016import com.hfg.xml.msofficexml.RelationshipType;
017
018//------------------------------------------------------------------------------
019/**
020 Represents an Office Open XML relationship part.
021
022 @author J. Alex Taylor, hairyfatguy.com
023 */
024//------------------------------------------------------------------------------
025// com.hfg XML/HTML Coding Library
026//
027// This library is free software; you can redistribute it and/or
028// modify it under the terms of the GNU Lesser General Public
029// License as published by the Free Software Foundation; either
030// version 2.1 of the License, or (at your option) any later version.
031//
032// This library is distributed in the hope that it will be useful,
033// but WITHOUT ANY WARRANTY; without even the implied warranty of
034// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
035// Lesser General Public License for more details.
036//
037// You should have received a copy of the GNU Lesser General Public
038// License along with this library; if not, write to the Free Software
039// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
040//
041// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
042// jataylor@hairyfatguy.com
043//------------------------------------------------------------------------------
044
045public abstract class OfficeOpenXmlRelationshipPart extends OfficeXMLPart
046{
047   // Because file paths may not be initially set, we delay rendering out the
048   // relationship XML until the last moment.
049   private List<OfficeOpenXmlRelationship> mRelationships;
050
051   private int           mIndex = 1;
052
053   //---------------------------------------------------------------------------
054   public OfficeOpenXmlRelationshipPart(OfficeOpenXmlDocument inOfficeDoc)
055   {
056      super(inOfficeDoc);
057      setRootNode(new XMLTag(OfficeXML.RELATIONSHIPS));
058   }
059
060   //---------------------------------------------------------------------------
061   public String addRelationship(OfficeOpenXmlRelationship inValue)
062   {
063      String id = null;
064
065      if (inValue != null)
066      {
067         id = inValue.getId();
068         if (!StringUtil.isSet(id))
069         {
070            id = generateId();
071            inValue.setId(id);
072         }
073
074         if (null == mRelationships)
075         {
076            mRelationships = new ArrayList<>(25);
077         }
078
079         mRelationships.add(inValue);
080
081         if (inValue.getPart() != null)
082         {
083            // Register the content type
084            getParentDoc().getContentTypesPart().addOverride(inValue.getPart(), inValue.getType().getContentType());
085         }
086      }
087
088      return id;
089   }
090
091   //---------------------------------------------------------------------------
092   public String addRelationship(RelationshipType inType, OfficeXMLPart inPart)
093   {
094      OfficeOpenXmlRelationship relationship = new OfficeOpenXmlRelationship();
095      relationship.setPart(inPart)
096                  .setType(inType)
097                  .setId(generateId());
098
099      if (null == mRelationships)
100      {
101         mRelationships = new ArrayList<>(25);
102      }
103
104      mRelationships.add(relationship);
105
106      return relationship.getId();
107   }
108
109   //---------------------------------------------------------------------------
110   public String addRelationship(RelationshipType inType, File inTarget)
111   {
112      return addRelationship(new OfficeOpenXmlRelationship()
113            .setId(generateId())
114            .setType(inType)
115            .setTarget(getRelativePath(inTarget)));
116   }
117
118   //---------------------------------------------------------------------------
119   public String addHyperlink(URL inValue)
120   {
121      return addRelationship(new OfficeOpenXmlRelationship()
122            .setId(generateId())
123            .setType(RelationshipType.HYPERLINK)
124            .setTarget(inValue.toString())
125            .setTargetMode("External"));
126   }
127
128   //---------------------------------------------------------------------------
129   public String addMedia(MediaPart inValue)
130   {
131//      getParentDoc().addMediaPart(inValue);
132
133      return addRelationship(RelationshipType.IMAGE, inValue);
134   }
135
136   //---------------------------------------------------------------------------
137   @Override
138   public void toXML(Writer inWriter)
139   {
140      // Because file paths may not be initially set, we delay rendering out the
141      // relationship XML until the last moment.
142      populateXML();
143      super.toXML(inWriter);
144   }
145
146   //---------------------------------------------------------------------------
147   @Override
148   public void toIndentedXML(Writer inWriter, int inInitialIndentLevel, int inIndentSize)
149   {
150      // Because file paths may not be initially set, we delay rendering out the
151      // relationship XML until the last moment.
152      populateXML();
153      super.toIndentedXML(inWriter, inInitialIndentLevel, inIndentSize);
154   }
155
156   //---------------------------------------------------------------------------
157   public void populateXML()
158   {
159      XMLTag rootNode = new XMLTag(OfficeXML.RELATIONSHIPS);
160      if (CollectionUtil.hasValues(mRelationships))
161      {
162         for (OfficeOpenXmlRelationship relationship : mRelationships)
163         {
164            XMLTag relationshipTag = new XMLTag(OfficeXML.RELATIONSHIP);
165            relationshipTag.setAttribute(OfficeXML.ID_ATT, relationship.getId());
166            relationshipTag.setAttribute(OfficeXML.TYPE_ATT, relationship.getType());
167
168            String target = relationship.getTarget();
169            if (null == target)
170            {
171               target = getRelativePath(relationship.getPart().getFile());
172            }
173
174            relationshipTag.setAttribute(OfficeXML.TARGET_ATT, target);
175
176            String targetMode = relationship.getTargetMode();
177            if (StringUtil.isSet(targetMode))
178            {
179               relationshipTag.setAttribute(OfficeXML.TARGET_MODE_ATT, targetMode);
180            }
181
182
183            rootNode.addSubtag(relationshipTag);
184         }
185      }
186
187      setRootNode(rootNode);
188   }
189
190   //---------------------------------------------------------------------------
191   protected String generateId()
192   {
193      return "rId" + (mIndex++);
194   }
195/*
196   //---------------------------------------------------------------------------
197   private String getRelativePath(File inFile)
198   {
199      String relativePath = FileUtil.getRelativePath(inFile, getFile().getParentFile());
200      if (relativePath.startsWith("./"))
201      {
202         relativePath = relativePath.substring(2);
203      }
204
205      return relativePath;
206//      String path = inFile.getPath();
207//      if (path.startsWith(getFile().getParentFile().getParentFile().getPath()))
208//      {
209//         path = path.substring(getFile().getParentFile().getParentFile().getPath().length() + 1);
210//      }
211//
212//      return path;
213   }
214*/
215   //---------------------------------------------------------------------------
216   protected String getRelativePath(File inFile)
217   {
218      String path = inFile.getPath();
219      if (path.startsWith(getFile().getParentFile().getParentFile().getPath()))
220      {
221         path = path.substring(getFile().getParentFile().getParentFile().getPath().length() + 1);
222      }
223
224      // Also ensure that the file paths consistently use '/' instead of '\' even if
225      // generated on a Windoze system.  Windoze separators were causing files to appear corrupt.
226      return FileUtil.convertSeparatorsToUnix(path);
227   }
228
229}