package util;

import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import DrawTop.*;
import shape.*;
import textBox.*;
import geomExtension.*;


public class DrawFileIo
{
    public final String[] versions={"ver0.0", "ver1.0", "ver1_0"};
	private int depth=0;
    public int debug=0;
    
    public DrawFileIo(){}

//--------------------------//
// write PageList
//--------------------------//
   public void writePageList(String filePath, ArrayList outputPageList)
			throws Exception {
		ObjectOutputStream out
				= new ObjectOutputStream(new FileOutputStream(filePath));
		int size = outputPageList.size();
		if (debug > 0) {
			System.out.println(" -- write file ver0.0, total page=" + size);
		}
		try {
			out.writeUTF(this.versions[2]);
			out.writeInt(size);
			for (int i = 0; i < size; i++) {
				PageData outputPageData = (PageData)outputPageList.get(i);
				ViewData.writeViewData(out, outputPageData.viewData, this.versions[2]);
			  //-------------------------------------------------------------------------------//
				this.writeContainerList(i, out, this.versions[2], outputPageData.ContainerList);
		       //-------------------------------------------------------------------------------//
			}
		} catch (Exception e) {
			System.err.println("*** Error writeOutputPageList e=" + e);
			e.printStackTrace();
		}
		out.close();
		return;
	}

//--------------------------//
// write ContainerList      //
//--------------------------//
	public void writeContainerList(int page, ObjectOutputStream out, String version,
			ArrayList containerList) {
		ArrayList serializableElementList = new ArrayList();
		//------------------------------------------------------------------//
		this.convertContainerList(containerList, serializableElementList);
		//------------------------------------------------------------------//
		int size = serializableElementList.size();
		try {
			out.writeUTF(version);
			out.writeInt(size);
			for (int i = 0; i < size; i++) {
				SerializableElement sShape = (SerializableElement) serializableElementList.get(i);
			  //------------------------------------------//
				this.writeSerializableElement(out, sShape);
			  //------------------------------------------//
			}
		} catch (Exception e) {
			System.err.println("*** Error writeContainerList e~" + e);
			e.printStackTrace();
		}
		return;
	}

	public void convertContainerList(ArrayList containerList, ArrayList serializableElementList) {
		int size = containerList.size();
		for (int i = 0; i < size; i++) {
			ShapeContainer container
					= (ShapeContainer) containerList.get(i);
		  //-----------------------------------------------------------------------//
			SerializableElement[] sElements= this.convertShapeContainer(container);
		  //-----------------------------------------------------------------------//
			for (int j = 0; j < sElements.length; j++) {
				serializableElementList.add(sElements[j]);
			}
		}
		if (debug >0) {
			System.out.println("\n*** DrawFileIo convertContainerList before convert ***");
			this.printContainerList("out","Print ContainerList",containerList);
			System.out.println("\n*** DrawFileIo convertContainerList after convert ***");
			this.printSerializableElementList("out","Print SerializableElementList",
					serializableElementList);
		}
		return;
	}

// Convert to write format of ShapeContainer   //
	public SerializableElement[] convertShapeContainer(ShapeContainer container) {
		SerializableElement[] sElements = null;
		if (container.getContainerType() == container.SHAPE) {
			sElements = new SerializableElement[1];
		  //-----------------------------------------------------------------------//
			sElements[0] = SerializableElementUtil.convertSingleContainer(container);
			//sElements[0] = SerializableElementUtil_org.convertContainerSimply(container);
		  //-----------------------------------------------------------------------//
		} else {
		  //---------------------------------------------------//
			sElements = this.convertGroupContainer(container);
			//sElements = convertGroupContainerSimply(container);
		  //---------------------------------------------------//
		}
		return sElements;
	}

	public SerializableElement[] convertGroupContainer(ShapeContainer container) {
		SerializableElement[] sElements = null;
		ShapeContainer[] containers = container.getGroupedContainers();
		sElements = new SerializableElement[containers.length];
		for (int i = 0; i < containers.length; i++) {
		  //------------------------------------------------------------------------------//
			sElements[i] = SerializableElementUtil.convertShapeContainer(containers[i]);
			//sElements[i] = SerializableElementUtil_org.convertContainerSimply(containers[i]);
		   //-----------------------------------------------------------------------------//
		   if(sElements[i].containerType==ShapeContainer.GROUP){
			   ArrayList childrenList=sElements[i].childrenList;
			   for(int j=0;j<childrenList.size();j++){
				   String shapeId=((SerializableElement)childrenList.get(j)).shapeId;
				   sElements[i].childrenList.set(j, shapeId);
			   }
		   }
		}
		return sElements;
	}

	public void writeSerializableElement(ObjectOutputStream out, SerializableElement sElement)
			throws Exception {
		try {
			out.writeUTF(this.versions[1]);
			//sElement for ShapeContainer
			out.writeInt(sElement.containerType);
			out.writeInt(sElement.containerIndex);
			out.writeUTF(sElement.parent);
			//sElement for shapeElement
			out.writeUTF(sElement.elementType);
			//out.writeInt(sElement.elementType);
			out.writeUTF(sElement.shapeId);
			out.writeObject(sElement.date);
			out.writeUTF(sElement.fileNameAndPage);
			out.writeBoolean(sElement.connectorTargetPermission);
			out.writeBoolean(sElement.connectorPermission);
			out.writeObject(sElement.property);
			int ret = SerializableCurve2D.writeSerializableCurve2D(out, sElement.serializableCurve2D);
			//sElement for PaintStyle
			out.writeObject(sElement.fillColor);
			out.writeObject(sElement.lineColor);
			out.writeFloat(sElement.lineWidth);
			out.writeUTF(sElement.dashedStyle);
			out.writeObject(sElement.dash);
			out.writeInt(sElement.arrowStyle);
			out.writeInt(sElement.startArrowType);
			out.writeInt(sElement.endArrowType);
			//sElement for TextBox only
			out.writeObject(sElement.textArea);
			SerializableAttributedString.writeSerializableAttributedString(out,
					sElement.attributedString);
			out.writeObject(sElement.textBoxInsets);
			out.writeInt(sElement.textAlign);
			out.writeInt(sElement.lineSpace);
			//sElement for ImageElement only
			out.writeObject(sElement.imageByteData);
			//sElement for GroupElement only
			out.writeObject(sElement.childrenList);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return;
	}

//--------------------------//
// read PageList
//--------------------------//
     public ArrayList readPageList(String filePath) throws Exception{
        ObjectInputStream in
                =new ObjectInputStream(new FileInputStream(filePath));
        ArrayList newPageList=new ArrayList();
        try{
            String version=in.readUTF();
            if(!version.equals(this.versions[1])&&
               !version.equals(this.versions[2])){
                String str="Cannot read the old draw file (version 0_0)";
                JOptionPane.showMessageDialog(ObjectTable.getDrawMain(), str, "",
                        JOptionPane.ERROR_MESSAGE);
                in.close();
                return newPageList;
            }
        } catch(Exception e){
            System.err.println("*** Error readOutputPageList e="+e);
            e.printStackTrace();
            in.close();
            return newPageList;
        }
        try{
            //String version=in.readUTF();
            int numpage=in.readInt();
            if(debug>0) System.out.println(" -- Read file total page="+numpage);
            for(int i=0;i<numpage;i++){
                ViewData viewData=ViewData.readViewData(in);
			  //-------------------------------------------------------//
                ArrayList containerList=this.readContainerList(i+1, in);
			  //-------------------------------------------------------//
                PageData pageData=
                        new PageData(containerList, viewData, new UndoDrawManager());
                newPageList.add(pageData);
            }
        } catch(Exception e){
            System.err.println("*** Error readOutputPageList e="+e);
            e.printStackTrace();
            in.close();
            return newPageList;
        }
        in.close();
        return newPageList;
    }

//++++----------------------//
//  read ContainerList      //
//--------------------------//
    public ArrayList readContainerList(int page, ObjectInputStream in) throws Exception{
        ArrayList serializableElementList=new ArrayList();
        ArrayList containerList=new ArrayList();
        try{
            String version=in.readUTF();
            int size=in.readInt();
            for(int i=0;i<size;i++){
			  //---------------------------------------------------------------//
                SerializableElement sElement=this.readSerializableElement(in);
			  //---------------------------------------------------------------//
                serializableElementList.add(sElement);
            }
        } catch(Exception e){
            System.out.println("*** Error readSerializableElementList e="+e);
            e.printStackTrace();
        }
    //ShapeId's number Dduplication check
		DupicatedTable dupTabel=new DupicatedTable(serializableElementList);
        if(dupTabel.isDuplicated()){
            String fileName=ObjectTable.getFileIo().getCurrentSimpleFileName();
            String message = "\n*** Warning: page-"+page+"  The shapeId numbers are Duplicated ! ***"
                    +"\n file Name="+fileName+"  => Recovered";
            //JOptionPane.showConfirmDialog(ObjectTable.getDrawMain(),message);
            System.err.println(message);
			System.out.println(message);
			String str = "";
			str += "\n*** Error in DrawFileIo shapeId numbers duplicated page="+page+"\n";
			str +=dupTabel.toString();
			System.err.println(str);
		// Recovery
			RenameTable table=new RenameTable(serializableElementList);
			table.exec();
			str="";
			str="\n** DrawFileIo.renumbering "+table.toString();
			System.err.println(str);
			printSerializableElementList("err","\n** readContainerList Print SerializableElementList after renumbering="+page,
                serializableElementList);
        }
      //--------------------------------------------------------------------//
        this.invertContainerList(containerList, serializableElementList);
      //--------------------------------------------------------------------//
        if(dupTabel.isDuplicated()) {
            printContainerList("err", "\n** readContainerList Print ContainerList after readContainerList page="+page, 
					containerList);
        }
        if(debug>0) {
            printContainerList("out", "\n** readContainerList Print ContainerList after readContainerList page="+page, 
					containerList);
        }

        return containerList;
    }
	
//++++ getSerializableElement ----
    private SerializableElement getSerializableElement(String shapeId, ArrayList sElementList){
        SerializableElement target=null;
        int size=sElementList.size();
        for(int i=0;i<size;i++) {
            SerializableElement element=(SerializableElement)sElementList.get(i);
			if(element.shapeId.equals(shapeId)){
                target=element;
                break;
            }
        }
        return target;
    }
	//++++ removeSerializableElement ----
	private int removeSerializableElement(String shapeId, ArrayList sElementList) {
		SerializableElement target = null;
		int size = sElementList.size();
		int pos=-1;
		for (int i = 0; i < size; i++) {
			SerializableElement element = (SerializableElement) sElementList.get(i);
			if (element.shapeId.equals(shapeId)) {
				pos=i;
				sElementList.remove(element);
				break;
			}
		}
		if(debug>0) System.out.println("removeSerializableElement shapeId="+shapeId+", pos="+pos);
		return pos;
	}

//++++ readSerializableElement ----
    public SerializableElement readSerializableElement(ObjectInputStream in)
            throws Exception{
        SerializableElement sElement=new SerializableElement();
        try{
            String version=in.readUTF();
          //sElement for container
            sElement.containerType=in.readInt();
            sElement.containerIndex=in.readInt();
            sElement.parent=in.readUTF();
            sElement.elementType=in.readUTF();
            sElement.shapeId=in.readUTF();
            sElement.date=(Date)in.readObject();
            sElement.fileNameAndPage=(String)in.readUTF();
            sElement.connectorTargetPermission=in.readBoolean();
            sElement.connectorPermission=in.readBoolean();
            if(version.equals(versions[1])) sElement.property=(HashMap)in.readObject();
            //sElement.inf=(HashMap)in.readObject();
          //sElement for shapeElement
            sElement.serializableCurve2D=SerializableCurve2D.readSerializableCurve2D(in);
          //sElement for PaintStyle
            sElement.fillColor=(Color)in.readObject();
            sElement.lineColor=(Color)in.readObject();
            sElement.lineWidth=in.readFloat();
            sElement.dashedStyle=in.readUTF();
            sElement.dash=(float[])in.readObject();
            sElement.arrowStyle=in.readInt();
            sElement.startArrowType=in.readInt();
            sElement.endArrowType=in.readInt();
          //sElement for TextBox only
            sElement.textArea=(Rectangle2D)in.readObject();

            sElement.attributedString=SerializableAttributedString.readSerializableAttributedString(in);

            sElement.textBoxInsets=(Insets)in.readObject();
            sElement.textAlign=in.readInt();
            sElement.lineSpace=in.readInt();
          //sElement for ImageElement only
            sElement.imageByteData=(byte[])in.readObject();
          //sElement for GroupElement only
            sElement.childrenList=(ArrayList)in.readObject();
        } catch(Exception e){
            System.err.println("*** Error readSerializableElement e="+e);
            e.printStackTrace();
        }
        return sElement;
    }
	
//++++ invertContainerList ----
    private void invertContainerList(ArrayList containerList, ArrayList serializableElementList)
            throws Exception{

        int size=serializableElementList.size();
        for(int i=0;i<size;i++){
            SerializableElement sElement=(SerializableElement)serializableElementList.get(i);
            String parent=sElement.parent;
            if(parent==null||parent.equals("")){
			  //--------------------------------------------------------------//
                ShapeContainer container=this.invertShapeContainer(sElement,
                    serializableElementList);
			  //--------------------------------------------------------------//
                containerList.add(container);
            }
        }
        if(debug>0) {
			System.out.println("\n** DrawFileIo invertContainerList before invert **");
			printSerializableElementList("out","Print SerializableElementList",
					serializableElementList);
			System.out.println("\n** DrawFileIo invertContainerList after invert **");
            //printSerializableElementList(" ** Print SerializableElementList before invert", serializableElementList);
            printContainerList("out","Print ContainerList ", containerList);
        }
        return;
    }

//++++ invertShapeContainer ----
    public ShapeContainer invertShapeContainer(SerializableElement sElement, 
			ArrayList serializableElementList){
		//++this.recursiveCall;
		if (debug > 0) {
			System.out.println("\n** DrawFileIo invertShapeContainer before invert"
					+", sElement="+sElement.shapeId+ " **");
			System.out.println("Print SerializableElement\n"+sElement.toShortString());
		}
        ShapeContainer container=new ShapeContainer();
		if (sElement.containerType == ShapeContainer.SHAPE) {
			//System.out.println(" - DrawFileIo invertShapeContainer single shape");
			//single ShapeContainer
			container=SerializableElementUtil.invertSingleContainer(sElement);
		} else {
			if (debug > 0) System.out.println("- DrawFileIo invertShapeContainer group");
			//Group ShapeContainer
			container = SerializableElementUtil.invertGroupContainer(sElement);
			GroupElement groupElement=(GroupElement)container.getElement();
			ArrayList childrenList = (ArrayList) sElement.childrenList.clone();
			for (int j = 0; j < childrenList.size(); j++) {
				String childShapeId = (String) childrenList.get(j);
				//-----------------------------------------------------------------------------------------------//
				SerializableElement childData 
						= this.getSerializableElement(childShapeId, serializableElementList);
				//-----------------------------------------------------------------------------------------------//
				if (debug >0) {
					System.out.println("--  DrawFileIo invertShapeContainer --");
					System.out.println(" - childData[="+j+"]" + childData.toShortString());
				}
				//--------------------------------------------------------------------//
				ShapeContainer childContainer
						= this.invertShapeContainer(childData, serializableElementList);
				//--------------------------------------------------------------------//
				if (childContainer != null) {
					groupElement.addChildren(childContainer);
					childContainer.setParent(container);
				}
			}
		}
		container.setSelected(false);
		if (debug > 0) {
			System.out.println("\n** DrawFileIo invertShapeContainer after invert"
					+ ", sElement=" + sElement.shapeId + " **");
			System.out.println("Print ShapeContainer\n" + container.toVeryShortString());
		}
		//--this.recursiveCall;
		return container;
	}
	
//++++ getPerfectSerializableElement ----
	public SerializableElement getPerfectSerializableElement(SerializableElement sElement,
			ArrayList serializableElementList) {
		++depth;
		if (debug > 0) {
			System.out.println("** getPerfectSerializableElement start depth=" + depth
					+ "\n - sElement=" + sElement.toVeryShortString()
					+ "\n--> getPerfectSerializableElement start end");
		}
		if (sElement.containerType == ShapeContainer.SHAPE) {
			return sElement;
		}
		// sElement is group
		if (debug > 0) {
			System.out.println("   -- sElement.childrenList.size()=" + sElement.childrenList.size());
		}
		String ObjectName = sElement.childrenList.get(0).getClass().getSimpleName();
		for (int i = 0; i < sElement.childrenList.size(); i++) {
			if (ObjectName.equals("String")) {
				String shapeId = (String) sElement.childrenList.get(i);
				SerializableElement childElement = this.getSerializableElement(shapeId, serializableElementList);
				if (debug > 0) {
					System.out.println("  - ObjectName=" + ObjectName
							+ ": childElement[" + i + "]=" + childElement.shapeId
							+ ", containerType=" + childElement.containerType
							+ ", parent=" + childElement.parent
							+ ", children=" + childElement.childrenList.size());
				}
				if (childElement.containerType == ShapeContainer.SHAPE) {
					sElement.childrenList.set(i, childElement);
					int remove = this.removeSerializableElement(shapeId, serializableElementList);
				} else {
					//sElement.childrenList.set(i, childElement);
					SerializableElement perfectChildElement
							= this.getPerfectSerializableElement(childElement, serializableElementList);
					sElement.childrenList.set(i, perfectChildElement);
					int remove = this.removeSerializableElement(shapeId, serializableElementList);
				}
			} else {
				SerializableElement childElement = (SerializableElement) sElement.childrenList.get(i);
				if (debug > 0) {
					System.out.println("  - ObjectName=" + ObjectName
							+ ": childElement[" + i + "]=" + childElement.shapeId
							+ ", parent=" + childElement.parent + ", children=" + childElement.childrenList.size());
				}
			}
		}
		if (debug > 0) {
			System.out.println("** getPerfectSerializableElement return depth=" + depth
					+ "\n - sElement=" + sElement.toVeryShortString()
					+ "\n--> getPerfectSerializableElement return end");
		}
		--depth;
		return sElement;
	}

	private void printContainerList(String out, String title, ArrayList containerList) {
		String str="";
		str+=title+"\n";
		for (int i = 0; i < containerList.size(); i++) {
			ShapeContainer container = (ShapeContainer) containerList.get(i);
			str+=" - Container[" + i + "]=" + container.toVeryShortString()+"\n";
			//System.out.println(" - Container[" + i + "]=" + container.toVeryShortString());
		}
		if(out.equals("out")) System.out.println(str);
		else if(out.equals("err")) System.err.println(str);
	}

	private void printSerializableElementList(String out, String title, ArrayList sElementList) {
		String str="";
		str+=title+"\n";
		for (int i = 0; i < sElementList.size(); i++) {
			SerializableElement sElement = (SerializableElement) sElementList.get(i);
			str+=" - SerializableElement[" + i + "]=" + sElement.toVeryShortString()+"\n";
			//System.out.println(" - SerializableElement[" + i + "]=" + sElement.toVeryShortString());
		}
		if(out.equals("out")) System.out.println(str);
		else if(out.equals("err")) System.err.println(str);
	}

	private void printPerfectSerializableElementList(String out, String title, ArrayList sElementList) {
		String str="";
		str+=title+"\n";
		for (int i = 0; i < sElementList.size(); i++) {
			SerializableElement sElement = (SerializableElement) sElementList.get(i);
			sElement=this.getPerfectSerializableElement(sElement, sElementList);
			str+=" - SerializableElement[" + i + "]=" + sElement.toVeryShortString()+"\n";
			//System.out.println(" - SerializableElement[" + i + "]=" + sElement.toVeryShortString());
		}
		if(out.equals("out")) System.out.println(str);
		else if(out.equals("err")) System.err.println(str);
	}
	
//**** inner class DupicatedTable ----
	class DupicatedTable{
		Vector InfoTable=new Vector();
		ArrayList serializableElementList;
	 
		DupicatedTable(ArrayList serializableElementList){
			this.serializableElementList=serializableElementList;
			int size = serializableElementList.size();
			int[] numbers = new int[size];
			String[] shapeIds = new String[size];
			for (int i = 0; i < size; i++) {
				SerializableElement sElement = (SerializableElement) serializableElementList.get(i);
				String shapeId = sElement.shapeId;
				shapeIds[i] = shapeId;
				int id0 = shapeId.indexOf("-");
				int id1 = shapeId.indexOf(")");
				String num = shapeId.substring(id0 + 1, id1);
				numbers[i] = (new Integer(num)).intValue();
			}
			for (int i = 1; i < size; i++) {
				for (int j = 0; j < i; j++) {
					if (numbers[j] == numbers[i]) {
						DuplicatedInfo info = new DuplicatedInfo(numbers[i], shapeIds[i], shapeIds[j]);
						InfoTable.add(info);
					}
				}
			}
		}
		
		boolean isDuplicated(){
			boolean dup=false;
			if(this.InfoTable.size()>0) dup=true;
			return dup;
		}
		public String toString(){
			String str="";
			int size=InfoTable.size();
			str+="DupicatedTable InfoTable size="+size;
			for (int i = 0; i < size; i++) {
				DuplicatedInfo info=(DuplicatedInfo)InfoTable.get(i);
				str+="\n- info number="+info.dupNumber
						+", shapeIds1="+info.shapeId1+", shapeIds2="+info.shapeId2;
			}
			return str;
		}
	}
	
//**** inner class DuplicatedInfo see=>readContainerList ++++
	class DuplicatedInfo {
		int dupNumber=-1;
		String shapeId1="";
		String shapeId2="";
		public DuplicatedInfo(int dupNumber, String shapeId1, String shapeId2){
			this.dupNumber=dupNumber;
			this.shapeId1=shapeId1;
			this.shapeId2=shapeId2;
		}
		public String toString(){
			String str="";
			str+="DuplicatedInfo number="+this.dupNumber
					+", shapeId1="+this.shapeId1+", shapeId2="+this.shapeId2;
			return str;
		}
	}
	
//**** inner class RenameTable see=>renumbering ++++
	class RenameTable {
		ArrayList ElementTable = new ArrayList();
		ArrayList serializableElementList;

		RenameTable(ArrayList serializableElementList){
			this.serializableElementList=serializableElementList;
		}
		void exec(){
			this.setElements();
			this.setChildrenIndex();
			this.initUsedFlag();
			this.setNewShapeId();
			this.setNewChildrenShapeId();
			this.setNewParentShapeId();
			this.setToSerializableElementList();


		}
		void setElements(){
			int size=this.serializableElementList.size();
			for (int i = 0; i < size; i++) {
				SerializableElement sElement = (SerializableElement) serializableElementList.get(i);
				Element element = new Element();
				element.shapeId = sElement.shapeId;
				element.parent = sElement.parent;
				if (sElement.containerType == ShapeContainer.GROUP) {
					element.group = true;
					ArrayList childrenList = (ArrayList) sElement.childrenList;
					int listSize = childrenList.size();
					element.childrenShapeIdList = new String[listSize];
					element.childrenNewShapeIdList = new String[listSize];
					element.childrenId = new int[listSize];
					for (int j = 0; j < listSize; j++) {
						element.childrenShapeIdList[j] = (String) sElement.childrenList.get(j);
						element.childrenNewShapeIdList[j] = "";
						element.childrenId[j] = -1;
					}
				}
				this.ElementTable.add(element);
			}
		}
		
		void setChildrenIndex() {
			int size = this.ElementTable.size();
			Element elm = null;
			for (int i = 0; i < size; i++) {
				Element element = (Element) this.ElementTable.get(i);
				//if (!element.group) {
				if (element.used || !element.group) {
					continue;
				}
				int num = element.childrenShapeIdList.length;
				if (num == 0) {
					continue;
				}
				element.childrenId = new int[num];
				for (int j = 0; j < num; j++) {
					String childName = (String) element.childrenShapeIdList[j];
					int[] indices = this.getElementIndex(childName, false);
					if (indices.length != 0) {
						element.childrenId[j] = indices[0];
						Element childElm = (Element) this.ElementTable.get(indices[0]);
						childElm.used = true;
					}
				}
			}
		}

		int[] getElementIndex(String shapeId, boolean newId) {
			int size = this.ElementTable.size();
			Vector vector = new Vector();
			Element elm = null;
			for (int i = 0; i < size; i++) {
				Element element = (Element) this.ElementTable.get(i);
				if (element.used) {
					continue;
				}
				if (newId) {
					if (element.newShapeId.equals(shapeId)) {
						vector.add(i);
					}
				} else if (element.shapeId.equals(shapeId)) {
					vector.add(i);
				}
			}
			size = vector.size();
			int[] indices = new int[size];
			for (int i = 0; i < size; i++) {
				Integer num = (Integer) vector.get(i);
				indices[i] = num.intValue();
			}
			return indices;
		}

		void initUsedFlag() {
			int size = this.ElementTable.size();
			Element elm = null;
			for (int i = 0; i < size; i++) {
				Element element = (Element) this.ElementTable.get(i);
				element.used= false;
			}
		}

		void setNewShapeId() {
			int size = this.ElementTable.size();
			Element elm = null;
			for (int i = 0; i < size; i++) {
				Element element = (Element) this.ElementTable.get(i);
				String shapeId = element.shapeId ;
				String newShapeId = element.changeShapeIdNumber(shapeId, i);
				element.newShapeId = newShapeId;
				//if(debug>0)System.err.println(" -  i="+i+ ", shapeId="+shapeId+", newShapeId="+newShapeId);
			}

		}

		private void setNewChildrenShapeId() {
			int size = this.ElementTable.size();
			Element elm = null;
			for (int i = 0; i < size; i++) {
				Element element = (Element) this.ElementTable.get(i);
				if (!element.group) {
				//if (!element.access || !element.group) {
					continue;
				}

				int num = element.childrenShapeIdList.length;
				if (num == 0) {
					continue;
				}
				for (int j = 0; j < num; j++) {
					Element childElm = (Element) this.ElementTable.get(element.childrenId[j]);
					element.childrenNewShapeIdList[j] = childElm.newShapeId;
				}
			}
		}

		private void setNewParentShapeId() {
			int size = this.ElementTable.size();
			Element elm = null;
			for (int i = 0; i < size; i++) {
				Element element = (Element) this.ElementTable.get(i);
				if (element.parent.equals("")) {
				//if (!element.access || element.parent.equals("")) {
					continue;
				}
				Element[] parentElms = this.getElements(element.parent);
				if (parentElms.length == 0) {
					continue;
				}
				element.newParent = parentElms[0].newShapeId;
			}
		}
		
		Element[] getElements(String shapeId) {
			int size = this.ElementTable.size();
			Vector vector = new Vector();
			Element elm = null;
			for (int i = 0; i < size; i++) {
				Element element = (Element) this.ElementTable.get(i);
				if (element.shapeId .equals(shapeId)) {
					vector.add(element);
				}
			}
			size = vector.size();
			Element[] elms = new Element[size];
			for (int i = 0; i < size; i++) {
				elms[i] = (Element) vector.get(i);
			}
			return elms;
		}

		void setToSerializableElementList() {
			int size=this.serializableElementList.size();
			for (int i = 0; i < size; i++) {
				SerializableElement sElement = (SerializableElement)this.serializableElementList.get(i);
				Element element = (Element)this.ElementTable.get(i);
				sElement.shapeId = element.newShapeId;
				sElement.parent = element.newParent;
				if (sElement.containerType == ShapeContainer.GROUP) {
					ArrayList childrenList = (ArrayList) sElement.childrenList;
					int listSize = childrenList.size();
					for (int j = 0; j < listSize; j++) {
						sElement.childrenList.set(j, element.childrenNewShapeIdList[j]);
					}
				}
			}
		}
		
		public String toString() {
			int size = this.ElementTable.size();
			String str = "";
			if (size == 0) {
				str = "RenameTable is empty";
				return str;
			}
			str = "RenameTable size=" + size + "\n";
			for (int i = 0; i < size; i++) {
				Element element = (Element) this.ElementTable.get(i);
				str += " - element[" + i + "]  " + element.toString() + "\n";
			}
			return str;
		}

	}

//**** inner class Element ++++
	class Element {
		String shapeId = "";
		String newShapeId = "";
		boolean group = false;
		boolean used = false;
		String parent = "";
		String newParent = "";
		String[] childrenShapeIdList = new String[0];
		String[] childrenNewShapeIdList = new String[0];
		int[] childrenId = new int[0];

		public String changeShapeIdNumber(String shapeId, int number) {
			String newShapeId = "";
			int id = shapeId.indexOf("(");
			newShapeId = shapeId.substring(0, id);
			newShapeId+= "(No-" + number + ")";
			//System.err.println(" - Element shapeId="+shapeId+", newShapeId="+newShapeId);
			return newShapeId;
		}

		public String toString() {
			String str = "";
			str += "shapeId=" + this.shapeId  + ", newShapeId=" + this.newShapeId;
			if(this.group) str+=", group";
			if(this.parent!=null&&!this.parent.equals("")) str += ", parent=" + this.parent;
			if(this.newParent!=null&&!this.newParent.equals("")) str += ", newParent=" + this.newParent;
			int size = this.childrenShapeIdList.length;
			if (size == 0) return str;
			else{
				str += "\n";
				for (int i = 0; i < size; i++) {
					String childName = childrenShapeIdList[i];
					str += "    child[" + i + "]: shapeId=" + childName + ", id=" + childrenId[i] + ", newShapeId=" + childrenNewShapeIdList[i];
					if(i<size-1) str+="\n";
				}
			}
			return str;
		}
	}
}
