Package net.sourceforge.javautil.common.io.impl

Source Code of net.sourceforge.javautil.common.io.impl.Directory

package net.sourceforge.javautil.common.io.impl;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sourceforge.javautil.common.IOUtil;
import net.sourceforge.javautil.common.io.IVirtualArtifact;
import net.sourceforge.javautil.common.io.VirtualArtifactAbstract;
import net.sourceforge.javautil.common.io.VirtualArtifactException;
import net.sourceforge.javautil.common.io.VirtualArtifactNotFoundException;
import net.sourceforge.javautil.common.io.VirtualArtifactSystem;
import net.sourceforge.javautil.common.io.VirtualArtifactWrapped;
import net.sourceforge.javautil.common.io.IVirtualDirectory;
import net.sourceforge.javautil.common.io.VirtualDirectoryAbstract;
import net.sourceforge.javautil.common.io.IVirtualFile;
import net.sourceforge.javautil.common.io.IVirtualPath;

/**
* An implementation allowing any artifacts to be added/removed dynamically pointing to different actual locations.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: Directory.java 2355 2010-07-27 20:25:32Z ponderator $
*/
public abstract class Directory<O extends IVirtualDirectory> extends VirtualDirectoryAbstract {
 
  protected String name;
  protected final O owner;
 
  protected final List<LinkedDirectory> roots = new ArrayList<LinkedDirectory>();
  protected final Map<String, IVirtualArtifact> artifacts = new LinkedHashMap<String, IVirtualArtifact>();
 
  protected long modified = System.currentTimeMillis();
 
  public Directory() { this("", null); }
 
  public Directory(String name) { this(name, null); }
 
  public Directory(String name, O owner) {
    this.name = name;
    this.owner = owner;
  }

  public boolean isReadOnly() { return false; }

  public <T extends IVirtualArtifact> T getArtifact(Class<T> type, IVirtualPath path) {
    try {
      IVirtualArtifact artifact = path == null ? this : this.getArtifact(path);
      if (type.isAssignableFrom(artifact.getClass())) return (T) artifact;
      else if (artifact instanceof VirtualArtifactWrapped) { return (T) ((VirtualArtifactWrapped)artifact).unwrap(type); }
      if (artifact instanceof Directory) return this.resolve(type, (Directory) artifact);
    } catch (VirtualArtifactNotFoundException e) {}
    return null;
  }
 
  protected <T extends IVirtualArtifact> T resolve (Class<T> type, IVirtualFile file) {
    while (true) {
      if (file instanceof LinkedFile) file = ((LinkedFile)file).getDelegate();
      else if (file instanceof DirectoryFileLinked) file = ((DirectoryFileLinked)file).getDelegate();
      else break;
    }
    return type.isAssignableFrom(file.getClass()) ? (T) file : null;
  }
 
  protected <T extends IVirtualArtifact> T resolve (Class<T> type, Directory directory) {
    List<LinkedDirectory> roots = directory.getLinkedRoots();
    if (type == ILinkedArtifact.class && roots.size() > 0) {
      return (T) roots.get(0);
    } else if (ISystemArtifact.class.isAssignableFrom(type) && roots.size() > 0) {
      IVirtualDirectory search = null;
      for (LinkedDirectory root : roots) {
        search = root.getDelegate();
        while (true) {
          if (search instanceof Directory) {
            return this.resolve(type, (Directory) search);
          } else if (search instanceof LinkedDirectory) {
            search = ((LinkedDirectory)search).getDelegate();
          } else
            break;
        }
        if (type.isAssignableFrom(search.getClass())) return (T) search;
      }
    }
    return null;
  }

  public void rename(String newName) {
    if (this.owner != null) {
      this.owner.remove(this.name);
    }
    this.name = newName;

    this.clearCache();
  }
 
  /**
   * @return The root directories linked to this one
   */
  protected List<LinkedDirectory> getLinkedRoots() {
    return this.roots;
  }

  public long getLength() { return artifacts.size(); }

  public URL getURL() {
    SystemDirectory sd = getFirst(this);
    return sd != null ? sd.getURL() : this.createURL();
  }
 
  protected SystemDirectory getFirst (Directory<?> directory) {
    for (LinkedDirectory root : directory.getLinkedRoots()) {
      IVirtualDirectory dir = root.unwrap(SystemDirectory.class);
      if (dir instanceof SystemDirectory) {
        return (SystemDirectory) dir;
      } else if (dir instanceof Directory) {
        SystemDirectory sys = this.getFirst((Directory)dir);
        if (sys != null) return sys;
      }
    }
    return null;
  }

  public long getLastModified() { return this.modified; }
 
  /**
   * @return The linked directories
   */
  public List<LinkedDirectory> getLinkedDirectories () {
    return new ArrayList<LinkedDirectory>( this.getLinkedRoots() );
  }

  public IVirtualArtifact getArtifact(IVirtualPath path) {
    IVirtualArtifact artifact = this;
   
    int idx = 0;
    while (path.getPartCount() > idx && artifact instanceof IVirtualDirectory) {
      if ("".equals(path.getPart(idx))) { idx++; continue; }
     
      artifact = ((IVirtualDirectory)artifact).getArtifact( path.getPart(idx++) );
    }
    if (idx != path.getPartCount()) {
      for (LinkedDirectory linked : this.getLinkedRoots()) {
        try {
          return linked.getArtifact(path);
        } catch (VirtualArtifactNotFoundException e) {}
      }
     
    }
   
    if (artifact == null)
      throw new VirtualArtifactNotFoundException(this, this.getPath().append( path.getParts() ).toString("/") + " does not exist.");
     
    return artifact;
  }
 
  /**
   * This will cause the directory passed to act as part of the root of this directory
   * it's files and sub directories are treated as though they are from the root of this
   * directory.
   *
   * @param root The directory to link as a root
   */
  public void link (IVirtualDirectory root) {
    this.roots.add(new LinkedDirectory(this, root, ""));
  }
 
  /**
   * Unlink a previously linked directory.
   *
   * @param path The path that should match a previously linked directories path
   *
   * @return True if the path was linked and removed, otherwise false
   */
  public boolean unlink (IVirtualPath path) {
    for (LinkedDirectory linked : this.getLinkedRoots()) {
      if (linked.getDelegate().getPath().compareTo(path) == 0) {
        this.roots.remove(linked);
        return true;
      }
    }
    return false;
  }
 
  /**
   * This can be used to remove all directory links to this directory
   */
  public void removeLinks () {
    this.roots.clear();
  }

  /**
   * This assumes the same name as the file
   *
   * @see #link(IVirtualFile, String)
   */
  public DirectoryFileLinked link (IVirtualFile file) { return this.link(file, file.getName()); }
 
  /**
   * This allows any file to be linked to this directory, without having to link another directory
   * to accomplish the same thing.
   *
   * @param file The file to link
   * @param name The name of the link
   *
   * @return A file wrapper representing the link
   */
  public DirectoryFileLinked link (IVirtualFile file, String name) {
    DirectoryFileLinked linked = new DirectoryFileLinked(this, file, name);
    this.artifacts.put(name, linked);
    return linked;
  }

  public IVirtualArtifact getArtifact(String name) {
    IVirtualArtifact artifact = artifacts.get(name);
   
    if (artifact == null) {
      for (LinkedDirectory linked : this.getLinkedRoots()) {
        artifact = linked.getArtifact(name);
        if (artifact != null)
          break;
      }
    }
   
    if (artifact instanceof LinkedDirectory) {
      return this.createDirectory(name);
    }
   
    return artifact;
  }

  public Directory createDirectory(String name) {
    Directory dir = null;
    IVirtualArtifact artifact = this.artifacts.get(name);
    if (artifact instanceof IVirtualFile) {
      throw new VirtualArtifactException(this, "A file already exists by this name: " + name);
    } else if (artifact != null) {
      dir = (Directory) artifact;
    } else {
      SystemDirectory system = this.getFirst(this);
     
      if (system != null && this.isCreateLinkedArtifacts()) { system.createDirectory(name); }
      dir = new DirectoryInternal(name, this);
      this.artifacts.put(name, dir);
    }
    return dir;
  }
 
  /**
   * @return True if created artifacts should also be created in possibly linked {@link ISystemArtifact} targets.
   */
  public abstract boolean isCreateLinkedArtifacts();

  /**
   * This allows more control over linked directory related creations.
   * If there are linked directories to this one then the desired functionality
   * may be that a real file is created. Calls to {@link #createFile(String)}
   * will default to whatever is returned by {@link #isCreateLinkedFiles()}.
   *
   * @param name The name the new file
   * @param real True if a real file should be created in the case there are directories linked to this one
   * @return The new file created
   */
  public IVirtualFile createFile(String name, boolean real) {
    SystemDirectory system = this.getFirst(this);
    return system == null || !real ? new DirectoryFile(name, this) : this.link( system.createFile(name) );
  }

  public IVirtualFile createFile(String name) { return this.createFile(name, this.isCreateLinkedArtifacts()); }
 
  /**
   * @param name The name of the new file
   * @param url The URL that forms the source for input/output for the file
   * @return A new file that will automatically be created in this directory
   */
  public IVirtualFile createFile(String name, URL url) {
    IVirtualFile file = new DirectoryFile(name, this);
    file.setIOHandler(new URLIOHandler(url));
    this.artifacts.put(name, file);
    return file;
  }
 
  public boolean makeDirectories() {
    if (owner != null) return owner.makeDirectories();
   
    return true;
  }

  public boolean makeDirectory() { return true; }

  public boolean remove(String name) { artifacts.remove(name); return true; }

  public Iterator<IVirtualArtifact> getArtifacts() {
    Set<IVirtualArtifact> artifacts = new LinkedHashSet<IVirtualArtifact>(this.artifacts.values());
   
    for (LinkedDirectory root : this.getLinkedRoots()) {
      Iterator<IVirtualArtifact> ra = root.getArtifacts();
      while (ra.hasNext()) {
        IVirtualArtifact artifact = ra.next();
       
        if (artifact instanceof LinkedDirectory) {
          artifacts.add(this.getDirectory(artifact.getName(), true));
        } else
          artifacts.add(artifact);
      }
    }
   
    return artifacts.iterator();
  }

  public String getName() { return name; }

  public IVirtualDirectory getOwner() { return owner; }

  public boolean isExists() { return true; }
 
  public boolean remove() {
    if (this.owner != null)
      return this.owner.remove(this.name);
    return true;
  }

  public String toString () { return (owner == null ? "Root" : owner) + ("".equals(name) ? "" : ("->[" + name + "]")); }

}
TOP

Related Classes of net.sourceforge.javautil.common.io.impl.Directory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.