package net.oni2.aeinstaller.backend.packages; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.TreeSet; import java.util.Vector; import net.oni2.aeinstaller.backend.Paths; import net.oni2.aeinstaller.backend.oni.management.ModInstallationList; import net.oni2.aeinstaller.backend.oni.management.tools.ToolInstallationList; import net.oni2.moddepot.DepotManager; import net.oni2.moddepot.model.NodeMod; import net.oni2.moddepot.model.TaxonomyTerm; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStreamException; import com.thoughtworks.xstream.io.xml.StaxDriver; /** * @author Christian Illy */ public class PackageManager { private static PackageManager instance = new PackageManager(); private HashMap types = new HashMap(); private HashMap mods = new HashMap(); private HashMap tools = new HashMap(); private Type localType = null; /** * @param f * Mod selection file * @return Mod selection */ @SuppressWarnings("unchecked") public Vector loadModSelection(File f) { Vector res = new Vector(); try { if (f.exists()) { FileInputStream fis = new FileInputStream(f); XStream xs = new XStream(new StaxDriver()); Object obj = xs.fromXML(fis); if (obj instanceof Vector) res = (Vector) obj; fis.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return res; } /** * @param f * Mod selection file * @param mods * Selected mods */ public void saveModSelection(File f, TreeSet mods) { try { Vector installed = new Vector(); for (Package m : mods) { installed.add(m.getPackageNumber()); } FileOutputStream fos = new FileOutputStream(f); XStream xs = new XStream(new StaxDriver()); xs.toXML(installed, fos); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * First initialization of ModManager */ public void init() { types = new HashMap(); mods = new HashMap(); localType = new Type("-Local-"); types.put("-Local-", localType); for (TaxonomyTerm tt : DepotManager.getInstance().getTypes()) { types.put(tt.getName(), new Type(tt.getName())); } for (NodeMod nm : DepotManager.getInstance().getModPackageNodes()) { if (nm.getUploads().size() == 1) { Package m = new Package(nm); if (nm.isTool()) tools.put(m.getPackageNumber(), m); else mods.put(m.getPackageNumber(), m); } } updateLocalData(); } /** * @return Singleton instance */ public static PackageManager getInstance() { return instance; } Type getTypeByName(String name) { return types.get(name); } /** * @return Collection of types which do have mods associated */ public Collection getTypesWithContent() { Vector res = new Vector(); for (Type t : types.values()) { if (t.getEntries().size() > 0) res.add(t); } return res; } /** * @return Collection of mods valid on this platform and not core package */ public Collection getModsValidAndNotCore() { Vector res = new Vector(); for (Package m : mods.values()) if (m.isValidOnPlatform() && !m.isCorePackage()) res.add(m); return res; } /** * @return Mods which are always installed and valid on this platform */ public TreeSet getCoreMods() { TreeSet res = new TreeSet(); for (Package m : mods.values()) { if (m.isValidOnPlatform() && m.isCorePackage()) res.add(m); } return res; } /** * @return Mods which are already locally available */ public TreeSet getLocalAvailableMods() { TreeSet res = new TreeSet(); for (Package m : mods.values()) { if (m.isLocalAvailable()) res.add(m); } return res; } /** * @return Mods which can be updated */ public TreeSet getUpdatableMods() { TreeSet res = new TreeSet(); for (Package m : getLocalAvailableMods()) { if (m.isNewerAvailable()) res.add(m); } return res; } /** * @return Currently installed mods */ public TreeSet getInstalledMods() { TreeSet res = new TreeSet(); for (int n : ModInstallationList.getInstance().getInstalledMods()) { res.add(getPackageByNumber(n)); } return res; } /** * @return Collection of tools valid on this platform and not core */ public Collection getTools() { Vector res = new Vector(); for (Package m : tools.values()) if (m.isValidOnPlatform() && !m.isCorePackage()) res.add(m); return res; } /** * @return Tools which are always installed and valid on this platform */ public TreeSet getCoreTools() { TreeSet res = new TreeSet(); for (Package m : tools.values()) { if (m.isValidOnPlatform() && m.isCorePackage()) res.add(m); } return res; } /** * @return Tools which are already locally available */ public TreeSet getLocalAvailableTools() { TreeSet res = new TreeSet(); for (Package m : tools.values()) { if (m.isLocalAvailable()) res.add(m); } return res; } /** * @return Tools which can be updated */ public TreeSet getUpdatableTools() { TreeSet res = new TreeSet(); for (Package m : getLocalAvailableTools()) { if (m.isNewerAvailable()) res.add(m); } return res; } /** * @return Currently installed tools */ public TreeSet getInstalledTools() { TreeSet res = new TreeSet(); for (int n : ToolInstallationList.getInstance().getItems().keySet()) { res.add(getPackageByNumber(n)); } return res; } /** * Get a mod/tool by its package number * * @param number * Package number * @return Mod/tool or null */ private Package getPackageByNumber(int number) { if (mods.containsKey(number)) return mods.get(number); if (tools.containsKey(number)) return tools.get(number); return null; } /** * Check for unresolved dependencies within the given mods * * @param mods * Mods to check * @return Unmet dependencies */ public HashMap> checkDependencies( TreeSet mods) { HashMap> res = new HashMap>(); for (Package m : mods) { for (int depNum : m.getDependencies()) { Package other = getPackageByNumber(depNum); if (other != null) { if (!mods.contains(other)) { if (!res.containsKey(m)) res.put(m, new HashSet()); res.get(m).add(other); } } } } return res; } /** * Check for incompabitilites between given mods * * @param mods * Mods to check * @return Incompatible mods */ public HashMap> checkIncompabitilites( TreeSet mods) { HashMap> res = new HashMap>(); for (Package m : mods) { for (int confNum : m.getIncompabitilities()) { Package other = getPackageByNumber(confNum); if (other != null) { if (mods.contains(other)) { if (!res.containsKey(m)) res.put(m, new HashSet()); res.get(m).add(other); } } } } return res; } /** * @param m * Mod to check * @return Is mod installed? */ boolean isModInstalled(Package m) { return ModInstallationList.getInstance().isInstalled( m.getPackageNumber()); } /** * Rescan local packages folder for local only packages and updated * Mod_Info.cfg */ public void updateLocalData() { if (Paths.getModsPath().exists()) { for (File f : Paths.getModsPath().listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory(); } })) { Package m = new Package(f); HashMap map = null; if (m.isTool()) map = tools; else map = mods; if (!map.containsKey(m.getPackageNumber())) { map.put(m.getPackageNumber(), m); if (!m.isCorePackage()) { localType.addEntry(m); m.getTypes().add(localType); } } } } for (Package p : mods.values()) { p.updateLocalData(); } for (Package p : tools.values()) { p.updateLocalData(); } } private static XStream getXStream() { XStream xs = new XStream(new StaxDriver()); xs.alias("Packages", PackageManager.class); xs.alias("Type", Type.class); xs.alias("Package", Package.class); return xs; } /** * Save Depot cache instance to file * * @param cacheFile * File to save to */ public void saveToCacheFile(java.io.File cacheFile) { try { FileOutputStream fos = new FileOutputStream(cacheFile); XStream xs = getXStream(); xs.toXML(this, fos); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * Load cache from file * * @param cacheFile * File to load */ public static void loadFromCacheFile(java.io.File cacheFile) { try { FileInputStream fis = new FileInputStream(cacheFile); XStream xs = getXStream(); Object obj = xs.fromXML(fis); fis.close(); if (obj instanceof PackageManager) { instance = (PackageManager) obj; instance.updateLocalData(); } } catch (XStreamException e) { } catch (FileNotFoundException e) { } catch (IOException e) { } } }