001package com.hfg.xml.msofficexml.xlsx.spreadsheetml;
002
003import java.util.Collection;
004import java.util.List;
005
006import com.hfg.graphics.units.GfxSize;
007import com.hfg.graphics.units.GfxUnits;
008import com.hfg.util.StringUtil;
009import com.hfg.util.collection.CollectionUtil;
010import com.hfg.xml.XMLAttribute;
011import com.hfg.xml.XMLName;
012import com.hfg.xml.XMLTag;
013import com.hfg.xml.XMLizable;
014import com.hfg.xml.msofficexml.xlsx.CellRef;
015
016//------------------------------------------------------------------------------
017/**
018 Represents an Office Open XML worksheet data row (<ssml:r>) tag.
019
020 @author J. Alex Taylor, hairyfatguy.com
021 */
022//------------------------------------------------------------------------------
023// com.hfg XML/HTML Coding Library
024//
025// This library is free software; you can redistribute it and/or
026// modify it under the terms of the GNU Lesser General Public
027// License as published by the Free Software Foundation; either
028// version 2.1 of the License, or (at your option) any later version.
029//
030// This library is distributed in the hope that it will be useful,
031// but WITHOUT ANY WARRANTY; without even the implied warranty of
032// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
033// Lesser General Public License for more details.
034//
035// You should have received a copy of the GNU Lesser General Public
036// License along with this library; if not, write to the Free Software
037// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
038//
039// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
040// jataylor@hairyfatguy.com
041//------------------------------------------------------------------------------
042
043public class SsmlRow extends SsmlXMLTag
044{
045   private SsmlWorksheet mParentWorksheet;
046
047   // Cached values
048   private List<SsmlCell> mCells;
049
050   //##########################################################################
051   // CONSTRUCTORS
052   //##########################################################################
053
054   //---------------------------------------------------------------------------
055   public SsmlRow(SsmlWorksheet inParentWorksheet)
056   {
057      super(SsmlXML.ROW, inParentWorksheet.getParentDoc());
058      mParentWorksheet = inParentWorksheet;
059   }
060
061   //---------------------------------------------------------------------------
062   public SsmlRow(SsmlWorksheet inParentWorksheet, XMLTag inXMLTag)
063   {
064      this(inParentWorksheet);
065      inXMLTag.verifyTagName(SsmlXML.ROW);
066
067      setRowIndex(Integer.parseInt(inXMLTag.getAttributeValue(SsmlXML.ROW_IDX_ATT)));
068
069      // Copy subtags over to this tag
070      if (CollectionUtil.hasValues(inXMLTag.getSubtags()))
071      {
072         for (XMLTag subtag : (List<XMLTag>) (Object) inXMLTag.getSubtags())
073         {
074            if (subtag.getTagName().equals(SsmlXML.CELL.getLocalName()))
075            {
076               addCell(new SsmlCell(inParentWorksheet, subtag));
077            }
078            else
079            {
080               addSubtag(subtag);
081            }
082         }
083      }
084   }
085
086   //##########################################################################
087   // PUBLIC METHODS
088   //##########################################################################
089
090
091   //---------------------------------------------------------------------------
092   public SsmlRow setRowIndex(int inValue)
093   {
094      setAttribute(SsmlXML.ROW_IDX_ATT, inValue);
095
096      return this;
097   }
098
099   //---------------------------------------------------------------------------
100   public Integer getRowIndex()
101   {
102      XMLAttribute attr = getAttribute(SsmlXML.ROW_IDX_ATT);
103
104      return attr != null ? Integer.parseInt(attr.getValue()) : null;
105   }
106
107   //---------------------------------------------------------------------------
108   public SsmlCell addCell()
109   {
110      String column = "A";
111      // How many cells do we already have?
112      CellRef maxCell = getMaxCellRef();
113      if (maxCell != null)
114      {
115         column = maxCell.nextCol();
116      }
117
118      // They might set the column later but we want to be sure that it has a value.
119      SsmlCell cell = new SsmlCell(mParentWorksheet).setRef(new CellRef(column + getRowIndex()));
120      addSubtag(cell);
121
122      clearCachedValues();
123
124      return cell;
125   }
126
127   //---------------------------------------------------------------------------
128   public SsmlCell setCell(int inColIndex, String inValue)
129   {
130      return addCellByColIndex(inColIndex).setValue(inValue);
131   }
132
133   //---------------------------------------------------------------------------
134   public SsmlCell addCellByColIndex(int inColIndex)
135   {
136      CellRef cellRef = new CellRef().setColIndex(inColIndex).setRowIndex(getRowIndex());
137
138      SsmlCell cell = new SsmlCell(mParentWorksheet).setRef(cellRef);
139      addCell(cell);
140
141      return cell;
142   }
143
144   //---------------------------------------------------------------------------
145   public void addCell(SsmlCell inValue)
146   {
147      int maxColIndex = 0;
148
149      CellRef maxCellRef = getMaxCellRef();
150      if (maxCellRef != null)
151      {
152         maxColIndex = maxCellRef.getColIndex();
153      }
154
155      if (null == inValue.getRef())
156      {
157         // No column specified. Add to the end of the row.
158         inValue.setRef(new CellRef().setColIndex(maxColIndex + 1).setRowIndex(getRowIndex()));
159      }
160
161
162      if (inValue.getRef().getColIndex() > maxColIndex)
163      {
164         // It's the highest value. Just add it to the end.
165         addSubtag(inValue);
166      }
167      else
168      {
169         List<SsmlCell> cells = getCells();
170         for (int i = 0; i < cells.size(); i++)
171         {
172            SsmlCell cell = cells.get(i);
173            if (cell.getRef().equals(inValue.getRef()))
174            {
175               // Replace this cell.
176               addSubtag(getContentPlusSubtagList().indexOf(cells.get(i)), inValue);
177               removeSubtag(cell);
178               break;
179            }
180            else if (cell.getRef().getColIndex() > inValue.getRef().getColIndex())
181            {
182               // Insert before this cell.
183               addSubtag(getContentPlusSubtagList().indexOf(cells.get(i)), inValue);
184               break;
185            }
186         }
187      }
188
189      clearCachedValues();
190   }
191
192   //---------------------------------------------------------------------------
193   public SsmlCell addCell(Object inValue)
194   {
195      return addCell().setValue(inValue);
196   }
197
198   //---------------------------------------------------------------------------
199   public SsmlCell addCell(SsmlTextRun inValue)
200   {
201      return addCell().setValue(inValue);
202   }
203
204   //---------------------------------------------------------------------------
205   public SsmlCell addCell(List<SsmlTextRun> inValue)
206   {
207      return addCell().setValue(inValue);
208   }
209
210   //---------------------------------------------------------------------------
211   public SsmlCell addCell(String inValue)
212   {
213      return addCell().setValue(inValue);
214   }
215
216   //---------------------------------------------------------------------------
217   public SsmlCell addCell(int inValue)
218   {
219      return addCell().setValue(inValue);
220   }
221
222   //---------------------------------------------------------------------------
223   public SsmlCell addCell(long inValue)
224   {
225      return addCell().setValue(inValue);
226   }
227
228   //---------------------------------------------------------------------------
229   public SsmlCell addCell(float inValue)
230   {
231      return addCell().setValue(inValue);
232   }
233
234   //---------------------------------------------------------------------------
235   public SsmlCell addCell(double inValue)
236   {
237      return addCell().setValue(inValue);
238   }
239
240   //---------------------------------------------------------------------------
241   public List<SsmlCell> getCells()
242   {
243      if (null == mCells)
244      {
245         mCells = (List<SsmlCell>) (Object) getSubtagsByName(SsmlXML.CELL);
246      }
247
248      return mCells;
249   }
250
251   //---------------------------------------------------------------------------
252   /**
253    * Returns whether or not any cell in this row contains content.
254    * @return whether or not any cell in this row contains content
255    */
256   public boolean isEmpty()
257   {
258      return null == getFirstCellWithContent();
259   }
260
261   //---------------------------------------------------------------------------
262   /**
263    * Returns the first cell in this row that contains content.
264    * @return the first cell in this row that contains content
265    */
266   public SsmlCell getFirstCellWithContent()
267   {
268      SsmlCell firstCellWithContent = null;
269      List<SsmlCell> cells = getCells();
270      if (CollectionUtil.hasValues(cells))
271      {
272         for (SsmlCell cell : cells)
273         {
274            Object value = cell.getValue();
275            if (value != null
276                && StringUtil.isSet(value.toString()))
277            {
278               firstCellWithContent = cell;
279               break;
280            }
281         }
282      }
283
284      return firstCellWithContent;
285   }
286
287   //---------------------------------------------------------------------------
288   public SsmlCell getCellByColIndex(int inColIndex)
289   {
290      SsmlCell requestedCell = null;
291
292      if (CollectionUtil.hasValues(getCells()))
293      {
294         for (SsmlCell cell : getCells())
295         {
296            if (cell.getRef().getColIndex() == inColIndex)
297            {
298               requestedCell = cell;
299               break;
300            }
301         }
302      }
303
304      return requestedCell;
305   }
306
307   //---------------------------------------------------------------------------
308   public CellRef getMinCellRef()
309   {
310      // How many cells do we already have?
311      CellRef cellRef = null;
312
313      List<XMLTag> cellTags = getSubtagsByName(SsmlXML.CELL);
314      if (CollectionUtil.hasValues(cellTags))
315      {
316         XMLTag firstCell = cellTags.get(0);
317         XMLAttribute attr = firstCell.getAttribute(SsmlXML.REF_ATT);
318         if (attr != null)
319         {
320            cellRef = new CellRef(attr.getValue());
321         }
322      }
323
324      return cellRef;
325   }
326
327   //---------------------------------------------------------------------------
328   public CellRef getMaxCellRef()
329   {
330      // How many cells do we already have?
331      CellRef cellRef = null;
332
333      List<XMLTag> cellTags = getSubtagsByName(SsmlXML.CELL);
334      if (CollectionUtil.hasValues(cellTags))
335      {
336         XMLTag lastCell = cellTags.get(cellTags.size() - 1);
337         XMLAttribute attr = lastCell.getAttribute(SsmlXML.REF_ATT);
338         if (attr != null)
339         {
340            cellRef = new CellRef(attr.getValue());
341         }
342      }
343
344      return cellRef;
345   }
346
347   //---------------------------------------------------------------------------
348   public SsmlRow setHeight(GfxSize inValue)
349   {
350      setAttribute(SsmlXML.HEIGHT_ATT, inValue.to(GfxUnits.points));
351      setAttribute(SsmlXML.CUSTOM_HEIGHT_ATT, "1");
352      return this;
353   }
354
355   //---------------------------------------------------------------------------
356   @Override
357   public synchronized void addSubtags(Collection<? extends XMLizable> inSubtags)
358   {
359      clearCachedValues();
360      super.addSubtags(inSubtags);
361   }
362
363   //---------------------------------------------------------------------------
364   @Override
365   public void addSubtag(XMLizable inSubtag)
366   {
367      clearCachedValues();
368      super.addSubtag(inSubtag);
369   }
370
371   //---------------------------------------------------------------------------
372   @Override
373   public void addSubtag(int inIndex, XMLizable inSubtag)
374   {
375      clearCachedValues();
376      super.addSubtag(inIndex, inSubtag);
377   }
378
379   //--------------------------------------------------------------------------
380   @Override
381   public XMLTag addSubtag(String inTagName)
382   {
383      clearCachedValues();
384      return super.addSubtag(inTagName);
385   }
386
387   //--------------------------------------------------------------------------
388   @Override
389   public XMLTag addSubtag(XMLName inTagName)
390   {
391      clearCachedValues();
392      return super.addSubtag(inTagName);
393   }
394
395   //---------------------------------------------------------------------------
396   private void clearCachedValues()
397   {
398      mCells = null;
399   }
400}