Package com.cburch.logisim.file

Source Code of com.cburch.logisim.file.LibraryManager$LogisimProjectDescriptor

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.file;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.WeakHashMap;

import com.cburch.logisim.tools.Library;
import com.cburch.logisim.util.StringUtil;

class LibraryManager {
  public static final LibraryManager instance = new LibraryManager();

  private static char desc_sep = '#';
 
  private static abstract class LibraryDescriptor {
    abstract boolean concernsFile(File query);
    abstract String toDescriptor(Loader loader);
    abstract void setBase(Loader loader, LoadedLibrary lib)
      throws LoadFailedException;
  }
 
  private static class LogisimProjectDescriptor extends LibraryDescriptor {
    private File file;
   
    LogisimProjectDescriptor(File file) {
      this.file = file;
    }
   
    @Override
    boolean concernsFile(File query) {
      return file.equals(query);
    }
   
    @Override
    String toDescriptor(Loader loader) {
      return "file#" + toRelative(loader, file);
    }
   
    @Override
    void setBase(Loader loader, LoadedLibrary lib) throws LoadFailedException {
      lib.setBase(loader.loadLogisimFile(file));
    }
   
    @Override
    public boolean equals(Object other) {
      if (!(other instanceof LogisimProjectDescriptor)) return false;
      LogisimProjectDescriptor o = (LogisimProjectDescriptor) other;
      return this.file.equals(o.file);
    }
   
    @Override
    public int hashCode() {
      return file.hashCode();
    }
  }
 
  private static class JarDescriptor extends LibraryDescriptor {
    private File file;
    private String className;
   
    JarDescriptor(File file, String className) {
      this.file = file;
      this.className = className;
    }
   
    @Override
    boolean concernsFile(File query) {
      return file.equals(query);
    }

    @Override
    String toDescriptor(Loader loader) {
      return "jar#" + toRelative(loader, file) + desc_sep + className;
    }
   
    @Override
    void setBase(Loader loader, LoadedLibrary lib) throws LoadFailedException {
      lib.setBase(loader.loadJarFile(file, className));
    }
   
    @Override
    public boolean equals(Object other) {
      if (!(other instanceof JarDescriptor)) return false;
      JarDescriptor o = (JarDescriptor) other;
      return this.file.equals(o.file) && this.className.equals(o.className);
    }
   
    @Override
    public int hashCode() {
      return file.hashCode() * 31 + className.hashCode();
    }
  }
 
  private HashMap<LibraryDescriptor,WeakReference<LoadedLibrary>> fileMap;
  private WeakHashMap<LoadedLibrary,LibraryDescriptor> invMap;

  private LibraryManager() {
    fileMap = new HashMap<LibraryDescriptor,WeakReference<LoadedLibrary>>();
    invMap = new WeakHashMap<LoadedLibrary,LibraryDescriptor>();
    ProjectsDirty.initialize();
  }
 
  void setDirty(File file, boolean dirty) {
    LoadedLibrary lib = findKnown(file);
    if (lib != null) {
      lib.setDirty(dirty);
    }
  }
 
  Collection<LogisimFile> getLogisimLibraries() {
    ArrayList<LogisimFile> ret = new ArrayList<LogisimFile>();
    for (LoadedLibrary lib : invMap.keySet()) {
      if (lib.getBase() instanceof LogisimFile) {
        ret.add((LogisimFile) lib.getBase());
      }
    }
    return ret;
  }

  public Library loadLibrary(Loader loader, String desc) {
    // It may already be loaded.
    // Otherwise we'll have to decode it.
    int sep = desc.indexOf(desc_sep);
    if (sep < 0) {
      loader.showError(StringUtil.format(Strings.get("fileDescriptorError"), desc));
      return null;
    }
    String type = desc.substring(0, sep);
    String name = desc.substring(sep + 1);

    if (type.equals("")) {
      Library ret = loader.getBuiltin().getLibrary(name);
      if (ret == null) {
        loader.showError(StringUtil.format(Strings.get("fileBuiltinMissingError"), name));
        return null;
      }
      return ret;
    } else if (type.equals("file")) {
      File toRead = loader.getFileFor(name, Loader.LOGISIM_FILTER);
      return loadLogisimLibrary(loader, toRead);
    } else if (type.equals("jar")) {
      int sepLoc = name.lastIndexOf(desc_sep);
      String fileName = name.substring(0, sepLoc);
      String className = name.substring(sepLoc + 1);
      File toRead = loader.getFileFor(fileName, Loader.JAR_FILTER);
      return loadJarLibrary(loader, toRead, className);
    } else {
      loader.showError(StringUtil.format(Strings.get("fileTypeError"),
        type, desc));
      return null;
    }
  }
 
  public LoadedLibrary loadLogisimLibrary(Loader loader, File toRead) {
    LoadedLibrary ret = findKnown(toRead);
    if (ret != null) return ret;
   
    try {
      ret = new LoadedLibrary(loader.loadLogisimFile(toRead));
    } catch (LoadFailedException e) {
      loader.showError(e.getMessage());
      return null;
    }
   
    LogisimProjectDescriptor desc = new LogisimProjectDescriptor(toRead);
    fileMap.put(desc, new WeakReference<LoadedLibrary>(ret));
    invMap.put(ret, desc);
    return ret;
  }
 
  public LoadedLibrary loadJarLibrary(Loader loader, File toRead, String className) {
    JarDescriptor jarDescriptor = new JarDescriptor(toRead, className);
    LoadedLibrary ret = findKnown(jarDescriptor);
    if (ret != null) return ret;

    try {
      ret = new LoadedLibrary(loader.loadJarFile(toRead, className));
    } catch (LoadFailedException e) {
      loader.showError(e.getMessage());
      return null;
    }
   
    fileMap.put(jarDescriptor, new WeakReference<LoadedLibrary>(ret));
    invMap.put(ret, jarDescriptor);
    return ret;
  }
 
  public void reload(Loader loader, LoadedLibrary lib) {
    LibraryDescriptor descriptor = invMap.get(lib);
    if (descriptor == null) {
      loader.showError(StringUtil.format(Strings.get("unknownLibraryFileError"),
          lib.getDisplayName()));
    } else {
      try {
        descriptor.setBase(loader, lib);
      } catch (LoadFailedException e) {
        loader.showError(e.getMessage());
      }
    }
  }
 
  public Library findReference(LogisimFile file, File query) {
    for (Library lib : file.getLibraries()) {
      LibraryDescriptor desc = invMap.get(lib);
      if (desc != null && desc.concernsFile(query)) {
        return lib;
      }
      if (lib instanceof LoadedLibrary) {
        LoadedLibrary loadedLib = (LoadedLibrary) lib;
        if (loadedLib.getBase() instanceof LogisimFile) {
          LogisimFile loadedProj = (LogisimFile) loadedLib.getBase();
          Library ret = findReference(loadedProj, query);
          if (ret != null) return lib;
        }
      }
    }
    return null;
  }
 
  public void fileSaved(Loader loader, File dest, File oldFile, LogisimFile file) {
    LoadedLibrary old = findKnown(oldFile);
    if (old != null) {
      old.setDirty(false);
    }
   
    LoadedLibrary lib = findKnown(dest);
    if (lib != null) {
      LogisimFile clone = file.cloneLogisimFile(loader);
      clone.setName(file.getName());
      clone.setDirty(false);
      lib.setBase(clone);
    }
  }

  public String getDescriptor(Loader loader, Library lib) {
    if (loader.getBuiltin().getLibraries().contains(lib)) {
      return desc_sep + lib.getName();
    } else {
      LibraryDescriptor desc = invMap.get(lib);
      if (desc != null) {
        return desc.toDescriptor(loader);
      } else {
        throw new LoaderException(StringUtil.format(
            Strings.get("fileDescriptorUnknownError"), lib.getDisplayName()));
      }
    }
  }

  private LoadedLibrary findKnown(Object key) {
    WeakReference<LoadedLibrary> retLibRef;
    retLibRef = fileMap.get(key);
    if (retLibRef == null) {
      return null;
    } else {
      LoadedLibrary retLib = retLibRef.get();
      if (retLib == null) {
        fileMap.remove(key);
        return null;
      } else {
        return retLib;
      }
    }
  }
 
  private static String toRelative(Loader loader, File file) {
    File currentDirectory = loader.getCurrentDirectory();
    if (currentDirectory == null) {
      try {
        return file.getCanonicalPath();
      } catch (IOException e) {
        return file.toString();
      }
    }

    File fileDir = file.getParentFile();
    if (fileDir != null) {
      if (currentDirectory.equals(fileDir)) {
        return file.getName();
      } else if (currentDirectory.equals(fileDir.getParentFile())) {
        return fileDir.getName() + "/" + file.getName();
      } else if (fileDir.equals(currentDirectory.getParentFile())) {
        return "../" + file.getName();
      }
    }
    try {
      return file.getCanonicalPath();
    } catch (IOException e) {
      return file.toString();
    }
  }
}
TOP

Related Classes of com.cburch.logisim.file.LibraryManager$LogisimProjectDescriptor

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.