/*******************************************************************************
 * Copyright (c) 2003, 2005 IBM Corporation and others.
 * 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:
 * IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.j2ee.internal.web.operations;



import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;


/**
 * This class stores the relationship between two files. In particular, this is an inLink and the
 * files which reference it.
 */
public class RelationData {
	public class Link implements Cloneable {

		private String url;
		private int occurrences = 0;

		public Link(String newUrl, int occ) {
			url = newUrl;
			occurrences = occ;
		}

		/**
		 * Returns an exact copy of this object.
		 * 
		 * @return Created clone object
		 */
		public Object clone() {
			return new Link(url, occurrences);
		}

		/**
		 * Returns the url of the file that references this inLink
		 * 
		 * @return String
		 */
		public String getURL() {
			return url;
		}

		/**
		 * Returns the number of times this file references the inLink
		 * 
		 * @return int
		 */
		public int getOccurrences() {
			return occurrences;
		}

		private int addOccurrence(int add) {
			occurrences = occurrences + add;
			return occurrences;
		}

		public String toString() {
			return url;
		}
	}

	// our relationship table. Key is a string which is the path of the inLink,
	// value is a vector of files that reference the inLink.
	protected Hashtable inLinksTable = null;
	protected Hashtable anchorsTable = null;
	private static final int INIT_HASH_TABLE_SIZE = 100;
	private static final int INIT_ANCHORS_HASH_TABLE_SIZE = 10;
	private boolean fileOk = false;
	private static final String LINK_STATE_FILE_NAME = "link_table_states.txt";//$NON-NLS-1$
	private static final String LINK_SERVERCONTEXTROOT_FILE_NAME = "link_scr_states.txt";//$NON-NLS-1$
	public static final String LINK_MISSING_FILE = "-";//$NON-NLS-1$
	public static final String LINK_INDEX_SEPARATOR = "+";//$NON-NLS-1$
	public static final String ANCHOR_INDEX_SEPARATOR = "#";//$NON-NLS-1$
	public static final String LINK_OCCURENCE_SEPARATOR = "/";//$NON-NLS-1$
	public static final String ANCHOR_SEPARATOR = "#### ANCHORS ####";//$NON-NLS-1$

	/**
	 * RelationData constructor comment.
	 */
	public RelationData() {
		super();
		inLinksTable = new Hashtable(INIT_HASH_TABLE_SIZE);
		anchorsTable = new Hashtable(INIT_ANCHORS_HASH_TABLE_SIZE);
	}

	public Link addInLink(String file_path, String parent_path, int occurence) {
		Vector in_links = (Vector) inLinksTable.get(file_path);
		if (in_links == null) {
			return null;
		}
		for (int i = 0; i < in_links.size(); i++) {
			Link inlnk = (Link) in_links.elementAt(i);
			String url = inlnk.getURL();

			//
			// Increment the occurence and return
			//

			if (url.compareTo(parent_path) == 0) {
				inlnk.addOccurrence(occurence);
				return inlnk;
			}
		}

		//
		// The link does not exist, need to add an entry in the table for it
		//

		Link inlnk = new Link(parent_path, occurence);
		in_links.addElement(inlnk);
		return inlnk;
	}

	public void changeInLink(String filePath, boolean missing) {

		if (missing) {
			Vector inlinks = (Vector) inLinksTable.remove(filePath);
			inLinksTable.put(LINK_MISSING_FILE + filePath, inlinks);
		} else {
			Vector inlinks = (Vector) inLinksTable.remove(LINK_MISSING_FILE + filePath);
			inLinksTable.put(filePath, inlinks);
		}
	}


	/*
	 * returns which projects depend on this file i.e. any projects that are in this file's list of
	 * in_links
	 */
	public Collection getDependentProjects(String file_path) {
		Hashtable outProjects = new Hashtable();
		Vector in_links = (Vector) inLinksTable.get(file_path);

		if (in_links != null) {
			for (int i = 0; i < in_links.size(); i++) {
				Link inlnk = (Link) in_links.elementAt(i);
				String url = inlnk.getURL();
				// should be in the form of: /ProjName/....
				if (url.length() > 0) {
					// key could be the filename or the missing filename ("-" + filename)
					// take this into account and offset the index accordingly
					int index = 0;
					int offset = 1;
					if (url.charAt(0) == '-') {
						index = url.indexOf(IPath.SEPARATOR, 2);
						offset = 2;
					} else {
						index = url.indexOf(IPath.SEPARATOR, 1);
						offset = 1;
					}
					if (index != -1) {
						String projName = url.substring(offset, index);
						outProjects.put(projName, projName);
					}
				}
			}
		}
		return outProjects.values();
	}

	/*
	 * returns which cross-project files depend on this file i.e. any projects that are in this
	 * file's list of in_links
	 */
	public Collection getDependentProjectFiles(String projName) {
		Hashtable outProjects = new Hashtable();

		for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
			String path = (String) aenum.nextElement();
			// should be in the form of: /ProjName/....
			if (path.length() > 0) {
				// if path is a missing filename ("-" + filename) then it means that it had
				// to come from this project (that is, the external nonexistent file could not have
				// linked to this project). So, we will not add this path. Also, since it is marked
				// broken, it probably won't exist to do anything with it anyway.
				if (path.charAt(0) != '-') {
					int index = path.indexOf(IPath.SEPARATOR, 1);
					if (index != -1) {
						String currentProjName = path.substring(1, index);
						if (!currentProjName.equals(projName)) {
							outProjects.put(path, path);
						}
					}
				}
			}
		}
		return outProjects.values();
	}



	public void createInLinkEntry(String file_path, String parent_path, int occurence) {

		Vector in_links = new Vector();
		Link inlnk = new Link(parent_path, occurence);
		in_links.addElement(inlnk);
		inLinksTable.put(file_path, in_links);
	}



	public void dump() {
		if (false) {
			if (inLinksTable != null) {
				for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
					StringBuffer St = new StringBuffer();
					String key = (String) aenum.nextElement();
					St.append("\nKey=" + key + "\n");//$NON-NLS-1$//$NON-NLS-2$
					Vector in_links = (Vector) inLinksTable.get(key);
					int nb_of_links = in_links.size();

					// Replace the string by index
					// Add a '+'separator only for more than one links to save space
					//


					for (int i = 0; i < nb_of_links; i++) {
						Link lnk = (Link) in_links.elementAt(i);
						St.append("\tValue=" + lnk.getURL() + "[" + lnk.getOccurrences() + "]");//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
					}
					org.eclipse.jem.util.logger.proxy.Logger.getLogger().logInfo(St.toString());
				}
			}
		}
	}

	public void dump(boolean dump) {
		if (dump) {
			if (inLinksTable != null) {
				for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
					StringBuffer St = new StringBuffer();
					String key = (String) aenum.nextElement();
					St.append("\nKey=" + key + "\n");//$NON-NLS-1$//$NON-NLS-2$
					Vector in_links = (Vector) inLinksTable.get(key);
					int nb_of_links = in_links.size();

					// Replace the string by index
					// Add a '+'separator only for more than one links to save space
					//


					for (int i = 0; i < nb_of_links; i++) {
						Link lnk = (Link) in_links.elementAt(i);
						St.append("\tValue=" + lnk.getURL() + "[" + lnk.getOccurrences() + "]");//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
					}
					org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(St.toString());
				}
			}
		}
	}

	/**
	 * used for LinksBuilder debugging
	 */
	public void dump2() {
		if (inLinksTable != null) {
			for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
				StringBuffer St = new StringBuffer();
				String key = (String) aenum.nextElement();

				Vector in_links = (Vector) inLinksTable.get(key);
				int nb_of_links = in_links.size();
				St.append("\nKey=" + key + " -- num:" + nb_of_links + "\n");//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
				// Replace the string by index
				// Add a '+'separator only for more than one links to save space
				//


				for (int i = 0; i < nb_of_links; i++) {
					Link lnk = (Link) in_links.elementAt(i);
					St.append("\tValue=" + lnk.getURL() + "[" + lnk.getOccurrences() + "]");//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
				}
				System.out.println(St.toString());
			}
		}
		System.out.println("************************************************\n\n\n\n************************************\n"); //$NON-NLS-1$
	}


	public Vector getInLinks(String filePath) {
		return (Vector) inLinksTable.get(filePath);
	}

	public void getInLinks(String filePath, Vector vectInLinks) {

		if (inLinksTable != null) {
			dump();
			Vector in_links = (Vector) inLinksTable.get(filePath);
			if (in_links != null) {
				for (int i = 0; i < in_links.size(); i++) {
					Link inlnk = (Link) ((Link) in_links.elementAt(i)).clone();
					vectInLinks.addElement(inlnk);
				}
			}
		}
	}

	public Hashtable getAnchorsTable() {
		return anchorsTable;
	}

	/**
	 * Returns the file used to store ServerContextRoot for the project.
	 */
	public static File getPreviousSCRFile(IProject project) {
		return new Path(J2EEPlugin.getDefault().getStateLocation().toString() + File.separator + project.getName() + File.separator + LINK_SERVERCONTEXTROOT_FILE_NAME).toFile();
	}

	/**
	 * Returns the file used to store the state of the link relations for the project.
	 * 
	 * @return java.io.File The state file
	 * @param project
	 *            org.eclipse.core.resources.IProject The project to get the state file for.
	 */
	private File getStateFile(IProject project) {
		return new Path(J2EEPlugin.getDefault().getStateLocation().toString() + File.separator + project.getName() + File.separator + LINK_STATE_FILE_NAME).toFile();
	}

	public boolean hasInLinkEntry(String path) {
		return inLinksTable.containsKey(path);
	}

	/**
	 * Run through all missing-file (-) RD entries to see if any of them closely match the path to
	 * this class. Return all of the matches.
	 */
	public Vector getPossibleMissingEndingMatches(IPath classPath) {
		Vector v = new Vector();

		String match = classPath.lastSegment();
		match = match.substring(0, match.length() - 6); // length minus ".class"

		String classPathStr = classPath.toString();
		String matchingClassPath = classPathStr.toString().substring(0, classPathStr.length() - 6);

		for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
			String path = (String) aenum.nextElement();
			// check if path ends with the class name that has been added/removed
			if (path.startsWith(LINK_MISSING_FILE) && path.endsWith(match)) {
				// OK: simple match found; now let's match with finer granularity.
				// Take path and put it into a form where we can check if it is a
				// close match to the class that has changed:
				// /Proj/Web Content/com.acme.Foo --> com/acme/Foo
				String linkPath;
				int index = path.lastIndexOf(IPath.SEPARATOR);
				if (index != -1 && index < path.length() - 1) {
					linkPath = path.substring(index + 1);
				} else {
					linkPath = path;
				}
				String closeMatch = linkPath.replace('.', IPath.SEPARATOR);

				if (matchingClassPath.endsWith(closeMatch)) {
					Vector in_links = (Vector) inLinksTable.get(path);
					String nonMissingPath = path.substring(1, path.length());
					changeInLink(nonMissingPath, false);
					if (in_links != null) {
						for (int i = 0; i < in_links.size(); i++) {
							Link inlnk = (Link) in_links.elementAt(i);
							String url = inlnk.getURL();
							v.add(url);
						}
					}
				}
			}
		}
		return v;
	}


	/**
	 * Run through all existing RD entries to see if any of them closely match the path to this
	 * class. Return all of the matches.
	 */
	public Vector getPossibleExistingEndingMatches(IPath classPath) {
		Vector v = new Vector();

		String match = classPath.lastSegment();
		match = match.substring(0, match.length() - 6); // length minus ".class"

		String classPathStr = classPath.toString();
		String matchingClassPath = classPathStr.toString().substring(0, classPathStr.length() - 6);

		for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
			String path = (String) aenum.nextElement();
			// check if path ends with the class name that has been added/removed
			if (path.endsWith(match) && !path.startsWith(LINK_MISSING_FILE)) {
				// OK: simple match found; now let's match with finer granularity.
				// Take path and put it into a form where we can check if it is a
				// close match to the class that has changed:
				// /Proj/Web Content/com.acme.Foo --> com/acme/Foo
				String linkPath;
				int index = path.lastIndexOf(IPath.SEPARATOR);
				if (index != -1 && index < path.length() - 1) {
					linkPath = path.substring(index + 1);
				} else {
					linkPath = path;
				}
				String closeMatch = linkPath.replace('.', IPath.SEPARATOR);

				if (matchingClassPath.endsWith(closeMatch)) {
					Vector in_links = (Vector) inLinksTable.get(path);
					changeInLink(path, true);
					if (in_links != null) {
						for (int i = 0; i < in_links.size(); i++) {
							Link inlnk = (Link) in_links.elementAt(i);
							String url = inlnk.getURL();
							v.add(url);
						}
					}
				}
			}
		}
		return v;
	}

	/**
	 * Run through all existing RD entries to see if any of them closely match the path to this
	 * class. Remove the inlinks for all the matches.
	 */
	public void removeInLinksPossibleExistingEndingMatches(IPath classPath) {
		String match = classPath.lastSegment();
		match = match.substring(0, match.length() - 6); // length minus ".class"

		String classPathStr = classPath.toString();
		String matchingClassPath = classPathStr.toString().substring(0, classPathStr.length() - 6);

		for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
			String path = (String) aenum.nextElement();
			if (path.endsWith(match) && !path.startsWith(LINK_MISSING_FILE)) {
				// OK: simple match found; now let's match with finer granularity.
				// Take path and put it into a form where we can check if it is a
				// close match to the class that has changed:
				// /Proj/Web Content/com.acme.Foo --> com/acme/Foo
				String linkPath;
				int index = path.lastIndexOf(IPath.SEPARATOR);
				if (index != -1 && index < path.length() - 1) {
					linkPath = path.substring(index + 1);
				} else {
					linkPath = path;
				}
				String closeMatch = linkPath.replace('.', IPath.SEPARATOR);

				if (matchingClassPath.endsWith(closeMatch)) {
					removeInLinks(path);
				}
			}
		}
	}

	/**
	 * Initialize links tables
	 */
	public void initialize() {
		inLinksTable = new Hashtable(INIT_HASH_TABLE_SIZE);
		anchorsTable = new Hashtable(INIT_ANCHORS_HASH_TABLE_SIZE);

	}

	/**
	 * Initialize links tables
	 */
	public void initializeAnchors() {
		anchorsTable = new Hashtable(INIT_ANCHORS_HASH_TABLE_SIZE);
	}

	/**
	 * Initialize links tables
	 */
	public void initializeInLinks() {
		inLinksTable = new Hashtable(INIT_HASH_TABLE_SIZE);
	}

	/**
	 * Return true if the file to restore data from existed and was successfully read.
	 * 
	 * @return boolean
	 */
	public boolean isFileOk() {
		return fileOk;
	}

	public boolean isInitialized() {
		return (inLinksTable != null);
	}

	public void newInLinkEntry(String path) {
		if (!inLinksTable.containsKey(path))
			inLinksTable.put(path, new Vector());
	}

	public void removeInLinks(String file_path) {

		//
		// Iterate through the fLinksTable to remove all in-links references
		// for file_path
		//

		for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
			String key = (String) aenum.nextElement();
			Vector in_links = (Vector) inLinksTable.get(key);

			for (int i = 0; i < in_links.size(); i++) {

				Link inlnk = (Link) in_links.elementAt(i);
				String url = inlnk.getURL();

				if (url.compareTo(file_path) == 0) {
					in_links.removeElementAt(i);
					break;
				}

				//
				// Remove the entry in the fLinksTable if the in-link
				// of the file is not in the workbench and an orphan link
				// otherwise update the in-links fLinksTable
				//
			}

			if (in_links.isEmpty() && key.startsWith(LINK_MISSING_FILE)) {
				inLinksTable.remove(key);
			}
		}
	}

	/**
	 * Iterate through the fLinksTable to return all out-links references for file_path
	 * 
	 * @param file_path
	 * @return
	 */
	public List getOutLinks(String file_path) {
		ArrayList list = new ArrayList();
		for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
			String key = (String) aenum.nextElement();
			Vector in_links = (Vector) inLinksTable.get(key);

			for (int i = 0; i < in_links.size(); i++) {

				Link inlnk = (Link) in_links.elementAt(i);
				String url = inlnk.getURL();

				if (url.compareTo(file_path) == 0) {
					list.add(key);
					break;
				}
			}
		}

		return list;
	}


	/**
	 * return whether other resources link to this file or not
	 */
	public boolean referencedByOtherLinks(String file_path) {

		//
		// Iterate through the fLinksTable to remove all in-links references
		// for file_path
		//
		boolean referenced = false;
		for (Enumeration aenum = inLinksTable.keys(); !referenced && aenum.hasMoreElements();) {
			String key = (String) aenum.nextElement();
			Vector in_links = (Vector) inLinksTable.get(key);

			for (int i = 0; i < in_links.size(); i++) {
				Link inlnk = (Link) in_links.elementAt(i);
				String url = inlnk.getURL();

				if (url.compareTo(file_path) == 0) {
					referenced = true;
					break;
				}
			}
		}
		return referenced;
	}


	/*
	 * performs as removeInLinks( String ) ... But for performance reasons, this also additionally
	 * returns a list of all the projects that this file is dependent upon. This is useful to get
	 * this information, and then go to all of those projects' relation data and tell them to
	 * removeInLinks for this file.
	 */
	public Collection removeInLinksForProjects(String file_path) {

		//
		// Iterate through the fLinksTable to remove all in-links references
		// for file_path
		//
		Hashtable projects = new Hashtable();
		for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
			String key = (String) aenum.nextElement();
			Vector in_links = (Vector) inLinksTable.get(key);

			for (int i = 0; i < in_links.size(); i++) {

				Link inlnk = (Link) in_links.elementAt(i);
				String url = inlnk.getURL();

				if (url.compareTo(file_path) == 0) {
					// should be in the form of: /ProjName/....
					if (key.length() > 0) {
						// key could be the filename or the missing filename ("-" + filename)
						// take this into account and offset the index accordingly
						int index = 0;
						int offset = 1;
						if (key.charAt(0) == '-') {
							index = key.indexOf(IPath.SEPARATOR, 2);
							offset = 2;
						} else {
							index = key.indexOf(IPath.SEPARATOR, 1);
							offset = 1;
						}
						if (index != -1) {
							String projName = key.substring(offset, index);
							projects.put(projName, projName);
						}
					}
					in_links.removeElementAt(i);
					break;
				}

				//
				// Remove the entry in the fLinksTable if the in-link
				// of the file is not in the workbench and an orphan link
				// otherwise update the in-links fLinksTable
				//
			}

			if (in_links.isEmpty() && key.startsWith(LINK_MISSING_FILE))
				inLinksTable.remove(key);
		}

		return projects.values();
	}



	/**
	 * performs as removeInLinks( String ) ... But for performance reasons, it additionally returns
	 * which projects depend on this file. i.e. any projects that are in this file's list of
	 * in_links
	 */
	public Collection removeInLinksAndGetDependentProjects(String file_path) {
		//
		// Iterate through the fLinksTable to remove all in-links references
		// for file_path
		//
		Hashtable projects = new Hashtable();
		for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
			String key = (String) aenum.nextElement();
			Vector in_links = (Vector) inLinksTable.get(key);

			if (key.equals(RelationData.LINK_MISSING_FILE + file_path)) {
				int index = -1;
				for (int i = 0; i < in_links.size(); i++) {
					Link inlnk = (Link) in_links.elementAt(i);
					String url = inlnk.getURL();

					if (url.compareTo(file_path) == 0) {
						index = i;
					}
					if (url.length() > 1) {
						int projindex = url.indexOf(IPath.SEPARATOR, 1);
						if (projindex != -1) {
							String projName = url.substring(1, projindex);
							projects.put(projName, projName);
						}
					}
				}
				if (index != -1) {
					in_links.removeElementAt(index);
				}

			} else {
				for (int i = 0; i < in_links.size(); i++) {

					Link inlnk = (Link) in_links.elementAt(i);
					String url = inlnk.getURL();

					if (url.compareTo(file_path) == 0) {

						in_links.removeElementAt(i);
						break;
					}

					//
					// Remove the entry in the fLinksTable if the in-link
					// of the file is not in the workbench and an orphan link
					// otherwise update the in-links fLinksTable
					//
				}
			}

			if (in_links.isEmpty() && key.startsWith(LINK_MISSING_FILE)) {
				inLinksTable.remove(key);
			}
		}
		return projects.values();
	}


	/**
	 * remove all references to a specific inLink. When removeOrphan is true the inLink entry is
	 * removed as well, when there are no more refereces to it
	 */
	public void removeInLinks(String inLinkEntry, String inLinkReference, boolean removeOrphan) {

		String key = inLinkEntry;
		Vector in_links = (Vector) inLinksTable.get(key);

		for (int i = 0; i < in_links.size(); i++) {

			Link inlnk = (Link) in_links.elementAt(i);
			String url = inlnk.getURL();

			if (url.compareTo(inLinkReference) == 0) {
				in_links.removeElementAt(i);
				break;
			}
		}

		// If there are no more references to the inLinkEntry
		// and the caller wants this orphan deleted then
		// remove the key from the table
		if (in_links.isEmpty() && removeOrphan)
			inLinksTable.remove(key);

	}

	/**
	 * Restores this builder's saved state and returns whether it was successful in doing so.
	 */
	public boolean restore(IProject project) {
		if (project != null) {
			// get the state
			File stateFile = getStateFile(project);
			if (stateFile.exists()) {
				inLinksTable = new Hashtable(INIT_HASH_TABLE_SIZE);

				// read inLinksTable from stateFile
				Vector keys = new Vector();
				Vector indices = new Vector();
				BufferedReader reader = null;
				try {
					reader = new BufferedReader(new FileReader(stateFile));

					String line = null;
					//				while( ((line = reader.readLine()) != null) && !line.startsWith(
					// ANCHOR_SEPARATOR ) )
					while ((line = reader.readLine()) != null) {
						String buffer = line;


						// to take into account the possibility of links spanning multiple lines,
						// keep reading until we find a line that starts with an idicator
						// that the link is finished (a line beginning w/ LINK_INDEX_SEPARATOR)
						line = reader.readLine();
						while (line != null && !line.startsWith(LINK_INDEX_SEPARATOR)) {
							buffer = buffer + line;
							line = reader.readLine();
						}
						// add link string (/MyProj/file.html)
						if (buffer != null) {
							keys.addElement(buffer);
						}
						// add references line (+2/3...)
						if (line != null) {
							indices.addElement(line);
						} else {
							System.out.println(ProjectSupportResourceHandler.Syntax_Error_in_the_links_UI_); //$NON-NLS-1$ = "Syntax Error in the links state file"
							return false;
						}
					}

					// Use this to load anchor information
					//				// Now let's add all of the extra anchor information
					//				if ( line != null && line.startsWith( ANCHOR_SEPARATOR ) ) {
					//					while( (line = reader.readLine()) != null )
					//					{
					//						String buffer = line;
					//	
					//						// to take into account the possibility of links spanning multiple lines,
					//						// keep reading until we find a line that starts with an idicator
					//						// that the link is finished (a line beginning w/ LINK_INDEX_SEPARATOR)
					//						line = reader.readLine();
					//						while ( line != null && !line.startsWith( ANCHOR_INDEX_SEPARATOR ) ) {
					//							buffer = buffer + line;
					//							line = reader.readLine();
					//						}
					//
					//						// add file and all of its anchors
					//						if ( buffer != null && line != null)
					//						{
					//							anchorsTable.put( buffer, line );
					//						}
					//						else
					//						{
					//							System.out.println(ResourceHandler.getString("Syntax_Error_in_the_links_UI_"));
					// //$NON-NLS-1$ = "Syntax Error in the links state file"
					//							return false;
					//						}
					//					}
					//		
					//				}
				} catch (FileNotFoundException fe) {
					org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(fe);
				} catch (IOException ie) {
					org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(ie);
				} finally {
					if (reader != null) {
						try {
							reader.close();
						} catch (IOException ie2) {
							org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(ie2);
						}
					}
				}


				//
				// Populate the hash inLinksTable with keys (file paths) and values (in links files
				// paths)
				//
				fileOk = true;
				for (int i = 0; i < keys.size(); i++) {
					try {
						String key = (String) keys.elementAt(i);
						String compacted_indices = (String) indices.elementAt(i);

						//
						// Parse the in-links indexes
						//

						int size = keys.size();
						Vector in_links = new Vector();
						if (compacted_indices != LINK_INDEX_SEPARATOR) {

							// Extract indexes and occurences

							StringTokenizer st_idx_occ = new StringTokenizer(new String(compacted_indices), LINK_INDEX_SEPARATOR);
							while (st_idx_occ.hasMoreTokens()) {
								String idx_occ = new String(st_idx_occ.nextToken());
								int pos_occ = idx_occ.indexOf(LINK_OCCURENCE_SEPARATOR);
								int index;
								int occurence = 1;
								if (pos_occ == -1) {
									index = Integer.valueOf(idx_occ).intValue();
								} else {
									index = Integer.valueOf(idx_occ.substring(0, pos_occ)).intValue();
									occurence = Integer.valueOf(idx_occ.substring(pos_occ + 1)).intValue();
								}
								if (index >= 0 && index < size) {
									Link inlnk = new Link((String) keys.elementAt(index), occurence);
									in_links.addElement(inlnk);
								}
							}
						}
						inLinksTable.put(key, in_links);
					} catch (Exception e) {
						fileOk = false;
					}
				}

				return fileOk;
			}
			return false;

		}

		return false;
	}

	/**
	 * Saves this builder's state to disk so that it can be restarted in the same state later.
	 */
	public void save(IProject project) {

		File stateFile = getStateFile(project);
		if (inLinksTable == null) {
			stateFile.delete();
		} else {

			// Prepare the index vector

			Vector index_vector = new Vector(inLinksTable.size());
			for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
				index_vector.addElement(aenum.nextElement());
			}

			// write inLinksTable to stateFile

			try {
				File parentFolder = stateFile.getParentFile();
				if (!parentFolder.exists()) {
					parentFolder.mkdirs();
				}
				PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(stateFile)));
				for (Enumeration aenum = inLinksTable.keys(); aenum.hasMoreElements();) {
					String key = (String) aenum.nextElement();
					out.print(key);
					out.println();
					out.print(LINK_INDEX_SEPARATOR);
					Vector in_links = (Vector) inLinksTable.get(key);
					int nb_of_links = in_links.size();

					// Replace the string by index
					// Add a '+'separator only for more than one links to save space
					// Add '/<occurence>' only if occurence > 1 to save space
					//

					Link lnk = null;
					int nb_lnks = 0;
					if (nb_of_links > 0) {
						lnk = (Link) in_links.elementAt(0);
						out.print(index_vector.indexOf(lnk.getURL()));
						nb_lnks = lnk.getOccurrences();
						if (nb_lnks > 1) {
							out.print(LINK_OCCURENCE_SEPARATOR);
							out.print(nb_lnks);
						}
						for (int i = 1; i < nb_of_links; i++) {
							out.print(LINK_INDEX_SEPARATOR);
							lnk = (Link) in_links.elementAt(i);
							out.print(index_vector.indexOf(lnk.getURL()));
							nb_lnks = lnk.getOccurrences();
							if (nb_lnks > 1) {
								out.print(LINK_OCCURENCE_SEPARATOR);
								out.print(nb_lnks);
							}
						}
					}
					out.println();
				}
				/*
				 * use this to save out anchor information //
				 * ############################################ if ( !anchorsTable.isEmpty() ) {
				 * out.println( ANCHOR_SEPARATOR ); } for (Enumeration enum = anchorsTable.keys();
				 * enum.hasMoreElements();) { String key = (String) enum.nextElement();
				 * out.print(key); out.println(); //out.print(ANCHOR_INDEX_SEPARATOR); out.println(
				 * anchorsTable.get(key) ); }
				 */

				out.flush();
				out.close();
			} catch (IOException e) {
				org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(ProjectSupportResourceHandler.Error_while_saving_links_s_EXC_); //$NON-NLS-1$ = "Error while saving links state file"
			}
		}
	}

	/**
	 * Insert the method's description here. Creation date: (3/21/2001 1:45:58 PM)
	 * 
	 * @param newFileOk
	 *            boolean
	 */
	void setFileOk(boolean newFileOk) {
		fileOk = newFileOk;
	}
}
