/*******************************************************************************
 * Copyright (c) 2000, 2012 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.team.internal.ccvs.ui.repo;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

import org.eclipse.core.runtime.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.Command;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
import org.eclipse.team.internal.ccvs.ui.*;
import org.eclipse.team.internal.ccvs.ui.Policy;
import org.eclipse.team.internal.ccvs.ui.operations.RemoteLogOperation;
import org.eclipse.team.internal.ccvs.ui.operations.RemoteLogOperation.LogEntryCache;

public class RepositoryRoot extends PlatformObject {

	public static final String[] DEFAULT_AUTO_REFRESH_FILES = { ".project" }; //$NON-NLS-1$ 
	private static final String DEFINED_MODULE_PREFIX = "module:"; //$NON-NLS-1$
	
	ICVSRepositoryLocation root;
	String name;
	TagCacheEntry rootTagCacheEntry = new TagCacheEntry(Path.ROOT, null);
	// Map of String (remote folder path) -> Set (file paths that are project relative)
	Map autoRefreshFiles = new HashMap();
	// Map of String (module name) -> ICVSRemoteFolder (that is a defined module)
	Map modulesCache;
	Object modulesCacheLock = new Object();
	// List of date tags
	List dateTags = new ArrayList();
	
	public static class TagCacheEntry {
		IPath path;
		// Set of tags found for this path
		private Set tags = new HashSet();
		// String(last path segment) -> TagCacheEntry for child paths
		Map children = new HashMap();
		TagCacheEntry parent;
		long lastAccessTime;
		private static final int CACHE_LIFESPAN_IN_DAYS = 7;

		public TagCacheEntry(IPath path, TagCacheEntry parent) {
			this.path = path;
			this.parent = parent;
			accessed();
		}

		public Set getTags() {
			accessed();
			return tags;
		}

		public Iterator getChildrenIterator() {
			return this.children.values().iterator();
		}

		public boolean isEmpty() {
			return getTags().isEmpty() && children.isEmpty();
		}

        public boolean isExpired() {
            long currentTime = System.currentTimeMillis();
            long ms = currentTime - lastAccessTime;
            int seconds = (int)ms / 1000;
            int hours = seconds / 60 / 60;
            int days = hours / 24;
            return days > CACHE_LIFESPAN_IN_DAYS;
        }

		private void accessed() {
			lastAccessTime = System.currentTimeMillis();
		}
	}
	
	public RepositoryRoot(ICVSRepositoryLocation root) {
		this.root = root;
	}
	
	/**
	 * Returns the name.
	 * @return String
	 */
	public String getName() {
		return name;
	}

	/**
	 * Method getRemoteFolder.
	 * @param path
	 * @param tag
	 * @return ICVSRemoteFolder
	 */
	public ICVSRemoteFolder getRemoteFolder(String path, CVSTag tag, IProgressMonitor monitor) {
		if (isDefinedModuleName(path)) {
			return getDefinedModule(getDefinedModuleName(path), tag, monitor);
		} else {
			return root.getRemoteFolder(path, tag);
		}
	}

	static boolean isDefinedModuleName(String path) {
		return path.startsWith(DEFINED_MODULE_PREFIX);
	}

	static String getDefinedModuleName(String path) {
		return path.substring(DEFINED_MODULE_PREFIX.length());
	}
	
	static String asDefinedModulePath(String path) {
		return DEFINED_MODULE_PREFIX + path;
	}
	
	/**
	 * Method getDefinedModule.
	 * @param path
	 * @param tag
	 * @param monitor
	 * @return ICVSRemoteFolder
	 */
	private ICVSRemoteFolder getDefinedModule(String path, CVSTag tag, IProgressMonitor monitor) {
		Map cache = getDefinedModulesCache(tag, monitor);
		ICVSRemoteFolder folder = (ICVSRemoteFolder)cache.get(path);
		if (folder != null) {
			folder = (ICVSRemoteFolder)folder.forTag(tag);
		}
		return folder;
	}
	
	private Map getDefinedModulesCache(CVSTag tag, IProgressMonitor monitor) {
		if (modulesCache == null) {
			try {
				// Fetch the modules before locking the cache (to avoid deadlock)
				ICVSRemoteResource[] folders = root.members(CVSTag.DEFAULT, true, monitor);
				synchronized(modulesCacheLock) {
					modulesCache = new HashMap();
					for (int i = 0; i < folders.length; i++) {
						ICVSRemoteResource resource = folders[i];
						modulesCache.put(resource.getName(), resource);
					}
				}
			} catch (CVSException e) {
				// we could't fetch the modules. Log the problem and continue
				CVSUIPlugin.log(e);
				// Return an empty map but don't save it so the fetching of 
				// the modules will occur again
				return new HashMap();
			}
		}
		return modulesCache;
	}
	
	public ICVSRemoteResource[] getDefinedModules(CVSTag tag, IProgressMonitor monitor) {
		Map cache = getDefinedModulesCache(tag, monitor);
		return (ICVSRemoteResource[]) cache.values().toArray(new ICVSRemoteResource[cache.size()]);
	}
	
	public static String getRemotePathFor(ICVSResource resource) throws CVSException {
		if (resource.isFolder()) {
			if (resource instanceof ICVSRemoteFolder) {
				ICVSRemoteFolder remoteFolder = (ICVSRemoteFolder) resource;
				if (remoteFolder.isDefinedModule()) {
					return asDefinedModulePath(remoteFolder.getName());
				}
			}
			FolderSyncInfo info = ((ICVSFolder)resource).getFolderSyncInfo();
			if (info == null)
				throw new CVSException(NLS.bind(CVSUIMessages.RepositoryRoot_folderInfoMissing, new String[] { resource.getName() })); 
			return info.getRepository();
		} else {
			FolderSyncInfo info = resource.getParent().getFolderSyncInfo();
			if (info == null)
				throw new CVSException(NLS.bind(CVSUIMessages.RepositoryRoot_folderInfoMissing, new String[] { resource.getParent().getName() })); 
			String path = new Path(null, info.getRepository()).append(resource.getName()).toString();
			return path;
		}
	}
	
	/**
	 * Returns the root.
	 * @return ICVSRepositoryLocation
	 */
	public ICVSRepositoryLocation getRoot() {
		return root;
	}

	/**
	 * Sets the name.
	 * @param name The name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Accept the tags for any remote path that represents a folder. However, for the time being,
	 * the given version tags are added to the list of known tags for the 
	 * remote ancestor of the resource that is a direct child of the remote root.
	 * 
	 * It is the responsibility of the caller to ensure that the given remote path is valid.
	 */
	public void addTags(String remotePath, CVSTag[] tags) {
		if (tags.length == 0) {
			return;
		}
		addDateTags(tags);
		addVersionAndBranchTags(remotePath, tags);
	}

	private void addDateTags(CVSTag[] tags){
		for(int i = 0; i < tags.length; i++){
			if(tags[i].getType() == CVSTag.DATE){
				dateTags.add(tags[i]);
			}
		}
	}

	private void addVersionAndBranchTags(String remotePath, CVSTag[] tags) {
		TagCacheEntry entry = getTagCacheEntryFor(remotePath, true);

		// Store the tag with the appropriate ancestor
		for (int i = 0; i < tags.length; i++) {
			if (tags[i].getType() != CVSTag.DATE) {
				Set parentTags = new HashSet();
				addAllKnownTagsForParents(entry, parentTags);
				if (!parentTags.contains(tags[i])) {
					entry.getTags().add(tags[i]);
					removeTagFromChildrenCacheEntries(entry, tags[i]);
				}
			}
		}
	}

	/**
	 * Add the given date tag to the list of date tags associated with the repository.
	 * @param tag a date tag
	 */
	public void addDateTag(CVSTag tag) {
		if (!dateTags.contains(tag)) {
			dateTags.add(tag);
		}
	}
	public void removeDateTag(CVSTag tag) {
		if (dateTags.contains(tag)) {
			dateTags.remove(tag);
		}
	}
	/**
	 * Return the list of date tags associated with the repository.
	 * @return the list of date tags
	 */
	public CVSTag[] getDateTags() {
		return (CVSTag[]) dateTags.toArray(new CVSTag[dateTags.size()]);
	}
	
	/**
	 * Remove the given tags from the receiver
	 * @param remotePath
	 * @param tags
	 */
	public void removeTags(String remotePath, CVSTag[] tags) {
		removeDateTags(tags);
		removeVersionAndBranchTags(remotePath, tags);
	}
	
	private void removeDateTags(CVSTag[] tags) {		
		if(dateTags.isEmpty())return;
		// Store the tag with the appropriate ancestor
		for (int i = 0; i < tags.length; i++) {
			dateTags.remove(tags[i]);
		}
	}

	private void removeVersionAndBranchTags(String remotePath, CVSTag[] tags) {
		TagCacheEntry entry = getTagCacheEntryFor(remotePath, false);
		// remove tags from this path and its children
		if (entry != null) {
			removeTagsFromChildrenCacheEntries(entry, tags);
		}

		// remove tags from all parents of this path
		entry = getKnownParentTagCacheEntryFor(remotePath);
		for (int i = 0; i < tags.length; i++) {
			if (entry.getTags().contains(tags[i])) {
				entry.getTags().remove(tags[i]);
				continue;
			}
			TagCacheEntry currentEntry = entry;
			while (currentEntry.parent != null) {
				if (currentEntry.parent.getTags().contains(tags[i])) {
					// remove tag from parent and add it to siblings
					currentEntry.parent.getTags().remove(tags[i]);
					Iterator siblingIterator = currentEntry.parent
							.getChildrenIterator();
					while (siblingIterator.hasNext()) {
						TagCacheEntry sibling = (TagCacheEntry) siblingIterator
								.next();
						if (!sibling.equals(currentEntry)) {
							sibling.getTags().add(tags[i]);
						}
					}
					break;
				} else {
					currentEntry = currentEntry.parent;
				}
			}
		}
		if (entry.isEmpty()) {
			removeTagCacheEntry(entry);
		}
	}

	/**
	 * Returns the absolute paths of the auto refresh files relative to the
	 * repository.
	 * 
	 * @return String[]
	 */
	public String[] getAutoRefreshFiles(String remotePath) {
		Set files = (Set) autoRefreshFiles.get(remotePath);
		if (files == null || files.isEmpty()) {
			// convert the default relative file paths to full paths
			if (isDefinedModuleName(remotePath)) {
				return new String[0];
			}
			List result = new ArrayList();
			for (int i = 0; i < DEFAULT_AUTO_REFRESH_FILES.length; i++) {
				String relativePath = DEFAULT_AUTO_REFRESH_FILES[i];
				result.add(new Path(null, remotePath).append(relativePath).toString());
			}
			return (String[]) result.toArray(new String[result.size()]);
		} else {
			return (String[]) files.toArray(new String[files.size()]);
		}
	}
	
	/**
	 * Sets the auto refresh files for the given remote path to the given
	 * string values which are absolute file paths (relative to the receiver).
	 * 
	 * @param autoRefreshFiles The autoRefreshFiles to set
	 */
	public void setAutoRefreshFiles(String remotePath, String[] autoRefreshFiles) {
		Set newFiles = new HashSet(Arrays.asList(autoRefreshFiles));
		// Check to see if the auto-refresh files are the default files
		if (autoRefreshFiles.length == DEFAULT_AUTO_REFRESH_FILES.length) {
			boolean isDefault = true;
			for (int i = 0; i < DEFAULT_AUTO_REFRESH_FILES.length; i++) {
				String filePath = DEFAULT_AUTO_REFRESH_FILES[i];
				if (!newFiles.contains(new Path(null, remotePath).append(filePath).toString())) {
					isDefault = false;
					break;
				}
			}
			if (isDefault) {
				this.autoRefreshFiles.remove(remotePath);
				return;
			}
		}
		this.autoRefreshFiles.put(remotePath, newFiles);
	}

	/**
	 * Fetches tags from auto-refresh files.
	 */
	public CVSTag[] refreshDefinedTags(ICVSFolder folder, boolean recurse,
			IProgressMonitor monitor) throws TeamException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, recurse ? 210 : 100);
		try {
			CVSTag[] tags = null;
			if (!folder.getFolderSyncInfo().isVirtualDirectory()) {
				// Only try the auto-refresh file(s) if we are not recursing
				// into sub-folders
				tags = fetchTagsUsingAutoRefreshFiles(folder,
						Policy.subMonitorFor(monitor, 50));
			}
			if (tags == null || tags.length == 0) {
				// There we're no tags found on the auto-refresh files or we
				// we're asked to go deep
				// Try using the log command
				tags = fetchTagsUsingLog(folder,
						Policy.subMonitorFor(monitor, 50));
			}
			if (tags != null && tags.length > 0) {
				String remotePath = getRemotePathFor(folder);
				addTags(remotePath, tags);
				return tags;
			}
			if (recurse) {
				Set tagsSet = new HashSet();
				folder.fetchChildren(Policy.subMonitorFor(monitor, 10));
				ICVSResource[] children = folder
						.members(ICVSFolder.FOLDER_MEMBERS);
				for (int i = 0; i < children.length; i++) {
					tagsSet.addAll(Arrays.asList(refreshDefinedTags(
							(ICVSFolder) children[i], recurse, Policy
									.subMonitorFor(monitor,
											100 / children.length))));
				}
				tags = (CVSTag[]) tagsSet.toArray(new CVSTag[tagsSet.size()]);
			}
			return tags;
		} finally {
			monitor.done();
		}
	}

    private CVSTag[] fetchTagsUsingLog(ICVSFolder folder, IProgressMonitor monitor) throws CVSException {
        LogEntryCache logEntries = new LogEntryCache();
        RemoteLogOperation operation = new RemoteLogOperation(null, new ICVSRemoteResource[] { asRemoteResource(folder) }, null, null, logEntries) {
            protected Command.LocalOption[] getLocalOptions(CVSTag tag1,CVSTag tag2) {
                Command.LocalOption[] options = new Command.LocalOption[] {};
                Command.LocalOption[] newOptions = new Command.LocalOption[options.length + 1];
                System.arraycopy(options, 0, newOptions, 0, options.length);
                newOptions[options.length] = Command.DO_NOT_RECURSE;
                return newOptions;
            }
        };
        try {
            operation.run(monitor);
        } catch (InvocationTargetException e) {
            throw CVSException.wrapException(e);
        } catch (InterruptedException e) {
            // Ignore;
        }
        String[] keys = logEntries.getCachedFilePaths();
        Set tags = new HashSet();
        for (int i = 0; i < keys.length; i++) {
            String key = keys[i];
            ILogEntry[] entries = logEntries.getLogEntries(key);
            for (int j = 0; j < entries.length; j++) {
                ILogEntry entry = entries[j];
                tags.addAll(Arrays.asList(entry.getTags()));
            }
        }
        return (CVSTag[]) tags.toArray(new CVSTag[tags.size()]);
    }

    private ICVSRemoteResource asRemoteResource(ICVSFolder folder) throws CVSException {
        if (folder instanceof ICVSRemoteResource) {
            return (ICVSRemoteResource)folder;
        }
        return CVSWorkspaceRoot.getRemoteResourceFor(folder);
    }

    /**
	 * Fetches tags from auto-refresh files.
	 */
	private CVSTag[] fetchTagsUsingAutoRefreshFiles(ICVSFolder folder, IProgressMonitor monitor) throws TeamException {
	    String remotePath = getRemotePathFor(folder);
		String[] filesToRefresh = getAutoRefreshFiles(remotePath);
		try {
			monitor.beginTask(null, filesToRefresh.length * 10); 
			List tags = new ArrayList();
			for (int i = 0; i < filesToRefresh.length; i++) {
				ICVSRemoteFile file = root.getRemoteFile(filesToRefresh[i], CVSTag.DEFAULT);
				try {
                    tags.addAll(Arrays.asList(fetchTags(file, Policy.subMonitorFor(monitor, 5))));
        		} catch (TeamException e) {
        			IStatus status = e.getStatus();
        			boolean doesNotExist = false;
        			if (status.getCode() == CVSStatus.SERVER_ERROR && status.isMultiStatus()) {
        				IStatus[] children = status.getChildren();
        				if (children.length == 1 && children[0].getCode() == CVSStatus.DOES_NOT_EXIST) {
        				    // Don't throw an exception if the file does no exist
        					doesNotExist = true;
        				}
        			}
        			if (!doesNotExist) {
        			    throw e;
        			}
                }
			}
			return (CVSTag[]) tags.toArray(new CVSTag[tags.size()]);
		} finally {
			monitor.done();
		}
	}
	
	/**
	 * Returns Branch and Version tags for the given files
	 */	
	private CVSTag[] fetchTags(ICVSRemoteFile file, IProgressMonitor monitor) throws TeamException {
		Set tagSet = new HashSet();
		ILogEntry[] entries = file.getLogEntries(monitor);
		for (int j = 0; j < entries.length; j++) {
			CVSTag[] tags = entries[j].getTags();
			for (int k = 0; k < tags.length; k++) {
				tagSet.add(tags[k]);
			}
		}
		return (CVSTag[])tagSet.toArray(new CVSTag[0]);
	}

	private TagCacheEntry getTagCacheEntryFor(String remotePath, boolean create) {
		String[] segments = new Path(null, remotePath).segments();
		TagCacheEntry currentTagCacheEntry = rootTagCacheEntry;
		for (int i = 0; i < segments.length; i++) {
			String segment = segments[i];
			if (currentTagCacheEntry.children.containsKey(segment)) {
				currentTagCacheEntry = (TagCacheEntry) currentTagCacheEntry.children
						.get(segment);
				continue;
			}
			if (!create) {
				return null;
			}
			TagCacheEntry newTagCacheEntry = new TagCacheEntry(new Path(null,
					remotePath).removeLastSegments(segments.length - (i + 1)),
					currentTagCacheEntry);
			currentTagCacheEntry.children.put(segment, newTagCacheEntry);
			currentTagCacheEntry = newTagCacheEntry;
		}
		return currentTagCacheEntry;
	}

	private TagCacheEntry getKnownParentTagCacheEntryFor(String remotePath) {
		String[] segments = new Path(null, remotePath).segments();
		TagCacheEntry currentTagCacheEntry = rootTagCacheEntry;
		for (int i = 0; i < segments.length; i++) {
			String segment = segments[i];
			if (currentTagCacheEntry.children.containsKey(segment)) {
				currentTagCacheEntry = (TagCacheEntry) currentTagCacheEntry.children
						.get(segment);
			} else {
				break; // we reached the last existing parent
			}
		}
		return currentTagCacheEntry;
	}

	private void removeTagsFromChildrenCacheEntries(TagCacheEntry entry,
			CVSTag[] tags) {
		for (int i = 0; i < tags.length; i++) {
			removeTagFromChildrenCacheEntries(entry, tags[i]);
		}
		entry.getTags().removeAll(Arrays.asList(tags));
		if (entry.isEmpty()) {
			// remove this entry when the last tags where removed
			// keep the entry if there are any children that have tags
			removeTagCacheEntry(entry);
		}
	}

	private void removeTagCacheEntry(TagCacheEntry entry) {
		if (entry.parent == null) {
			// We cannot remove root tag cache entry
			return;
		}
		Map newParentChildren = new HashMap();
		newParentChildren.putAll(entry.parent.children);
		newParentChildren.remove(entry.path.lastSegment());
		entry.parent.children = newParentChildren;
		if (entry.parent.isEmpty()) {
			// remove parents if they no longer carry any value
			removeTagCacheEntry(entry.parent);
		}
	}

	private void removeTagFromChildrenCacheEntries(TagCacheEntry entry,
			CVSTag tag) {
		Iterator childrenIterator = entry.getChildrenIterator();
		while (childrenIterator.hasNext()) {
			TagCacheEntry child = (TagCacheEntry) childrenIterator.next();
			removeTagFromChildrenCacheEntries(child, tag);
			child.getTags().remove(tag);
			if (child.isEmpty()) {
				// remove this entry when the last tag was removed
				// keep the entry if there are any children that have tags
				removeTagCacheEntry(child);
			}
		}
	}
	
	/**
	 * Write out the state of the receiver as XML on the given XMLWriter.
	 * 
	 * @param writer
	 * @throws IOException
	 */
	public void writeState(XMLWriter writer) {

		HashMap attributes = new HashMap();

		attributes.clear();
		attributes.put(RepositoriesViewContentHandler.ID_ATTRIBUTE, root.getLocation(false));
		if (name != null) {
			attributes.put(RepositoriesViewContentHandler.NAME_ATTRIBUTE, name);
		}
		
		writer.startTag(RepositoriesViewContentHandler.REPOSITORY_TAG, attributes, true);

		//put date tag under repository
		if(!dateTags.isEmpty()){
			writer.startTag(RepositoriesViewContentHandler.DATE_TAGS_TAG, attributes, true);
			Iterator iter = dateTags.iterator();
			while(iter.hasNext()){
				CVSTag tag = (CVSTag)iter.next();
				writeATag(writer, attributes, tag, RepositoriesViewContentHandler.DATE_TAG_TAG);
			}
			writer.endTag(RepositoriesViewContentHandler.DATE_TAGS_TAG);
		}
		
		// Gather all the modules that have tags and/or auto-refresh files
		// for each module, write the moduel, tags and auto-refresh files.
		String[] paths = getKnownRemotePaths();
		for (int i = 0; i < paths.length; i++) {
			String path = paths[i];
			attributes.clear();
			String name = path;
			if (isDefinedModuleName(path)) {
				name = getDefinedModuleName(path);
				
				attributes.put(RepositoriesViewContentHandler.TYPE_ATTRIBUTE, RepositoriesViewContentHandler.DEFINED_MODULE_TYPE);
			}
			attributes.put(RepositoriesViewContentHandler.PATH_ATTRIBUTE, name);
			TagCacheEntry entry = getTagCacheEntryFor(path, false);
			boolean writeOutTags = entry != null && !entry.isExpired();
			if (writeOutTags)
			    attributes.put(RepositoriesViewContentHandler.LAST_ACCESS_TIME_ATTRIBUTE, Long.toString(entry.lastAccessTime));
			writer.startTag(RepositoriesViewContentHandler.MODULE_TAG, attributes, true);
			if (writeOutTags) {
				Iterator tagIt = entry.getTags().iterator();
				while (tagIt.hasNext()) {
					CVSTag tag = (CVSTag)tagIt.next();
					writeATag(writer, attributes, tag, RepositoriesViewContentHandler.TAG_TAG);
				}
			}
			Set refreshSet = (Set)autoRefreshFiles.get(path);
			if (refreshSet != null) {
				Iterator filenameIt = refreshSet.iterator();
				while (filenameIt.hasNext()) {
					String filename = (String)filenameIt.next();
					attributes.clear();
					attributes.put(RepositoriesViewContentHandler.FULL_PATH_ATTRIBUTE, filename);
					writer.startAndEndTag(RepositoriesViewContentHandler.AUTO_REFRESH_FILE_TAG, attributes, true);
				}
			}
			writer.endTag(RepositoriesViewContentHandler.MODULE_TAG);
		}
		writer.endTag(RepositoriesViewContentHandler.REPOSITORY_TAG);
	}

    private void writeATag(XMLWriter writer, HashMap attributes, CVSTag tag, String s) {
		attributes.clear();
		attributes.put(RepositoriesViewContentHandler.NAME_ATTRIBUTE, tag.getName());
		attributes.put(RepositoriesViewContentHandler.TYPE_ATTRIBUTE, RepositoriesViewContentHandler.TAG_TYPES[tag.getType()]);
		writer.startAndEndTag(s, attributes, true);
	}

	private void addAllKnownTagsForParents(TagCacheEntry entry, Set tags) {
		if (entry.parent != null) {
			addAllKnownTagsForParents(entry.parent, tags);
		}
		tags.addAll(entry.getTags());
	}

	private void addAllKnownTagsForChildren(TagCacheEntry entry, Set tags) {
		Iterator childrenIterator = entry.getChildrenIterator();
		while (childrenIterator.hasNext()) {
			TagCacheEntry child = (TagCacheEntry) childrenIterator.next();
			addAllKnownTagsForChildren(child, tags);
		}
		tags.addAll(entry.getTags());
	}

	/**
	 * Method getKnownTags.
	 * @param remotePath
	 * @return CVSTag[]
	 */
	public CVSTag[] getAllKnownTags(String remotePath) {
		Set tags = new HashSet(dateTags);
		addAllKnownTagsForParents(getKnownParentTagCacheEntryFor(remotePath),
				tags);
		TagCacheEntry entry = getTagCacheEntryFor(remotePath, false);
		if (entry != null) {
			addAllKnownTagsForChildren(entry, tags);
		}
		return (CVSTag[]) tags.toArray(new CVSTag[tags.size()]);
	}

	public CVSTag[] getAllKnownTags() {
		Set tags = new HashSet(dateTags);
		addAllKnownTagsForChildren(rootTagCacheEntry, tags);
		return (CVSTag[]) tags.toArray(new CVSTag[tags.size()]);
	}

	public String[] getRemoteChildrenForTag(String remotePath, CVSTag tag) {
		TagCacheEntry entry;
		if (remotePath == null) {
			entry = rootTagCacheEntry;
		} else {
			entry = getTagCacheEntryFor(remotePath, false);
		}
		if (entry == null) {
			return new String[0];
		}

		Set paths = new HashSet();
		Iterator childrenIterator = entry.getChildrenIterator();
		while (childrenIterator.hasNext()) {
			TagCacheEntry child = (TagCacheEntry) childrenIterator.next();
			Set childTags = new HashSet();
			addAllKnownTagsForChildren(child, childTags);
			if (childTags.contains(tag)) {
				paths.add(child.path.toString());
			}
		}
		return (String[]) paths.toArray(new String[paths.size()]);
	}

	private Set getKnownRemotePaths(TagCacheEntry entry) {
		Set paths = new HashSet();
		Iterator childrenIterator = entry.getChildrenIterator();
		while (childrenIterator.hasNext()) {
			paths.addAll(getKnownRemotePaths((TagCacheEntry) childrenIterator
					.next()));
		}
		paths.add(entry.path.toString());
		return paths;
	}

	public String[] getKnownRemotePaths() {
		Set paths = getKnownRemotePaths(rootTagCacheEntry);
		paths.addAll(autoRefreshFiles.keySet());
		return (String[]) paths.toArray(new String[paths.size()]);
	}
	/**
	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
	 */
	public Object getAdapter(Class adapter) {
		if (ICVSRepositoryLocation.class.equals(adapter)) return getRoot();
		return super.getAdapter(adapter);
	}
	
	/**
	 * Method tagIsKnown.
	 * @param remoteResource
	 * @return boolean
	 */
	public boolean tagIsKnown(ICVSRemoteResource remoteResource) {
		if (remoteResource instanceof ICVSRemoteFolder) {
			ICVSRemoteFolder folder = (ICVSRemoteFolder) remoteResource;
			String path = folder.getRepositoryRelativePath();
			CVSTag[] tags = getAllKnownTags(path);
			CVSTag tag = folder.getTag();
			for (int i = 0; i < tags.length; i++) {
				CVSTag knownTag = tags[i];
				if (knownTag.equals(tag)) return true;
			}
		}
		return false;
	}
	
	/**
	 * This method is invoked whenever the refresh button in the
	 * RepositoriesView is pressed.
	 */
	void clearCache() {
		synchronized(modulesCacheLock) {
			if (modulesCache != null)
				modulesCache = null;
		}
	}

	/**
	 * Sets the root.
	 * @param root The root to set
	 */
	void setRepositoryLocation(ICVSRepositoryLocation root) {
		this.root = root;
	}

    /*
     * Set the last access time of the cache entry for the given path
     * as it was read from the persistent store.
     */
    /* package */ void setLastAccessedTime(String remotePath, long lastAccessTime) {
		TagCacheEntry entry = getTagCacheEntryFor(remotePath, false);
		if(entry != null){
		    entry.lastAccessTime = lastAccessTime;
		}
    }

}
