/*******************************************************************************
 * Copyright (c) 2005, 2010 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
 *     bug:244839 - eugene@genuitec.com
 *******************************************************************************/
package org.eclipse.wst.jsdt.internal.core;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.wst.jsdt.core.IAccessRule;
import org.eclipse.wst.jsdt.core.IIncludePathAttribute;
import org.eclipse.wst.jsdt.core.IIncludePathEntry;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
import org.eclipse.wst.jsdt.core.JSDScopeUtil;
import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer;
import org.eclipse.wst.jsdt.core.WorkingCopyOwner;
import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchScope;
import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
import org.eclipse.wst.jsdt.internal.core.search.IRestrictedAccessBindingRequestor;
import org.eclipse.wst.jsdt.internal.core.search.JavaSearchScope;


public class DocumentContextFragmentRoot extends PackageFragmentRoot{

	/*
	 * if user includes dojo.js check if dojo.js.uncompressed.js exists instead and replace with that.
	 */
	public static final boolean HACK_DOJO= true;
	private final String UNCOMPRESSED_DOJO="dojo.js.uncompressed.js"; //$NON-NLS-1$
	private final  String DOJO_COMPRESSED = "dojo.js"; //$NON-NLS-1$
	//private static final ClasspathAttribute HIDE = new ClasspathAttribute("hide","true"); //$NON-NLS-1$ //$NON-NLS-2$
	private String[] includedFiles;
	//private Long[] timeStamps;
	private IFile fRelativeFile;
	private IResource absolutePath;
	private IPath webContext;
	private IIncludePathEntry rawClassPathEntry;

	//public static final boolean RETURN_CU = true;
	private static final boolean DEBUG = false;
	//private boolean dirty;

	private static int instances=0;
	private IJavaScriptUnit[] workingCopies;
	private String[] fSystemFiles;
	private RestrictedDocumentBinding importPolice;

	class RestrictedDocumentBinding implements IRestrictedAccessBindingRequestor {

		private ArrayList foundPaths=new ArrayList();
		private String exclude;
		private boolean shown;

		public void reset() {
			foundPaths.clear();
			shown=false;
		}

		public boolean acceptBinding(int type,int modifiers, char[] packageName,char[] simpleTypeName, String path, AccessRestriction access) {
			if(path!=null && exclude!=null && path.compareTo(exclude)==0) return false;

			if(DEBUG && !shown) {
				shown=false;
				IJavaScriptProject proj = getJavaScriptProject();
				try {
					IIncludePathEntry[] entries = proj.getResolvedIncludepath(true);
					System.out.println("DocumentContextFragmentRoot ====>" +"Project Classpath : \n"); //$NON-NLS-1$ //$NON-NLS-2$

					for(int i = 0;i<entries.length;i++) {
						System.out.println("\t" + entries[i].getPath()); //$NON-NLS-1$

					}
				} catch (JavaScriptModelException ex) {
					// TODO Auto-generated catch block
					ex.printStackTrace();
				}
			}
			for (int i = 0; workingCopies!=null && i < workingCopies.length; i++) {
				if (workingCopies[i].getPath().toString().equals(path)) {
					if(DEBUG) System.out.println("DocumentContextFragmentRoot ====>" +"REJECTING binding..\n\t" + new String(simpleTypeName) + " in " + path + "\n\tfor file " + fRelativeFile.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
					if(DEBUG) System.out.println("\tType is in WorkingCopies "); //$NON-NLS-1$
					return false;
				}
			}
			
			this.foundPaths.add(path);
			return true;

//			for(int i = 0;i<includedFiles.length;i++) {
//				if(Util.isSameResourceString(path, includedFiles[i])) {
//					if(DEBUG) System.out.println("DocumentContextFragmentRoot ====>" + "Accepting binding.. " + new String(simpleTypeName) + " in " + path + "\n\tfor file " + fRelativeFile.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
//					this.foundPaths.add(path);
//					return true;
//				} else if(includedFiles[i].equals("*")) { //$NON-NLS-1$
//					this.foundPaths.add(path);
//					return true;
//				}
//				else if(HACK_DOJO) {
//					String includeString = includedFiles[i];
//					if(path.toLowerCase().indexOf(DOJO_COMPRESSED)>0 && (includeString.toLowerCase().indexOf(UNCOMPRESSED_DOJO)>0)) {
//						this.foundPaths.add(path);
//						return true;
//					}
//
//				}
//			}
//
//			String systemFiles[] = getProjectSystemFiles();
//
//			for(int i = 0;i<systemFiles.length;i++) {
//				if(Util.isSameResourceString(path, systemFiles[i]) || (new Path(systemFiles[i])).isPrefixOf(new Path(path))) {
//					if(DEBUG) System.out.println("DocumentContextFragmentRoot ====>" + "Accepting binding.. " + new String(simpleTypeName) + " in " + path + " \n\tfor file " + fRelativeFile.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
//					this.foundPaths.add(path);
//					return true;
//				}
//			}
//			if(DEBUG) System.out.println("DocumentContextFragmentRoot ====>" +"REJECTING binding..\n\t" + new String(simpleTypeName) + " in " + path + " \n\tfor file " + fRelativeFile.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
//			if(DEBUG) System.out.println("\t(relative) page includes = : " ); //$NON-NLS-1$
//			if(DEBUG) {
//				for(int i = 0;includedFiles!=null && i<includedFiles.length;i++) {
//					System.out.println("\t\t" + includedFiles[i]); //$NON-NLS-1$
//				}
//			}
//			//this.foundPath=null;
//			return false;
		}

		public String getFoundPath() {
			return foundPaths.size()>0?(String)foundPaths.get(0):null;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.wst.jsdt.internal.core.search.IRestrictedAccessBindingRequestor#getFoundPaths()
		 */
		public ArrayList getFoundPaths() {
			return foundPaths;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.wst.jsdt.internal.core.search.IRestrictedAccessBindingRequestor#setExcludePath(java.lang.String)
		 */
		public void setExcludePath(String excludePath) {
			this.exclude=excludePath;

		}
	}

	public String[] getProjectSystemFiles() {

		if(fSystemFiles!=null) return fSystemFiles;

		IJavaScriptProject javaProject = getJavaScriptProject();
		int lastGood = 0;
		IPackageFragmentRoot[]  projectRoots = null;

		try {
			projectRoots = javaProject.getPackageFragmentRoots();
			for(int i =0;i<projectRoots.length;i++) {
				if(projectRoots[i].isLanguageRuntime()) {
					projectRoots[lastGood++]=projectRoots[i];
				}else if(projectRoots[i].getRawIncludepathEntry().getEntryKind()== IIncludePathEntry.CPE_SOURCE) {
					projectRoots[lastGood++]=projectRoots[i];
				}
			}
		} catch (JavaScriptModelException ex) {
			projectRoots = new IPackageFragmentRoot[0];
		}

		fSystemFiles = new String[lastGood ];
		for(int i = 0;i<fSystemFiles.length;i++) {
			fSystemFiles[i] = projectRoots[i].getPath().toString().intern();
		}
		return fSystemFiles;
	}


	public void classpathChange() {
		fSystemFiles=null;
	}



	public DocumentContextFragmentRoot(IJavaScriptProject project,
									   IFile resourceRelativeFile,
									   IPath resourceAbsolutePath,
									   IPath webContext,
									   IIncludePathEntry rawClassPath) {

		super(resourceRelativeFile, (JavaProject)project);

		fRelativeFile = resourceRelativeFile ;
	//	this.includedFiles = new IPath[0];
		//this.timeStamps = new Long[0];
		this.absolutePath = ((IContainer)project.getResource()).findMember(resourceAbsolutePath);
		this.webContext=webContext;
		this.rawClassPathEntry = rawClassPath;
		//dirty = true;
		if(DEBUG) System.out.println("DocumentContextFragmentRoot ====>" + "Creating instance for total of:>>" + ++instances + "<<.  \n\tRelative file:" + fRelativeFile.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$


	}

	public void finalize() {

		if(DEBUG) System.out.println("DocumentContextFragmentRoot ====>" + "finalize() for a  total of:>>" + --instances + "<<.  \n\tRelative file:" + fRelativeFile!=null?null:fRelativeFile.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}


	/* (non-Javadoc)
	 * @see org.eclipse.wst.jsdt.internal.core.PackageFragmentRoot#getRawClasspathEntry()
	 */
	public IIncludePathEntry getRawIncludepathEntry() throws JavaScriptModelException {
		if(rawClassPathEntry!=null) return rawClassPathEntry;
		return super.getRawIncludepathEntry();
	}

	protected  RestrictedDocumentBinding getRestrictedAccessRequestor() {
		 if(importPolice==null) {
			 importPolice = new RestrictedDocumentBinding();
		 }
		importPolice.reset();
		return importPolice;
	}

	public DocumentContextFragmentRoot(IJavaScriptProject project,
			   IFile resourceRelativeFile,
			   IPath resourceAbsolutePath,
			   IPath webContext) {
		this(project,resourceRelativeFile,resourceAbsolutePath,webContext,null);
	}

	public DocumentContextFragmentRoot(IJavaScriptProject project,
			   						   IFile resourceRelativeFile) {

			this(project,resourceRelativeFile, new Path(""), new Path("")); //$NON-NLS-1$ //$NON-NLS-2$
	}


	public void setIncludedFiles2(String[] fileNames) {



		ArrayList newImports = new ArrayList();
		//int arrayLength = 0;

		for(int i = 0; i<fileNames.length;i++) {
			File importFile = isValidImport(fileNames[i]);
			if(importFile==null) continue;
			IPath importPath = resolveChildPath(fileNames[i]);
			newImports.add( importPath.toString() );
		}

		boolean equals = includedFiles!=null && newImports.size()==includedFiles.length;

		for(int i=0;equals && i<newImports.size();i++) {
			if(((String)newImports.get(i)).compareTo(includedFiles[i])!=0) equals=false;
		}

		if(DEBUG) System.out.println("DocumentContextFragmentRoot ====>" + "Imports " + (equals?"did NOT change": "CHANGED:") + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
		if(DEBUG) {
			for(int i = 0;includedFiles!=null && i<includedFiles.length;i++) {
				System.out.println("\t\t" + includedFiles[i]); //$NON-NLS-1$
			}
		}
		if(equals) return;
/*  start  try and expand the include paths from the library entries if necisary */
		IIncludePathEntry[] current = new IIncludePathEntry[0];
		IJavaScriptProject javaProject = getJavaScriptProject();

		try {
			current = javaProject.getRawIncludepath();
		} catch (JavaScriptModelException ex) {
			// TODO Auto-generated catch block
		//	ex.printStackTrace();
		}
		for(int i = 0;i<current.length;i++) {
			JsGlobalScopeContainerInitializer init = JSDScopeUtil.getContainerInitializer(current[i].getPath());
			for(int k=0;k<fileNames.length;k++) {
				String[] newEntries = init.resolvedLibraryImport(fileNames[k]);
				if(newEntries!=null && newEntries.length>0        ) {
					newImports.removeAll(Arrays.asList(newEntries));
					newImports.addAll(Arrays.asList(newEntries));
				}
			}
		}

/* end class path expansion */
		this.includedFiles = (String[])newImports.toArray(new String[newImports.size()]);
	//	System.arraycopy(newImports, 0, this.includedFiles, 0, arrayLength);
		updateClasspathIfNeeded();
		dojoHack();
	}
	public void setIncludedFiles(String[] fileNames) {
		
		
		
		String[] newImports = new String[fileNames.length];
		//Long[] newTimestamps = new Long[fileNames.length];
		int arrayLength = 0;
		
		for(int i = 0; i<fileNames.length;i++) {
			File importFile = isValidImport(fileNames[i]);
			if(importFile==null && !fileNames[i].equals("*")) continue; //$NON-NLS-1$
			if(fileNames[i].equals("*")) {
				newImports[arrayLength++] = fileNames[i];
			} else {
				IPath importPath = resolveChildPath(fileNames[i]);	
				newImports[arrayLength++] = importPath.toString();
			}
			//newTimestamps[arrayLength] = new Long(importFile.lastModified());	

			//arrayLength++;
		}
		
		boolean equals = includedFiles!=null && arrayLength==includedFiles.length;
		
		for(int i=0;equals && i<arrayLength;i++) {
			if(newImports[i].compareTo(includedFiles[i])!=0) equals=false;
		}
		
		//this.includedFiles!=null && (newImports !=null) &&   this.includedFiles.length == arrayLength;
		
		//equals = equals || (this.includedFiles==null && newImports ==null);
		//if(!equals) removeStaleClasspath(this.includedFiles);
		
		//		
//
//		if(!equals) dirty = true;
//		
//		/* try some more cases */
//		
//		for(int i = 0;!dirty && i<this.includedFiles.length;i++) {
//			if(!(this.includedFiles[i].equals(newImports[i]))) {
//				dirty = true;
//				
//			}
//		}
//		
//		for(int i = 0;!dirty && i<newTimestamps.length;i++) {
//			if(!(this.timeStamps[i].equals(newTimestamps[i]))) {
//				dirty = true;
//			}
//		}
//		
//		if(!dirty) return;
		if(DEBUG) System.out.println("DocumentContextFragmentRoot ====>" + "Imports " + (equals?"did NOT change": "CHANGED:") + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
		if(DEBUG) {
			for(int i = 0;includedFiles!=null && i<includedFiles.length;i++) {
				System.out.println("\t\t" + includedFiles[i]); //$NON-NLS-1$
			}
		}
		if(equals) return;
		this.includedFiles = new String[arrayLength];
	//	this.timeStamps = new Long[arrayLength];
		System.arraycopy(newImports, 0, this.includedFiles, 0, arrayLength);
	//	System.arraycopy(newTimestamps, 0, this.timeStamps, 0, arrayLength);
		dojoHack();
		updateClasspathIfNeeded();
	
		
	}
	private void dojoHack() {
		if(!HACK_DOJO) return;
		

		for(int i = 0;i<includedFiles.length;i++) {
			String includeString = includedFiles[i];

			int dojoIndex = includeString.toLowerCase().indexOf(DOJO_COMPRESSED);

			if(includeString!=null && dojoIndex>=0) {
				/* found dojo.js replace it with dojo.js.uncompressed.js if it exists */
				String newIncludeString = includeString.substring(0, dojoIndex) + UNCOMPRESSED_DOJO + includeString.substring(dojoIndex + DOJO_COMPRESSED.length(),includeString.length());
				File djUncom = isValidImport(newIncludeString);
				if(djUncom!=null && djUncom.exists()) {
					includedFiles[i] = newIncludeString;
				}
			}
		}
	}

	//private void removeStaleClasspath(String[] oldEntries) {
//
//	}

	private void updateClasspathIfNeeded() {



		ArrayList newEntriesList = new ArrayList();
		IJavaScriptProject javaProject = getJavaScriptProject();
		IResource myResource = getResource();
		IContainer folder = (IContainer)myResource;

		for(int i = 0;i<includedFiles.length;i++) {
			IResource theFile = folder.findMember(includedFiles[i]);
			if(theFile == null || javaProject.isOnIncludepath(theFile)) continue;
			IIncludePathEntry entry = JavaScriptCore.newLibraryEntry(theFile.getLocation().makeAbsolute(), null, null, new IAccessRule[0], new IIncludePathAttribute[] {IIncludePathAttribute.HIDE}, true);

			newEntriesList.add(entry);
		}
		IIncludePathEntry[] current = new IIncludePathEntry[0];
		try {
			current = javaProject.getRawIncludepath();
		} catch (JavaScriptModelException ex) {
			// TODO Auto-generated catch block
		//	ex.printStackTrace();
		}


		IIncludePathEntry[] newCpEntries = new IIncludePathEntry[newEntriesList.size() + current.length];
		System.arraycopy(current, 0, newCpEntries, 0, current.length);
		int newPtr = 0 ;
		for(int i =  current.length; i<newCpEntries.length;i++) {
			newCpEntries[i] = (IIncludePathEntry)newEntriesList.get(newPtr++);
		}
		try {
			javaProject.setRawIncludepath(newCpEntries, false, new NullProgressMonitor());
		} catch (JavaScriptModelException ex) {}

	}

	public IPath resolveChildPath(String childPathString) {
        // Genuitec Begin Fix 6149: Exception opening external HTML file
	    if (getResource() == null) {
	        return null;
	    }
	    // Genuitec End Fix 6149: Exception opening external HTML file
		/* relative paths:
		 * ./testfile.js  are relative to file scope
		 * absolute paths: /scripts/file.js are relative to absolutePath, and must be made relative to this resource
		 * if the file does not exist in context root, the path is the absolute path on the filesystem.
		 */
		if(childPathString==null) return null;
		if(childPathString.length()==0) return new Path(""); //$NON-NLS-1$
		IPath resolvedPath = null;
		IResource member;
		switch(childPathString.charAt(0)) {

			default:
				resolvedPath = new Path(childPathString);
			//if(resolvedPath.toFile()!=null && resolvedPath.toFile().exists()) break;

			member = ((IContainer)getResource()).findMember(resolvedPath);

			if(member!=null && member.exists()) break;
			case '/':
			case '\\':
				IPath childPath = new Path(childPathString);

				IPath newPath = childPath.removeFirstSegments(childPath.matchingFirstSegments(webContext));

				member = ((IContainer)getResource()).findMember(newPath);
				//if(member.exists()) return new Path(newPath);

				resolvedPath = newPath;
				if(member!=null && member.exists()) break;

			case '.':
				/* returns a new relative path thats relative to the resource */
				IPath relative=null;
				try {
					relative = fRelativeFile.getFullPath().removeLastSegments(1);
				} catch (Exception ex) {
					/* file usually outside of workspace in this instance */
					return null;
				}
				IPath relRes = getResource().getFullPath();
				if(relRes.isPrefixOf(relative)) {
					IPath amended = relative.removeFirstSegments(relRes.matchingFirstSegments(relative));
					resolvedPath = amended.append(childPathString);
				}
				break;


		}

		return resolvedPath;

	}

	public IPath getPath() {
		if(fRelativeFile!=null) return fRelativeFile.getFullPath().removeLastSegments(1);
		return super.getPath();
	}

	public boolean equals(Object o) {
//		if (this == o)
//			return true;
		if (!(o instanceof DocumentContextFragmentRoot)) return false;

		DocumentContextFragmentRoot other= (DocumentContextFragmentRoot) o;



		boolean equalRelativeFileAndIncludedFileLengths = (this.fRelativeFile!=null && this.fRelativeFile.equals(other.fRelativeFile)) &&
						  this.includedFiles!=null && (other.includedFiles !=null) &&
						  this.includedFiles.length == other.includedFiles.length;

		if(!equalRelativeFileAndIncludedFileLengths) return false;

		/* try some more cases */

		for(int i = 0;i<this.includedFiles.length;i++) {
			if(!(this.includedFiles[i].equals(other.includedFiles[i]))) return false;
		}

//		for(int i = 0;i<this.timeStamps.length;i++) {
//			if(!(this.timeStamps[i].equals( other.timeStamps[i]        )        )) return false;
//		}


		return true;
	}

	public String getElementName() {
		if(fRelativeFile!=null) return this.fRelativeFile.getName();
		return super.getElementName();
	}

	public int hashCode() {
		return fRelativeFile!=null?this.fRelativeFile.hashCode():super.hashCode();
	}

	public boolean isExternal() {
		return false;
	}
	/**
	 * Jars and jar entries are all read only
	 */
	public boolean isReadOnly() {
		return false;
	}

	/**
 * Returns whether the corresponding resource or associated file exists
 */
	protected boolean resourceExists() {
		return true;
	}


	public SearchableEnvironment newSearchableNameEnvironment(WorkingCopyOwner owner) throws JavaScriptModelException {
		/* previously restricted searchable environment to 'this'.  But that removes library entries from search results so going back to global project */
		SearchableEnvironment env =  super.newSearchableNameEnvironment(owner);//new SearchableEnvironment((JavaProject)getJavaProject(),this, owner);
		int includeMask = IJavaScriptSearchScope.SOURCES | IJavaScriptSearchScope.APPLICATION_LIBRARIES | IJavaScriptSearchScope.SYSTEM_LIBRARIES | IJavaScriptSearchScope.REFERENCED_PROJECTS;
		env.nameLookup.setRestrictedAccessRequestor(getRestrictedAccessRequestor());
		((JavaSearchScope)env.searchScope).add((JavaProject)getJavaScriptProject(), includeMask, new HashSet(2));
		return env;
	}

	/*
	 * Returns a new name lookup. This name lookup first looks in the given working copies.
	 */
	public NameLookup newNameLookup(IJavaScriptUnit[] workingCopies) throws JavaScriptModelException {
		this.workingCopies = workingCopies;
		NameLookup lookup = super.newNameLookup(this.workingCopies);
		lookup.setRestrictedAccessRequestor(getRestrictedAccessRequestor());
		return lookup;
		//return ((LookupScopeElementInfo)getElementInfo()).newNameLookup( workingCopies);
	}

	/*
	 * Returns a new name lookup. This name lookup first looks in the working copies of the given owner.
	 */
	public NameLookup newNameLookup(WorkingCopyOwner owner) throws JavaScriptModelException {

		NameLookup lookup =  super.newNameLookup(owner);
		lookup.setRestrictedAccessRequestor(getRestrictedAccessRequestor());
		return lookup;
//
//		JavaModelManager manager = JavaModelManager.getJavaModelManager();
//		IJavaScriptUnit[] workingCopies = owner == null ? null : manager.getWorkingCopies(owner, true/*add primary WCs*/);
//		return newNameLookup(workingCopies);
	}

	public File isValidImport(String importName) {
		IPath filePath = resolveChildPath(importName);
		if(filePath==null) return null;
		File file = filePath.toFile();
		if(file.isFile()) {
			return file;
		}else {
	//		IPath childPath = new Path(importName);
			IFile resolved = null;
			/* since eclipse throws an exception if it doesn't exists (contrary to its API) we have to catch it*/

			try {
				resolved = ((IContainer)getResource()).getFile(new Path(file.getPath()));
			}catch(Exception e) {}

			boolean exists =  resolved!=null && resolved.exists();
			/* Special case for absolute paths specified with \ and / */
			if( importName.charAt(0)=='\\' || importName.charAt(0)=='/'){
				int seg  = resolved.getFullPath().matchingFirstSegments(webContext);

				exists = exists && (webContext!=new Path("") && seg >0); //$NON-NLS-1$
			}
			if(exists) return new File(resolved.getLocation().toString());
		}
		return null;
	}

	public int getKind() throws JavaScriptModelException {
			return IPackageFragmentRoot.K_SOURCE;
	}


	public String toString() {
		StringBuffer me = new StringBuffer("Relative to: " + fRelativeFile.getName() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
		me.append("Absolute to: " + webContext + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
		me.append("Included File\t\t\tLast Moddified\n"); //$NON-NLS-1$
		for(int i = 0;i<includedFiles.length;i++) {
			me.append(includedFiles[i] /*+ "\t\t\t\t" + timeStamps[i].longValue()*/ + "\n"); //$NON-NLS-1$
		}

		return me.toString();
	}

	public IResource getResource() {
		return absolutePath;
	}


}
