/*
 * RectangleReportElement.java
 *
 *  iReport  --  Visual designer for generating JasperReports Documents
 *  Copyright (C) 2002  Giulio Toffoli gt@businesslogic.it
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Giulio Toffoli
 *  Via T.Aspetti, 233
 *  35100 Padova ITALY
 *  gt@businesslogic.it
 *
 * Created on 28 febbraio 2003, 19.20
 */
package it.businesslogic.ireport;
import it.businesslogic.ireport.gui.*;
import it.businesslogic.ireport.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.util.*;
import java.util.List;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;


public abstract class TextReportElement extends ReportElement
{
   static public Rotation ROTATION_NONE;
   static public Rotation ROTATION_LEFT;
   static public Rotation ROTATION_RIGHT;
  
   static
   { 
     ROTATION_NONE = new Rotation("None", 0);
     ROTATION_LEFT = new Rotation("Left", 1);
     ROTATION_RIGHT = new Rotation("Right", 2);
   }


   private String text="";
   
   private String reportFont="";
   
   private String fontName="";
   
   private String PDFFontName="";
   
   private int fontSize=10;
   
   private String TTFFont="";
   
   private boolean bold=false;
   
   private boolean underline=false;
   
   private boolean italic=false;
   
   private boolean strikeTrought=false;
   
   private String lineSpacing="";
   
   private String align="";
   
   private String verticalAlign="";
   
   private boolean pdfEmbedded=false;
   
   private String pdfEncoding="";
   
   private java.awt.Font font=null;


   private String rotate = "None";
   
   private boolean isStyledText = false;
   
    private Box box = null;


   
   public TextReportElement(int x, int y, int width, int height)
   {
	  super(x,y,width,height);
      
	  //see net.sf.jasperreports.engine.base.JRBaseFont
	  //setGraphicElementPen("Thin");
	  this.bgcolor = Color.WHITE;
	  this.fgcolor = Color.BLACK;
	  this.text = "Static text\nsecond line";
	  this.verticalAlign = "Top";
	  this.align = "Left";
	  this.lineSpacing = "Single";
          box = new Box();
	  //set font
	  setIReportFont(new IReportFont());	  
   }
   
   public void setIReportFont(IReportFont ireportFont){
   	
   	if(ireportFont == null){
   		ireportFont = new IReportFont();
   	}
   	
	this.fontSize = ireportFont.getFontSize();
	this.fontName = ireportFont.getFontName();//"SansSerif";
	this.PDFFontName = ireportFont.getPDFFontName();//"Helvetica";
	this.pdfEncoding = ireportFont.getPdfEncoding();//"CP1252";
	this.pdfEmbedded = ireportFont.isPdfEmbedded();//false;

	this.font = ireportFont.getJavaAWTFont();
   }

   /** Return a instance of IReportFont. */
   public IReportFont getIReportFont(){
   	
	IReportFont ireportFont = new IReportFont();

	ireportFont.setFontSize(this.fontSize);   	
	ireportFont.setFontName(this.fontName);   	

	ireportFont.setPDFFontName(this.PDFFontName);   	
	ireportFont.setPdfEncoding(this.pdfEncoding);   	
	ireportFont.setPdfEmbedded(this.pdfEmbedded);
	
	ireportFont.setBold(bold);   	
	ireportFont.setItalic(italic);   	

   	if(font != null){
		Map fontAttributes = font.getAttributes();
		ireportFont.setUnderline( (fontAttributes.containsKey(TextAttribute.UNDERLINE) && fontAttributes.get(TextAttribute.UNDERLINE).equals(TextAttribute.UNDERLINE_ON)) );
		ireportFont.setStrikeTrought( (fontAttributes.containsKey(TextAttribute.STRIKETHROUGH) && fontAttributes.get(TextAttribute.STRIKETHROUGH).equals(TextAttribute.STRIKETHROUGH_ON)) );
   	}
   	
   	return ireportFont;
   }
   
   public void drawObject(Graphics2D g,double zoom_factor, int x_shift_origin, int y_shift_origin)
   {
      //System.out.println(new java.util.Date() + " Print text " + this.getText() + " " +  x_shift_origin +" " +y_shift_origin);
      ArrayList               textLayouts;
      float                   x, y;
      TextReportElementLayout textReportElementLayout;
      AffineTransform         transform;
      
      position.x -= 10;
      position.y -= 10;
      x_shift_origin -= 10;
      y_shift_origin -= 10;


      this.zoom_factor = zoom_factor;
      
      
      
      g.setColor( bgcolor );
      if (!getTransparent().equalsIgnoreCase("Transparent"))
      {
         g.fillRect(getZoomedDim(position.x)-x_shift_origin,
                    getZoomedDim(position.y)-y_shift_origin,
                    getZoomedDim(width),
                    getZoomedDim(height));
      }
      g.setColor( this.fgcolor );
      
      // Set font to default font....
      //Font oldFont = g.getFont();
      
      if (font == null)
      {
         int style = 0;
         if (isBold()) style |= Font.BOLD;
         if (isItalic()) style |= Font.ITALIC;
         if (style == 0) style = Font.PLAIN;
         font = new Font( this.getFontName(), style , getZoomedDim( this.getFontSize() ));
      }
           
        // Code for rotation by gt (taked by jasperreports...
        
      
        int gfx_x = getZoomedDim(position.x + getBox().getLeftPadding() )-x_shift_origin;
        int gfx_y = getZoomedDim(position.y + getBox().getTopPadding())-y_shift_origin;
        int gfx_width = getZoomedDim(width - getBox().getLeftPadding() - getBox().getRightPadding());
        int gfx_height = getZoomedDim(height - getBox().getTopPadding() - getBox().getBottomPadding());

        
      Java2DUtil.setClip(g,
 //     0,0, 3000,3000);      
      gfx_x,
      gfx_y,
      gfx_width,
      gfx_height);
       
        double angle = 0;
        double angle_restore = 0;

        
        // Apply the transformation "rotation"
         // - Do nothing when rotate = "none"
         transform = null;
         if(rotate.equals(ROTATION_LEFT.getName()))
         {
           transform = new AffineTransform();
           transform.rotate(-Math.PI / 2, gfx_x, gfx_y);
           transform.translate(-gfx_height, -gfx_height);
           gfx_y = getZoomedDim(position.y)-y_shift_origin + getZoomedDim(height);
           gfx_width = getZoomedDim(height);
           gfx_height = getZoomedDim(width);
           Java2DUtil.setTransform(g, transform);
         }
         else if(rotate.equals(ROTATION_RIGHT.getName()))
         {
           transform = new AffineTransform();
           transform.rotate(Math.PI / 2, gfx_x, gfx_y);
           transform.translate(0, -gfx_width);
           gfx_x = getZoomedDim(position.x)-x_shift_origin + getZoomedDim(width);
           gfx_width = getZoomedDim(height);
           gfx_height = getZoomedDim(width);
           
           Java2DUtil.setTransform(g, transform);
         }
        
        
        // End code for rotation by gt
                
      // We must center the text..
      
/*
                Rectangle orgClipBounds = g.getClipBounds();
                g.setClip(getZoomedDim(position.x)-x_shift_origin,
            getZoomedDim(position.y)-y_shift_origin,
            getZoomedDim(width),
            getZoomedDim(height));
 */
      
      if (this.getText() != null && this.getText().length() > 0)
      {
         int zoomedFieldHeight = gfx_height;
         String allText = Misc.treatNewLineChars(this.getText());
         float formatWidth = (float)gfx_width;
         float verticalOffset = 0f;
         
         
         FontRenderContext fontRenderContext = g.getFontRenderContext();
         java.util.Map fontAttributes = font.getAttributes();
         fontAttributes.put(TextAttribute.SIZE, new Float(getZoomedDim( this.getFontSize() )) );
         fontAttributes.put(TextAttribute.FAMILY, this.getFontName() );
         if (this.isBold())
         {
            fontAttributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
         }
         if (this.isItalic())
         {
            fontAttributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
         }
         if (this.isUnderline())
         {
            fontAttributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
         }
         if (this.isStrikeTrought())
         {
            fontAttributes.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
         }
         
         float lineSpacing = 1f;
         if (this.getLineSpacing().equals("Single")) lineSpacing = 1f;
         else if (this.getLineSpacing().equals("1_1_2")) lineSpacing = 1.5f;
         else if (this.getLineSpacing().equals("Double")) lineSpacing = 2f;
         
         AttributedString atext;
         AttributedCharacterIterator paragraph;
         int paragraphStart;
         int paragraphEnd;
         LineBreakMeasurer lineMeasurer;
         TextLayout layout = null;
         
         
         String paragr_text = "";
         boolean isMaxHeightReached = false;
         
         StringTokenizer tkzer = new StringTokenizer(allText, "\n");
         
         float drawPosY = 0;
         float drawPosX = 0;
        
         paragr_text = "";
         isMaxHeightReached = false;
         
         tkzer = new StringTokenizer(allText, "\n");


         textLayouts = new ArrayList();
        
         // Calculate the layouts. (But don't draw yet because we don't know yet
         //   the offset which is needed if we align the text "middle" or "bottom")
         while(tkzer.hasMoreTokens() && !isMaxHeightReached)
         {
            paragr_text = tkzer.nextToken();
            
            atext = new AttributedString(paragr_text, fontAttributes);
            paragraph = atext.getIterator();
            paragraphStart = paragraph.getBeginIndex();
            paragraphEnd = paragraph.getEndIndex();
            lineMeasurer = new LineBreakMeasurer(paragraph, fontRenderContext);
            lineMeasurer.setPosition(paragraphStart);
            
            layout = null;
            while (lineMeasurer.getPosition() < paragraphEnd && !isMaxHeightReached)
            {
               layout = lineMeasurer.nextLayout(formatWidth);
               
               drawPosY += layout.getLeading() + lineSpacing * layout.getAscent();
               
               if (drawPosY + layout.getDescent() <= zoomedFieldHeight+1)
               {
                  if (this.getAlign().equals("Justify"))
                  {
                     if (layout.isLeftToRight())
                     {
                        drawPosX = 0;
                     }
                     else
                     {
                        drawPosX = formatWidth - layout.getAdvance();
                     }
                     if (lineMeasurer.getPosition() < paragraphEnd)
                     {
                        layout = layout.getJustifiedLayout(formatWidth);
                     }
                  }
                  else if (this.getAlign().equals("Right"))
                  {
                     if (layout.isLeftToRight())
                     {
                        drawPosX = formatWidth - layout.getAdvance();
                     }
                     else
                     {
                        drawPosX = formatWidth;
                     }
                  }
                  else if (this.getAlign().equals("Center"))
                  {
                     drawPosX = (formatWidth - layout.getAdvance()) / 2;
                  }
                  else //if (this.getAlign().equals("Left"))
                  {
                     if (layout.isLeftToRight())
                     {
                        drawPosX = 0;
                     }
                     else
                     {
                        drawPosX = formatWidth - layout.getAdvance();
                     }
                  }
                
                  x = drawPosX + gfx_x; //getZoomedDim(position.x)-x_shift_origin;
                  y = drawPosY + gfx_y; //getZoomedDim(position.y)-y_shift_origin;
                  textReportElementLayout = new TextReportElementLayout(layout, x, y);
                  textLayouts.add(textReportElementLayout);


                  drawPosY += layout.getDescent();
               }
               else
               {
                  drawPosY -= layout.getLeading() + lineSpacing * layout.getAscent();
                  isMaxHeightReached = true;
               }
            }
         }


         // Calculate the offset when aligning the text.
         float textHeight = drawPosY;
         if (this.getVerticalAlign().equals("Top"))
         {
             verticalOffset = 0f;
         }
         else if (this.getVerticalAlign().equals("Middle"))
         {
            verticalOffset = ((float)zoomedFieldHeight- textHeight) / 2f;
         }
         else if (this.getVerticalAlign().equals("Bottom"))
         {
            verticalOffset = (float)zoomedFieldHeight - (float)textHeight;
         }

         

         /*
         
         */
      
         // Now draw the text according to the calculated layouts.
         for(Iterator i=textLayouts.iterator(); i.hasNext();)
         {
           textReportElementLayout = (TextReportElementLayout) i.next();
           textReportElementLayout.drawWithOffset(g, verticalOffset);
         }


         if(transform != null)
         {
           // Undo the transformation "rotation"
           Java2DUtil.resetTransform(g);
         }

         
                    /*
                    int txt_width = g.getFontMetrics().stringWidth( this.getText() )/2;
                    int txt_height = g.getFontMetrics().getHeight();
                     
                    StringTokenizer st = new StringTokenizer(getText(),"\n");
                    while( st.hasMoreElements())
                    {
                     String line = st.nextToken();
                      float formatWidth = (float) this.getWidth();
                     g.drawString(line,
                        (float)(getZoomedDim(position.x)-x_shift_origin),
                        getZoomedDim(position.y)-y_shift_origin +  verticalOffset); //, zoomed_width, getZoomedDim(band.getHeight()
                     
                        verticalOffset += g.getFontMetrics().getHeight();
                    }
                     */
         //g.drawLine(0, getZoomedDim(y)+10-vertical_scroll -  txt_height - getZoomedDim(band.getHeight()/2),  700,getZoomedDim(y)+10-vertical_scroll -  txt_height - getZoomedDim(band.getHeight()/2));
         //g.drawLine(0, getZoomedDim(y)+10-vertical_scroll +  txt_height - getZoomedDim(band.getHeight()/2),  700,getZoomedDim(y)+10-vertical_scroll +  txt_height - getZoomedDim(band.getHeight()/2));
         
      }
      
      
      
      //g.setClip(null);
      //g.setClip(orgClipBounds);
         
      Java2DUtil.resetClip(g);
      position.x += 10;
      position.y += 10;
      x_shift_origin += 10;
      y_shift_origin += 10;
      
      drawBorder( g, zoom_factor,  x_shift_origin,y_shift_origin);
      drawBorder( g, zoom_factor,  x_shift_origin,y_shift_origin,getBox());
      //drawGraphicsElement(g,this.getGraphicElementPen(), zoom_factor,  x_shift_origin,y_shift_origin, 0);
   }
   
   /** Getter for property align.
    * @return Value of property align.
    *
    */
   public java.lang.String getAlign()
   {
      return align;
   }
   
   /** Setter for property align.
    * @param align New value of property align.
    *
    */
   public void setAlign(java.lang.String align)
   {
      this.align = align;
   }
   
   /** Getter for property bold.
    * @return Value of property bold.
    *
    */
   public boolean isBold()
   {
      return bold;
   }
   
   /** Setter for property bold.
    * @param bold New value of property bold.
    *
    */
   public void setBold(boolean bold)
   {
      this.bold = bold;
   }
   
   /** Getter for property font.
    * @return Value of property font.
    *
    */
   public java.awt.Font getFont()
   {
      return font;
   }
   
   /** Setter for property font.
    * @param font New value of property font.
    *
    */
   public void setFont(java.awt.Font font)
   {
      this.font = font;
   }
   
   /** Getter for property fontName.
    * @return Value of property fontName.
    *
    */
   public java.lang.String getFontName()
   {
      return fontName;
   }
   
   /** Setter for property fontName.
    * @param fontName New value of property fontName.
    *
    */
   public void setFontName(java.lang.String fontName)
   {
      this.fontName = fontName;
   }
   
   /** Getter for property fontSize.
    * @return Value of property fontSize.
    *
    */
   public int getFontSize()
   {
      return fontSize;
   }
   
   /** Setter for property fontSize.
    * @param fontSize New value of property fontSize.
    *
    */
   public void setFontSize(int fontSize)
   {
      this.fontSize = fontSize;
   }
   
   /** Setter for property fontSize.
    * @param fontSize New value of property fontSize.
    *
    */
   public void modifyFontSize(int delta)
   {
      if ( (this.fontSize + delta) >= 5) 
      this.fontSize += delta;
   }
   
   /** Getter for property italic.
    * @return Value of property italic.
    *
    */
   public boolean isItalic()
   {
      return italic;
   }
   
   /** Setter for property italic.
    * @param italic New value of property italic.
    *
    */
   public void setItalic(boolean italic)
   {
      this.italic = italic;
   }
   
   /** Getter for property lineSpacing.
    * @return Value of property lineSpacing.
    *
    */
   public java.lang.String getLineSpacing()
   {
      return lineSpacing;
   }
   
   /** Setter for property lineSpacing.
    * @param lineSpacing New value of property lineSpacing.
    *
    */
   public void setLineSpacing(java.lang.String lineSpacing)
   {
      this.lineSpacing = lineSpacing;
   }
   
   /** Getter for property pdfEmbedded.
    * @return Value of property pdfEmbedded.
    *
    */
   public boolean isPdfEmbedded()
   {
      return pdfEmbedded;
   }
   
   /** Setter for property pdfEmbedded.
    * @param pdfEmbedded New value of property pdfEmbedded.
    *
    */
   public void setPdfEmbedded(boolean pdfEmbedded)
   {
      this.pdfEmbedded = pdfEmbedded;
   }
   
   /** Getter for property pdfEncoding.
    * @return Value of property pdfEncoding.
    *
    */
   public java.lang.String getPdfEncoding()
   {
      return pdfEncoding;
   }
   
   /** Setter for property pdfEncoding.
    * @param pdfEncoding New value of property pdfEncoding.
    *
    */
   public void setPdfEncoding(java.lang.String pdfEncoding)
   {
      this.pdfEncoding = pdfEncoding;
   }
   
   /** Getter for property PDFFontName.
    * @return Value of property PDFFontName.
    *
    */
   public java.lang.String getPDFFontName()
   {
      return PDFFontName;
   }
   
   /** Setter for property PDFFontName.
    * @param PDFFontName New value of property PDFFontName.
    *
    */
   public void setPDFFontName(java.lang.String PDFFontName)
   {
      this.PDFFontName = PDFFontName;
   }
   
   /** Getter for property reportFont.
    * @return Value of property reportFont.
    *
    */
   public java.lang.String getReportFont()
   {
      return reportFont;
   }
   
   /** Setter for property reportFont.
    * @param reportFont New value of property reportFont.
    *
    */
   public void setReportFont(java.lang.String reportFont)
   {
      this.reportFont = reportFont;
   }
   
   /** Getter for property strikeTrought.
    * @return Value of property strikeTrought.
    *
    */
   public boolean isStrikeTrought()
   {
      return strikeTrought;
   }
   
   /** Setter for property strikeTrought.
    * @param strikeTrought New value of property strikeTrought.
    *
    */
   public void setStrikeTrought(boolean strikeTrought)
   {
      this.strikeTrought = strikeTrought;
   }
   
   /** Getter for property text.
    * @return Value of property text.
    *
    */
   public java.lang.String getText()
   {
      return text;
   }
   
   /** Setter for property text.
    * @param text New value of property text.
    *
    */
   public void setText(java.lang.String text)
   {
      this.text = text;
   }
   
   /** Getter for property TTFFont.
    * @return Value of property TTFFont.
    *
    */
   public java.lang.String getTTFFont()
   {
      return TTFFont;
   }
   
   /** Setter for property TTFFont.
    * @param TTFFont New value of property TTFFont.
    *
    */
   public void setTTFFont(java.lang.String TTFFont)
   {
      this.TTFFont = TTFFont;
   }
   
   /** Getter for property underline.
    * @return Value of property underline.
    *
    */
   public boolean isUnderline()
   {
      return underline;
   }
   
   /** Setter for property underline.
    * @param underline New value of property underline.
    *
    */
   public void setUnderline(boolean underline)
   {
      this.underline = underline;
   }
   
   /** Getter for property verticalAlign.
    * @return Value of property verticalAlign.
    *
    */
   public java.lang.String getVerticalAlign()
   {
      return verticalAlign;
   }
   
   /** Setter for property verticalAlign.
    * @param verticalAlign New value of property verticalAlign.
    *
    */
   public void setVerticalAlign(java.lang.String verticalAlign)
   {
      this.verticalAlign = verticalAlign;
   }
   
   /** Getter for property Rotate.
    *  Rotate can be one of the values: "none", "left", "right"
    * @return Value of property Rotate.
    */
   public java.lang.String getRotate()
   {
      return rotate;
   }
   
   /** Setter for property Rotate.
    * @param Rotate New value of property Rotate.
    *
    */
   public void setRotate(java.lang.String rotate)
   {
      this.rotate = rotate;
   }
   
   public int getTextHeight(java.awt.FontMetrics fm)
   {
      //
      return fm.getAscent() + (this.getLineCount()-1)*(fm.getHeight());
   }
   
   public int getLineCount()
   {
      // For any \n, return a line...
      String text = this.getText();
      text = text.replace('\r', ' ');
      int line=1;
      while (text.indexOf('\n')>0)
      {
         line++;
         text = text.substring( text.indexOf('\n') + 1);
      }
      return line;
   }
 
   public void copyBaseReportElement(ReportElement destination, ReportElement source)
   {
      super.copyBaseReportElement(destination, source);
      
      if (destination instanceof TextReportElement &&
      source instanceof TextReportElement )
      {
         ((TextReportElement)destination).setAlign(new String(  ((TextReportElement)source).getAlign() ));
         ((TextReportElement)destination).setReportFont(((TextReportElement)source).getReportFont());
         ((TextReportElement)destination).setFontName(new String(  ((TextReportElement)source).getFontName() ));
         ((TextReportElement)destination).setPDFFontName(new String(  ((TextReportElement)source).getPDFFontName() ));
         ((TextReportElement)destination).setFontSize( ((TextReportElement)source).getFontSize() );
         ((TextReportElement)destination).setTTFFont(new String(  ((TextReportElement)source).getTTFFont() ));
         ((TextReportElement)destination).setBold( ((TextReportElement)source).isBold() );
         ((TextReportElement)destination).setItalic( ((TextReportElement)source).isItalic() );
         ((TextReportElement)destination).setUnderline(  ((TextReportElement)source).isUnderline() );
         ((TextReportElement)destination).setStrikeTrought(  ((TextReportElement)source).isStrikeTrought() );
         ((TextReportElement)destination).setLineSpacing(new String(  ((TextReportElement)source).getLineSpacing() ));
         ((TextReportElement)destination).setVerticalAlign(new String(  ((TextReportElement)source).getVerticalAlign() ));
         ((TextReportElement)destination).setPdfEmbedded( ((TextReportElement)source).isPdfEmbedded());
         ((TextReportElement)destination).setPdfEncoding(new String(  ((TextReportElement)source).getPdfEncoding() ));
         ((TextReportElement)destination).setText(new String(  ((TextReportElement)source).getText() ));
         ((TextReportElement)destination).setBox( ((TextReportElement)source).getBox().cloneMe() );
      }
   }


   private class TextReportElementLayout {
       private TextLayout layout;
       private float x;
       private float y;


       private TextReportElementLayout(TextLayout layout, float x, float y) {
           this.layout = layout;
           this.x = x;
           this.y = y;
       }


       void drawWithOffset(Graphics2D g2, float yOffset) {
           layout.draw(g2, x, y + yOffset);
       }
   }


   static List getRotations() {
       return Rotation.rotations;
   }

   /** Getter for property isStyledText.
    * @return Value of property isStyledText.
    *
    */
   public boolean isIsStyledText() {
       return isStyledText;
   }   

   /** Setter for property isStyledText.
    * @param isStyledText New value of property isStyledText.
    *
    */
   public void setIsStyledText(boolean isStyledText) {
       this.isStyledText = isStyledText;
   }
   
   static class Rotation {
       static private ArrayList rotations;
       private String name;
       private int number;


       Rotation(String name, int number) {
           this.name = name;
           this.number = number;
           rotations = new ArrayList();
           rotations.add(this);
       }


       public int getNumber() {
         return number;
       }


       public String getName() {
           return name;
       }


       public String toString() {
           return getName();
       }
   }
   

    public Box getBox() {
        return box;
    }

    public void setBox(Box box) {
        this.box = box;
    }
}
