Browse Source

st backup before stipping old code from WPCMgr

LH 8 years ago
parent
commit
bcafa2a3f6
24 changed files with 2581 additions and 1412 deletions
  1. 627 627
      ToolKit/src/main/java/de/nplusc/izc/tools/IOtools/FileTK.java
  2. 190 191
      ToolKit/src/main/java/de/nplusc/izc/tools/baseTools/Detectors.java
  3. 1 1
      WPCMGr/build.gradle
  4. 65 0
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/CacheState.java
  5. 39 0
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Constants.java
  6. 55 55
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Main.java
  7. 85 0
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/PackageState.java
  8. 43 0
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/ResultWallpaper.java
  9. 27 23
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Screen.java
  10. 88 0
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/ScreenStrip.java
  11. 525 10
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Synchronizer.java
  12. 193 36
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/WPCUtils.java
  13. 86 0
      WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Wallpaper.java
  14. 2 2
      WPCMGr/src/main/resources/log4j2.xml
  15. 92 82
      external/java-progressbar/src/main/java/hu/ssh/progressbar/AbstractProgressBar.java
  16. 49 42
      external/java-progressbar/src/main/java/hu/ssh/progressbar/Progress.java
  17. 196 192
      external/java-progressbar/src/main/java/hu/ssh/progressbar/console/ConsoleProgressBar.java
  18. 38 0
      external/java-progressbar/src/main/java/hu/ssh/progressbar/console/replacers/MessageReplacer.java
  19. 30 30
      external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestBarReplacer.java
  20. 31 31
      external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestElapsedTimeReplacer.java
  21. 29 0
      external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestMessageReplacer.java
  22. 30 30
      external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestPercentageReplacer.java
  23. 30 30
      external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestRemainingTimeReplacer.java
  24. 30 30
      external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestTotalTimeReplacer.java

+ 627 - 627
ToolKit/src/main/java/de/nplusc/izc/tools/IOtools/FileTK.java

@@ -1,627 +1,627 @@
-/*
- * Copyright (C) 2015 iZc
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package de.nplusc.izc.tools.IOtools;
-
-import de.nplusc.izc.tools.baseTools.Tools;
-import java.io.*;
-import java.nio.CharBuffer;
-import java.nio.channels.FileChannel;
-import java.util.ArrayList;
-import java.util.Arrays;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-/**
- *
- * @author LH
- */
-public class FileTK
-{
-    
-    private static final Logger l = LogManager.getLogger();
-    protected FileTK()
-    {
-    }
-
-    /**
-     * Erzeugt die Verzeichnisse die nötig sind um das File zuspeichern
-     *
-     * @param f File zum abarbeiten
-     */
-    public static void ensuredirExistence(File f)
-    {
-        File fp = f.getParentFile();
-        if (!fp.exists())
-        {
-            fp.mkdirs();
-        }
-    }
-
-    /**
-     * Erzeugt die Verzeichnisse die nötig sind um das File zuspeichern
-     *
-     * @param path Path zum abarbeiten
-     */
-    public static void ensuredirExistence(String path)
-    {
-        ensuredirExistence(new File(path));
-    }
-
-    /**
-     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
-     * darunterliegende auf(begrenzt auf 40 Ebenen)
-     *
-     * @param path WO begonnen werden soll
-     * @return Liste der Pfae
-     */
-    public static String[] walkDirectoryRecursively(String path)
-    {
-        return walkDirectoryRecursively(path, 40);
-    }
-
-    /**
-     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
-     * darunterliegende auf(begrenzt auf 40 Ebenen)
-     *
-     * @param path WO begonnen werden soll
-     * @param verbose Geschwätzig?
-     * @return Liste der Pfae
-     */
-    public static String[] walkDirectoryRecursively(String path, boolean verbose)
-    {
-        return walkDirectoryRecursively(path, 40, verbose);
-    }
-
-    
-    
-    
-    
-    
-    /**
-     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
-     * darunterliegende auf
-     *
-     * @param path WO begonnen werden soll
-     * @param recurseDepth Wieviele ebenen
-     * @return Liste der Pfae
-     */
-    public static String[] walkDirectoryRecursively(String path, int recurseDepth)
-    {
-        return walkDirectoryRecursively(path, recurseDepth, false);
-    }
-
-    /**
-     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
-     * darunterliegende auf
-     *
-     * @param path WO begonnen werden soll
-     * @param recurseDepth Wieviele ebenen
-     * @param verbose Geschwätzig?
-     * @return Liste der Pfae
-     */
-    public static String[] walkDirectoryRecursively(String path, int recurseDepth, boolean verbose)
-    {
-        //if(verbose)
-        //System.out.print("cls\r\n");//DOESNTWORK:(
-        ArrayList<String> data = new ArrayList<>();
-        int length = 0;
-        String[] DirCnt = getDirectoryContent(path);
-        if(DirCnt==null)
-        {
-            return new String[]{};
-        }
-        for (String string : DirCnt)
-        {
-            File f = new File(string);
-            if (f.isDirectory())
-            {
-                if (verbose)
-                {
-                    //System.console().
-                    /*String s2 = "";//Satz mit X war wohl nix
-                    while(s2.length()<length)
-                    {
-                        s2+="\b";//weigert sich ne zeile nauf zu gehren
-                    }
-                    System.out.print(s2);
-                    System.console().writer().append(s2);*/
-                    String s = "\rReading in:" + f.getPath();
-                    //NOLOG
-                    System.out.print(s);
-                    /*try //abgekrachte FLiegenklatsche
-                    {
-                        Thread.sleep(20);
-                    }
-                    catch (InterruptedException ex)
-                    {
-                        ex.printStackTrace();
-                    }
-                            */
-                    if(s.length()>length)
-                    {
-                        length = s.length();
-                    }
-                    else
-                    {
-                        while(s.length()<length)
-                        {
-                            s+=" ";//auffüllen auf gewünschte länge....
-                        }
-                    }
-                 //   System.out.print((char)0x1b+"[u");//DOESNTWORK
-                }
-                String[] sdc = walkDirectoryRecursively(string, recurseDepth - 1,verbose);
-                data.add(string);
-                data.addAll(Arrays.asList(sdc));
-            }
-            else
-            {
-            data.add(string);
-            }
-        }
-        String[] s = new String[]
-        {
-            ""
-        };
-        return data.toArray(s);
-    }
-
-    /**
-     * Liest Dateiname mit Erweiterung aus
-     * @param path Pfad derDatei
-     * @return Dateiname ohne Pfad
-     */
-    
-    public static String getFileName(String path)
-    {
-        //String ft1 = FileTK.getFilePath(path);
-        String ft2 = path.substring(path.lastIndexOf("\\")+1);
-        return ft2;
-    }
-    
-    /**
-     * Liest dateiendung aus
-     *
-     * @param path Dateipfad zumauslesen
-     * @return dateiendung in lowercase
-     */
-    public static String getFileExt(String path)
-    {
-        String ext = null;
-        int i = path.lastIndexOf('.');
-
-        if (i > 0 && i < path.length() - 1)
-        {
-            ext = path.substring(i + 1).toLowerCase();
-        }
-        return ext;
-        /*
-         String[] splitpath = path.split(".");
-         String ret = null;
-         if(splitpath.length>1)
-         {
-         ret = splitpath[splitpath.length-1];
-         }
-         return ret;*/
-    }
-
-    /**
-     * Gibt Ordnerpfad netr datei aus
-     *
-     * @param path Dateiname/pfd
-     * @return Ordner der Datei
-     */
-    public static String getFilePath(String path)
-    {
-        path = new File(path).getAbsolutePath();//falls nen relativer Pfad verwendet wurde
-        String ext = path;
-        int i = path.lastIndexOf("\\");
-
-        if (i > 0 && i < path.length())
-        {
-            ext = path.substring(0, i);
-        }
-        return ext;
-    }
-
-    /*private static void log(String line)
-    {
-        Tools.DebugHelperPrint(line, true, "Toolkit.enableCoreDebug");
-    }*/
-
-    /**
-     * Lädt Datei in String-array
-     *
-     * @param path Dateipfad
-     * @return ZEilenweises Array der Datei
-     */
-    @SuppressWarnings("ConvertToTryWithResources")
-    public static String[] fileload(String path)
-    {
-        return fileload(path, true);
-    }
-
-    /**
-     * Lädt Datei in String-array
-     *
-     * @param path Dateipfad
-     * @param eofmark unbenutzt (zu fixen wegen bug)
-     * @return ZEilenweises Array der Datei
-     */
-    @SuppressWarnings("ConvertToTryWithResources")
-    public static String[] fileload(String path, boolean eofmark)//bugfix noch zu erledigen
-    {
-        String filedata = "";
-        String[] filecnt;
-        try
-        {
-            FileReader fr = new FileReader(path);
-            BufferedReader br = new BufferedReader(fr);
-            filedata = br.readLine() + "\n";
-            String zeile = "x";
-            while (zeile != null)
-            {
-                l.trace(zeile);
-                zeile = br.readLine();
-                filedata = filedata + zeile + "\n";
-            }
-            filecnt = filedata.split("\n");
-            fr.close();
-        }
-        catch (Exception ioe)
-        {
-            //log("Failed to load FIle:unknown error. Something f@ild.");
-            l.info("noncritical internal error. Ignored");
-            l.info("@:"+new File(path).getAbsolutePath());
-            //ioe.printStackTrace();
-            filecnt = new String[1];
-            filecnt[0] = "LMAA";
-        }
-        l.trace(filedata);
-        return filecnt;
-    }
-
-    /**
-     * Speichert Datei(überschreibend)
-     *
-     * @param cnt Inhalt
-     * @param path Wohin
-     */
-    public static void writeFile(String cnt, String path)
-    {
-        writeFile(cnt, path, false);
-    }
-
-    /**
-     * Speichert Datei
-     *
-     * @param cnt Inhalt
-     * @param path Wohin
-     * @param app Anfügen?
-     */
-    @SuppressWarnings("CallToThreadDumpStack")
-    public static void writeFile(String cnt, String path, boolean app)
-    {
-        
-        FileWriter fw = null;
-        try
-        {
-            new File(path).createNewFile();
-            fw = new FileWriter(path);
-            if (!app)
-            {
-                fw.write(cnt);
-            }
-            else
-            {
-                int size = (int) new File(path).length();
-                fw.write(path, size, cnt.length());
-            }
-        }
-        catch (IOException e)
-        {
-            l.warn("Konnte Datei nicht erstellen");
-            e.printStackTrace();
-        }
-        finally
-        {
-            if (fw != null)
-            {
-                try
-                {
-                    fw.close();
-                }
-                catch (IOException e)
-                {
-                }
-            }
-        }
-    }
-
-    /**
-     * Prüft auf existenz ner datei/Verzeichnis
-     *
-     * @param path Was
-     * @return Obs existiert
-     */
-    public static boolean checkDirExist(String path)
-    {
-        File f = new File(path);
-        if (!f.exists())
-        {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * entspricht dir von der cmd
-     *
-     * @param path Wo
-     * @return Array der dateien innerhalb
-     */
-    public static String[] getDirectoryContent(String path)
-    {
-        return getDirectoryContent(path,false);
-    }
-        /**
-     * entspricht dir von der cmd
-     *
-     * @param path Wo
-     * @param skipPrePath ob nur die t dateinamen kommen sollen;
-     * @return Array der dateien innerhalb
-     */
-    public static String[] getDirectoryContent(String path,boolean skipPrePath)
-    {
-        File f = new File(path);
-        File[] dirtmpf = f.listFiles();
-        //String[] dirtmp = new String[] d
-        l.info("Pfad={}",path);
-        String[] ret = null;
-        try
-        {
-            ret = new String[dirtmpf.length];
-
-            int j;
-            for (int i = 0; i < dirtmpf.length; i++)
-            {
-                j = i;
-                String tmp = dirtmpf[i].getPath();
-                if (!(tmp.length() < path.length()))
-                {
-                    
-                    ret[j] = tmp;
-                    if(skipPrePath)
-                    {
-                        ret[j] = getFileName(tmp);
-                    }
-                    
-                    
-                    //j++;
-                }
-
-            }
-        }
-        catch (NullPointerException e)
-        {
-
-            ret = new String[0];
-            l.trace("LMAA|{}",path);
-        }
-        return ret;
-    }
-
-    /**
-     * Erzeugt den relativen Pfad einer datei/eines Ordners zu eienm Basispfad
-     *
-     * @param absolutePath Pfad von dem relativer Pfad zu
-     * @param basePath diesem ermittelt werden soll
-     * @return der relative Pfad
-     */
-    public static String getRelativePath(String absolutePath, String basePath)//Initializer für Hack!
-    {
-        absolutePath = absolutePath.replace("/", "\\");
-        basePath = basePath.replace("/", "\\");
-        String rpath = getRelativePath(absolutePath, basePath, 0);
-        return rpath==null?rpath:rpath.replace("\\", File.separator);
-    }
-
-    private static String getRelativePath(String absolutePath, String basePath, int recurses)//Fetter Hack wegen fehkendem Java-Befehl!
-    {
-        String replace = null, unRegex = null, internalPath = "", parsedPath = "";
-        boolean err = false;
-        
-        if (absolutePath != null || basePath != null)
-        {
-
-            if (recurses > 0)
-            {
-                try
-                {
-                    String pathSplit[] = basePath.split("\\\\");
-                    Object[] psplit = Tools.truncateArray(pathSplit, 1, true);
-                    for (Object o : psplit)
-                    {
-                        internalPath += o + "\\";
-                    }
-                    //entfernt das letze element des pfades
-                    //BSP: C:\pfad\zu\krempel\killme  -> C:\pfad\zu\krempel
-                    //Kilme wird entfernt
-                    
-                    String replaceTemp = "";
-                    for (int i = 0; i < recurses; i++)//recurses gibt an wievile ebenen er rauf ist
-                    {
-                        replaceTemp += "\\.\\.\\\\"; //  ..\ so oft wie der parser den baum raufgewandert ist
-                    }
-                    replace = "\\.\\\\" + replaceTemp; //beginnt pfad mit .\ und dann soviele ..\-s wie nötig
-                    unRegex = internalPath.replaceAll("\\\\", "\\\\\\\\"); // \ -> \\
-                   l.trace("Aha");
-                }
-                catch (Exception ex)
-                {
-                    err = true;
-                    l.trace("FickDich");
-                }
-
-
-            }
-            else
-            {
-                internalPath = basePath;
-                replace = "\\.\\\\";
-                unRegex = basePath.replaceAll("\\\\", "\\\\\\\\"); // \ -> \\
-            }
-
-            parsedPath = absolutePath.replaceAll(unRegex, replace);// basePath -> .\ haut den gemeinsamen teil raus und fügt den relativteil an
-            l.info("ParsedPath={}",parsedPath);
-            if (parsedPath.equals(absolutePath))
-            {
-                //basePath=internalPath;
-                recurses++;
-                String parsedPath2 = null;
-                //absolutePath = absolutePath.replaceAll("\\\\", "\\\\\\\\");
-                try
-                {
-                    parsedPath2 = getRelativePath(absolutePath, internalPath, recurses);
-                }
-                catch (Exception ex)
-                {
-                    l.trace("Arschfotze");
-                }
-                if (parsedPath2 != null)
-                {
-                    parsedPath = parsedPath2;
-                }
-            }
-        }
-        else
-        {
-            err = false;
-        }
-        if (err == true)
-        {
-            parsedPath = null;
-        }
-        
-        return parsedPath;
-    }
-    /**
-     * Fatei kopieren
-     * Code ist ausm netz: http://www.javabeginners.de/Dateien_und_Verzeichnisse/Eine_Datei_kopieren.php
-     * @param in Eingabefile
-     * @param out Ausgabefile
-     * @throws IOException 
-     */
-    
-    public static void kopierpaste(File in, File out) //throws IOException
-    {
-        FileChannel inChannel=null,outChannel=null;
-        try
-        {
-        inChannel = new FileInputStream(in).getChannel();
-        outChannel = new FileOutputStream(out).getChannel();
-
-
-
-            inChannel.transferTo(0, inChannel.size(), outChannel);
-        }
-        catch (IOException e)
-        {
-            e.printStackTrace();
-            l.error("Kopiererei geerrort");
-          //  throw e;
-        }
-        finally
-        {
-            if (inChannel != null)
-            {
-                try
-                {
-                    inChannel.close();
-                }
-                catch (IOException ex)
-                {
-                    ex.printStackTrace();
-                }
-            }
-            if (outChannel != null)
-            {
-                try
-                {
-                    outChannel.close();
-                }
-                catch (IOException ex)
-                {
-                    ex.printStackTrace();
-                }
-            }
-        }
-    }
-        
-    /**
-     * Checkt ob pfad nen verzeichnis sit
-     * @param path welcher pfad
-     * @return ja/nein
-     */
-    public static boolean isDir(String path)
-    {
-        return new File(path).isDirectory();
-    }
-    
-    /**
-     * Schrubbt verzeichnis rekursiv raus;
-     * @param path welches dir
-     */
-    
-    public static void verzeichnisKillen(File path)
-    {
-        if(path.exists())
-        {
-            for (File file : path.listFiles())
-            {
-                if (file.isDirectory())
-                {
-                    verzeichnisKillen(file);
-                }
-                file.delete();
-            }
-            path.delete();
-        }
-    }
-    
-    
-    public static String fileAsString(String path) throws FileNotFoundException, IOException
-    {
-        return fileAsString(new File(path));
-    }
-    
-    public static String fileAsString(File path) throws FileNotFoundException, IOException
-    {
-            if(path.length()>Integer.MAX_VALUE)
-            {
-                throw new IOException(" File too large for specified operation");
-            }
-            FileReader fr = new FileReader(path);
-            CharBuffer c = CharBuffer.allocate((int)path.length());
-            fr.read(c);
-            c.rewind();
-            l.trace(path.length()+"|"+c.length());
-            return c.toString();
-    }
-    
-}
+/*
+ * Copyright (C) 2015 iZc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.nplusc.izc.tools.IOtools;
+
+import de.nplusc.izc.tools.baseTools.Tools;
+import java.io.*;
+import java.nio.CharBuffer;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ *
+ * @author LH
+ */
+public class FileTK
+{
+    
+    private static final Logger l = LogManager.getLogger();
+    protected FileTK()
+    {
+    }
+
+    /**
+     * Erzeugt die Verzeichnisse die nötig sind um das File zuspeichern
+     *
+     * @param f File zum abarbeiten
+     */
+    public static void ensuredirExistence(File f)
+    {
+        File fp = f.getParentFile();
+        if (!fp.exists())
+        {
+            fp.mkdirs();
+        }
+    }
+
+    /**
+     * Erzeugt die Verzeichnisse die nötig sind um das File zuspeichern
+     *
+     * @param path Path zum abarbeiten
+     */
+    public static void ensuredirExistence(String path)
+    {
+        ensuredirExistence(new File(path));
+    }
+
+    /**
+     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
+     * darunterliegende auf(begrenzt auf 40 Ebenen)
+     *
+     * @param path WO begonnen werden soll
+     * @return Liste der Pfae
+     */
+    public static String[] walkDirectoryRecursively(String path)
+    {
+        return walkDirectoryRecursively(path, 40);
+    }
+
+    /**
+     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
+     * darunterliegende auf(begrenzt auf 40 Ebenen)
+     *
+     * @param path WO begonnen werden soll
+     * @param verbose Geschwätzig?
+     * @return Liste der Pfae
+     */
+    public static String[] walkDirectoryRecursively(String path, boolean verbose)
+    {
+        return walkDirectoryRecursively(path, 40, verbose);
+    }
+
+    
+    
+    
+    
+    
+    /**
+     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
+     * darunterliegende auf
+     *
+     * @param path WO begonnen werden soll
+     * @param recurseDepth Wieviele ebenen
+     * @return Liste der Pfae
+     */
+    public static String[] walkDirectoryRecursively(String path, int recurseDepth)
+    {
+        return walkDirectoryRecursively(path, recurseDepth, false);
+    }
+
+    /**
+     * Hangelt sich rekursiv durch ein Verzeichnis und listet alles
+     * darunterliegende auf
+     *
+     * @param path WO begonnen werden soll
+     * @param recurseDepth Wieviele ebenen
+     * @param verbose Geschwätzig?
+     * @return Liste der Pfae
+     */
+    public static String[] walkDirectoryRecursively(String path, int recurseDepth, boolean verbose)
+    {
+        //if(verbose)
+        //System.out.print("cls\r\n");//DOESNTWORK:(
+        ArrayList<String> data = new ArrayList<>();
+        int length = 0;
+        String[] DirCnt = getDirectoryContent(path);
+        if(DirCnt==null)
+        {
+            return new String[]{};
+        }
+        for (String string : DirCnt)
+        {
+            File f = new File(string);
+            if (f.isDirectory())
+            {
+                if (verbose)
+                {
+                    //System.console().
+                    /*String s2 = "";//Satz mit X war wohl nix
+                    while(s2.length()<length)
+                    {
+                        s2+="\b";//weigert sich ne zeile nauf zu gehren
+                    }
+                    System.out.print(s2);
+                    System.console().writer().append(s2);*/
+                    String s = "\rReading in:" + f.getPath();
+                    //NOLOG
+                    System.out.print(s);
+                    /*try //abgekrachte FLiegenklatsche
+                    {
+                        Thread.sleep(20);
+                    }
+                    catch (InterruptedException ex)
+                    {
+                        ex.printStackTrace();
+                    }
+                            */
+                    if(s.length()>length)
+                    {
+                        length = s.length();
+                    }
+                    else
+                    {
+                        while(s.length()<length)
+                        {
+                            s+=" ";//auffüllen auf gewünschte länge....
+                        }
+                    }
+                 //   System.out.print((char)0x1b+"[u");//DOESNTWORK
+                }
+                String[] sdc = walkDirectoryRecursively(string, recurseDepth - 1,verbose);
+                data.add(string);
+                data.addAll(Arrays.asList(sdc));
+            }
+            else
+            {
+            data.add(string);
+            }
+        }
+        String[] s = new String[]
+        {
+            ""
+        };
+        return data.toArray(s);
+    }
+
+    /**
+     * Liest Dateiname mit Erweiterung aus
+     * @param path Pfad derDatei
+     * @return Dateiname ohne Pfad
+     */
+    
+    public static String getFileName(String path)
+    {
+        //String ft1 = FileTK.getFilePath(path);
+        String ft2 = path.substring(path.lastIndexOf("\\")+1);
+        return ft2;
+    }
+    
+    /**
+     * Liest dateiendung aus
+     *
+     * @param path Dateipfad zumauslesen
+     * @return dateiendung in lowercase
+     */
+    public static String getFileExt(String path)
+    {
+        String ext = null;
+        int i = path.lastIndexOf('.');
+
+        if (i > 0 && i < path.length() - 1)
+        {
+            ext = path.substring(i + 1).toLowerCase();
+        }
+        return ext;
+        /*
+         String[] splitpath = path.split(".");
+         String ret = null;
+         if(splitpath.length>1)
+         {
+         ret = splitpath[splitpath.length-1];
+         }
+         return ret;*/
+    }
+
+    /**
+     * Gibt Ordnerpfad netr datei aus
+     *
+     * @param path Dateiname/pfd
+     * @return Ordner der Datei
+     */
+    public static String getFilePath(String path)
+    {
+        path = new File(path).getAbsolutePath();//falls nen relativer Pfad verwendet wurde
+        String ext = path;
+        int i = path.lastIndexOf("\\");
+
+        if (i > 0 && i < path.length())
+        {
+            ext = path.substring(0, i);
+        }
+        return ext;
+    }
+
+    /*private static void log(String line)
+    {
+        Tools.DebugHelperPrint(line, true, "Toolkit.enableCoreDebug");
+    }*/
+
+    /**
+     * Lädt Datei in String-array
+     *
+     * @param path Dateipfad
+     * @return ZEilenweises Array der Datei
+     */
+    @SuppressWarnings("ConvertToTryWithResources")
+    public static String[] fileload(String path)
+    {
+        return fileload(path, true);
+    }
+
+    /**
+     * Lädt Datei in String-array
+     *
+     * @param path Dateipfad
+     * @param eofmark unbenutzt (zu fixen wegen bug)
+     * @return ZEilenweises Array der Datei
+     */
+    @SuppressWarnings("ConvertToTryWithResources")
+    public static String[] fileload(String path, boolean eofmark)//bugfix noch zu erledigen
+    {
+        String filedata = "";
+        String[] filecnt;
+        try
+        {
+            FileReader fr = new FileReader(path);
+            BufferedReader br = new BufferedReader(fr);
+            filedata = br.readLine() + "\n";
+            String zeile = "x";
+            while (zeile != null)
+            {
+                l.trace(zeile);
+                zeile = br.readLine();
+                filedata = filedata + zeile + "\n";
+            }
+            filecnt = filedata.split("\n");
+            fr.close();
+        }
+        catch (Exception ioe)
+        {
+            //log("Failed to load FIle:unknown error. Something f@ild.");
+            l.info("noncritical internal error. Ignored");
+            l.info("@:"+new File(path).getAbsolutePath());
+            //ioe.printStackTrace();
+            filecnt = new String[1];
+            filecnt[0] = "LMAA";
+        }
+        l.trace(filedata);
+        return filecnt;
+    }
+
+    /**
+     * Speichert Datei(überschreibend)
+     *
+     * @param cnt Inhalt
+     * @param path Wohin
+     */
+    public static void writeFile(String cnt, String path)
+    {
+        writeFile(cnt, path, false);
+    }
+
+    /**
+     * Speichert Datei
+     *
+     * @param cnt Inhalt
+     * @param path Wohin
+     * @param app Anfügen?
+     */
+    @SuppressWarnings("CallToThreadDumpStack")
+    public static void writeFile(String cnt, String path, boolean app)
+    {
+        
+        FileWriter fw = null;
+        try
+        {
+            new File(path).createNewFile();
+            fw = new FileWriter(path);
+            if (!app)
+            {
+                fw.write(cnt);
+            }
+            else
+            {
+                int size = (int) new File(path).length();
+                fw.write(path, size, cnt.length());
+            }
+        }
+        catch (IOException e)
+        {
+            l.warn("Konnte Datei nicht erstellen");
+            e.printStackTrace();
+        }
+        finally
+        {
+            if (fw != null)
+            {
+                try
+                {
+                    fw.close();
+                }
+                catch (IOException e)
+                {
+                }
+            }
+        }
+    }
+
+    /**
+     * Prüft auf existenz ner datei/Verzeichnis
+     *
+     * @param path Was
+     * @return Obs existiert
+     */
+    public static boolean checkDirExist(String path)
+    {
+        File f = new File(path);
+        if (!f.exists())
+        {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * entspricht dir von der cmd
+     *
+     * @param path Wo
+     * @return Array der dateien innerhalb
+     */
+    public static String[] getDirectoryContent(String path)
+    {
+        return getDirectoryContent(path,false);
+    }
+        /**
+     * entspricht dir von der cmd
+     *
+     * @param path Wo
+     * @param skipPrePath ob nur die t dateinamen kommen sollen;
+     * @return Array der dateien innerhalb
+     */
+    public static String[] getDirectoryContent(String path,boolean skipPrePath)
+    {
+        File f = new File(path);
+        File[] dirtmpf = f.listFiles();
+        //String[] dirtmp = new String[] d
+        l.trace("Pfad={}",path);
+        String[] ret = null;
+        try
+        {
+            ret = new String[dirtmpf.length];
+
+            int j;
+            for (int i = 0; i < dirtmpf.length; i++)
+            {
+                j = i;
+                String tmp = dirtmpf[i].getPath();
+                if (!(tmp.length() < path.length()))
+                {
+                    
+                    ret[j] = tmp;
+                    if(skipPrePath)
+                    {
+                        ret[j] = getFileName(tmp);
+                    }
+                    
+                    
+                    //j++;
+                }
+
+            }
+        }
+        catch (NullPointerException e)
+        {
+
+            ret = new String[0];
+            l.trace("LMAA|{}",path);
+        }
+        return ret;
+    }
+
+    /**
+     * Erzeugt den relativen Pfad einer datei/eines Ordners zu eienm Basispfad
+     *
+     * @param absolutePath Pfad von dem relativer Pfad zu
+     * @param basePath diesem ermittelt werden soll
+     * @return der relative Pfad
+     */
+    public static String getRelativePath(String absolutePath, String basePath)//Initializer für Hack!
+    {
+        absolutePath = absolutePath.replace("/", "\\");
+        basePath = basePath.replace("/", "\\");
+        String rpath = getRelativePath(absolutePath, basePath, 0);
+        return rpath==null?rpath:rpath.replace("\\", File.separator);
+    }
+
+    private static String getRelativePath(String absolutePath, String basePath, int recurses)//Fetter Hack wegen fehkendem Java-Befehl!
+    {
+        String replace = null, unRegex = null, internalPath = "", parsedPath = "";
+        boolean err = false;
+        
+        if (absolutePath != null || basePath != null)
+        {
+
+            if (recurses > 0)
+            {
+                try
+                {
+                    String pathSplit[] = basePath.split("\\\\");
+                    Object[] psplit = Tools.truncateArray(pathSplit, 1, true);
+                    for (Object o : psplit)
+                    {
+                        internalPath += o + "\\";
+                    }
+                    //entfernt das letze element des pfades
+                    //BSP: C:\pfad\zu\krempel\killme  -> C:\pfad\zu\krempel
+                    //Kilme wird entfernt
+                    
+                    String replaceTemp = "";
+                    for (int i = 0; i < recurses; i++)//recurses gibt an wievile ebenen er rauf ist
+                    {
+                        replaceTemp += "\\.\\.\\\\"; //  ..\ so oft wie der parser den baum raufgewandert ist
+                    }
+                    replace = "\\.\\\\" + replaceTemp; //beginnt pfad mit .\ und dann soviele ..\-s wie nötig
+                    unRegex = internalPath.replaceAll("\\\\", "\\\\\\\\"); // \ -> \\
+                   l.trace("Aha");
+                }
+                catch (Exception ex)
+                {
+                    err = true;
+                    l.trace("FickDich");
+                }
+
+
+            }
+            else
+            {
+                internalPath = basePath;
+                replace = "\\.\\\\";
+                unRegex = basePath.replaceAll("\\\\", "\\\\\\\\"); // \ -> \\
+            }
+
+            parsedPath = absolutePath.replaceAll(unRegex, replace);// basePath -> .\ haut den gemeinsamen teil raus und fügt den relativteil an
+            l.trace("ParsedPath={}",parsedPath);
+            if (parsedPath.equals(absolutePath))
+            {
+                //basePath=internalPath;
+                recurses++;
+                String parsedPath2 = null;
+                //absolutePath = absolutePath.replaceAll("\\\\", "\\\\\\\\");
+                try
+                {
+                    parsedPath2 = getRelativePath(absolutePath, internalPath, recurses);
+                }
+                catch (Exception ex)
+                {
+                    l.trace("Arschfotze");
+                }
+                if (parsedPath2 != null)
+                {
+                    parsedPath = parsedPath2;
+                }
+            }
+        }
+        else
+        {
+            err = false;
+        }
+        if (err == true)
+        {
+            parsedPath = null;
+        }
+        
+        return parsedPath;
+    }
+    /**
+     * Fatei kopieren
+     * Code ist ausm netz: http://www.javabeginners.de/Dateien_und_Verzeichnisse/Eine_Datei_kopieren.php
+     * @param in Eingabefile
+     * @param out Ausgabefile
+     * @throws IOException 
+     */
+    
+    public static void kopierpaste(File in, File out) //throws IOException
+    {
+        FileChannel inChannel=null,outChannel=null;
+        try
+        {
+        inChannel = new FileInputStream(in).getChannel();
+        outChannel = new FileOutputStream(out).getChannel();
+
+
+
+            inChannel.transferTo(0, inChannel.size(), outChannel);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+            l.error("Kopiererei geerrort");
+          //  throw e;
+        }
+        finally
+        {
+            if (inChannel != null)
+            {
+                try
+                {
+                    inChannel.close();
+                }
+                catch (IOException ex)
+                {
+                    ex.printStackTrace();
+                }
+            }
+            if (outChannel != null)
+            {
+                try
+                {
+                    outChannel.close();
+                }
+                catch (IOException ex)
+                {
+                    ex.printStackTrace();
+                }
+            }
+        }
+    }
+        
+    /**
+     * Checkt ob pfad nen verzeichnis sit
+     * @param path welcher pfad
+     * @return ja/nein
+     */
+    public static boolean isDir(String path)
+    {
+        return new File(path).isDirectory();
+    }
+    
+    /**
+     * Schrubbt verzeichnis rekursiv raus;
+     * @param path welches dir
+     */
+    
+    public static void verzeichnisKillen(File path)
+    {
+        if(path.exists())
+        {
+            for (File file : path.listFiles())
+            {
+                if (file.isDirectory())
+                {
+                    verzeichnisKillen(file);
+                }
+                file.delete();
+            }
+            path.delete();
+        }
+    }
+    
+    
+    public static String fileAsString(String path) throws FileNotFoundException, IOException
+    {
+        return fileAsString(new File(path));
+    }
+    
+    public static String fileAsString(File path) throws FileNotFoundException, IOException
+    {
+            if(path.length()>Integer.MAX_VALUE)
+            {
+                throw new IOException(" File too large for specified operation");
+            }
+            FileReader fr = new FileReader(path);
+            CharBuffer c = CharBuffer.allocate((int)path.length());
+            fr.read(c);
+            c.rewind();
+            l.trace(path.length()+"|"+c.length());
+            return c.toString();
+    }
+    
+}

+ 190 - 191
ToolKit/src/main/java/de/nplusc/izc/tools/baseTools/Detectors.java

@@ -1,191 +1,190 @@
-/*
- * Copyright (C) 2015 iZc
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package de.nplusc.izc.tools.baseTools;
-
-import de.nplusc.izc.tools.IOtools.FileTK;
-import java.io.File;
-import java.io.IOException;
-import java.util.prefs.Preferences;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-
-/**
- * Various detectuon routines
- * @author LH
- */
-public class Detectors
-{
-    
-    public static boolean isJavaw()
-    {
-        try
-        {
-            System.in.available();
-            return false;
-        }
-        catch (IOException e)
-        {
-            // invalid handle in case of javaw
-            return true;
-        }
-    }
-    
-    
-    private static final Logger l = LogManager.getLogger();
-    //@SuppressWarnings("empty-statement")
-    
-    
-    /**
-     * Detecs the OS Family and architecture
-     * @return {OSFamily,Architecture}
-     */
-    public static String[] getSystemClassification()
-    {
-        String operatingSystemInternal = System.getProperty("os.name");
-        String osname = "VOID";
-        String osarchinternal = System.getProperty("os.arch");
-        String osarch = "VOID";
-        if(operatingSystemInternal.contains("Linux"))
-                osname="linux";
-        if(operatingSystemInternal.contains("Windows"))
-                osname="windows";
-        if(operatingSystemInternal.contains("Mac"))
-        {
-                osname="mac";
-        }
-        switch(osarchinternal)
-        {
-            case "i386":
-            case "i486":
-            case "i586":
-            case "i686":
-            case "x86":
-                osarch= "x86";
-                break;
-            case "x86_64":
-            case "amd64":
-                osarch = "x64";
-                break;
-        }
-        return new String[]{osname,osarch};
-    }
-    
-    
-    /**
-     * Checks whether OS is windows 8
-     * @return True when win8 got detected
-     */
-    public static boolean detectIsWin8()
-    {
-        boolean ret = false;
-
-        return FileTK.checkDirExist("C:\\Users\\Default\\appdata\\Local\\Microsoft\\windows\\WinX");
-        /*
-         String[] cnt = FileTK.getDirectoryContent("C:\\Users\\Default\\appdata\\Local\\Microsoft\\windows\\WinX");
-         try
-         {
-         String s = cnt[0];
-         }
-         catch(Exception e){}*/
-        //if(System.getProperty("os.name").equals("Windows 8"))
-        //        {
-        //            ret = true;
-        //        }
-        // return ret;
-
-    }
-    
-    
-    /**
-     * Detecs if a 64bit windows7 got used
-     * @return true on 64bit win7 or win8
-     */
-    public static boolean detect64bitWinon7and8()
-    {
-        return FileTK.checkDirExist("Program files (x86)");
-    }
-
-    
-    /**
-     * Detects if PRogram runs on WIndows XPlode
-     * @return true if WinXP
-     */
-    public static boolean detectWInXP()
-    {
-        return FileTK.checkDirExist("C:\\WINDOWS\\Help\\Tours");
-    }
-    
-    /**
-     * Detects Existence of win7
-     * @return true on win7
-     */
-    public static boolean detectWin7()
-    {
-        return FileTK.checkDirExist("C:\\Users") && !detectIsWin8();//Users gibts bei 7 und 8 deshalb die 2. bedingung
-    }
-    
-    /**
-     * Detecs whether program runs as Admin on windows
-     * @return True when admin-rights are existing
-     */
-    public static boolean detectisAdmin()
-    {
-        ////neuer dirty hack
-            Preferences prefs = Preferences.systemRoot();
-    try{
-        prefs.put("foo", "bar"); // SecurityException on Windows
-        prefs.remove("foo");
-        prefs.flush(); // BackingStoreException on Linux
-        return true;
-    }catch(Exception e){
-        return false;
-    }
-        
-        
-        ////HACKALERT.... auskommentierter weg ging nicht muss ne eigenheit von WIndows ausnutzen auf C:\adminrechte zu verlangen
-       /* try{
-           File f =  new File("C:\\temp.dat");
-           f.createNewFile();
-           f.delete();
-            
-        }
-        catch(IOException e)
-        {
-            return false;
-        }
-        return true;*/
-        
-        /*
-        String groups[] = (new com.sun.security.auth.module.NTSystem()).getGroupIDs();
-        for (String group : groups)
-        {
-            Tools.DebugHelperPrint("grp..."+group, true, "Toolkit.enableFinerDebug");
-            if (group.equals("S-1-5-32-544"))
-            {
-                Tools.DebugHelperPrint("ADM", true, "Toolkit.enableFinerDebug");
-                return true;
-            }
-        }
-        return false;*/
-    }
-
-    private Detectors()
-    {
-    }
-}
+/*
+ * Copyright (C) 2015 iZc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.nplusc.izc.tools.baseTools;
+
+import de.nplusc.izc.tools.IOtools.FileTK;
+import java.io.File;
+import java.io.IOException;
+import java.util.prefs.Preferences;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+
+/**
+ * Various detectuon routines
+ * @author LH
+ */
+public class Detectors
+{
+    
+    public static boolean isJavaw()
+    {
+        try
+        {
+            System.in.available();
+            return false;
+        }
+        catch (IOException e)
+        {
+            // invalid handle in case of javaw
+            return true;
+        }
+    }
+    
+    
+    private static final Logger l = LogManager.getLogger();
+    //@SuppressWarnings("empty-statement")
+    
+    
+    /**
+     * Detecs the OS Family and architecture
+     * @return {OSFamily,Architecture}
+     */
+    public static String[] getSystemClassification()
+    {
+        String operatingSystemInternal = System.getProperty("os.name");
+        String osname = "VOID";
+        String osarchinternal = System.getProperty("os.arch");
+        String osarch = "VOID";
+        if(operatingSystemInternal.contains("Linux"))
+                osname="linux";
+        if(operatingSystemInternal.contains("Windows"))
+                osname="windows";
+        if(operatingSystemInternal.contains("Mac"))
+        {
+                osname="mac";
+        }
+        switch(osarchinternal)
+        {
+            case "i386":
+            case "i486":
+            case "i586":
+            case "i686":
+            case "x86":
+                osarch= "x86";
+                break;
+            case "x86_64":
+            case "amd64":
+                osarch = "x64";
+                break;
+        }
+        return new String[]{osname,osarch};
+    }
+    
+    /**
+     * Checks whether OS is windows 8
+     * @return True when win8 got detected
+     */
+    public static boolean detectIsWin8()
+    {
+        boolean ret = false;
+
+        return FileTK.checkDirExist("C:\\Users\\Default\\appdata\\Local\\Microsoft\\windows\\WinX");
+        /*
+         String[] cnt = FileTK.getDirectoryContent("C:\\Users\\Default\\appdata\\Local\\Microsoft\\windows\\WinX");
+         try
+         {
+         String s = cnt[0];
+         }
+         catch(Exception e){}*/
+        //if(System.getProperty("os.name").equals("Windows 8"))
+        //        {
+        //            ret = true;
+        //        }
+        // return ret;
+
+    }
+    
+    
+    /**
+     * Detecs if a 64bit windows7 got used
+     * @return true on 64bit win7 or win8
+     */
+    public static boolean detect64bitWinon7and8()
+    {
+        return FileTK.checkDirExist("Program files (x86)");
+    }
+
+    
+    /**
+     * Detects if PRogram runs on WIndows XPlode
+     * @return true if WinXP
+     */
+    public static boolean detectWInXP()
+    {
+        return FileTK.checkDirExist("C:\\WINDOWS\\Help\\Tours");
+    }
+    
+    /**
+     * Detects Existence of win7
+     * @return true on win7
+     */
+    public static boolean detectWin7()
+    {
+        return FileTK.checkDirExist("C:\\Users") && !detectIsWin8();//Users gibts bei 7 und 8 deshalb die 2. bedingung
+    }
+    
+    /**
+     * Detecs whether program runs as Admin on windows
+     * @return True when admin-rights are existing
+     */
+    public static boolean detectisAdmin()
+    {
+        ////neuer dirty hack
+            Preferences prefs = Preferences.systemRoot();
+    try{
+        prefs.put("foo", "bar"); // SecurityException on Windows
+        prefs.remove("foo");
+        prefs.flush(); // BackingStoreException on Linux
+        return true;
+    }catch(Exception e){
+        return false;
+    }
+        
+        
+        ////HACKALERT.... auskommentierter weg ging nicht muss ne eigenheit von WIndows ausnutzen auf C:\adminrechte zu verlangen
+       /* try{
+           File f =  new File("C:\\temp.dat");
+           f.createNewFile();
+           f.delete();
+            
+        }
+        catch(IOException e)
+        {
+            return false;
+        }
+        return true;*/
+        
+        /*
+        String groups[] = (new com.sun.security.auth.module.NTSystem()).getGroupIDs();
+        for (String group : groups)
+        {
+            Tools.DebugHelperPrint("grp..."+group, true, "Toolkit.enableFinerDebug");
+            if (group.equals("S-1-5-32-544"))
+            {
+                Tools.DebugHelperPrint("ADM", true, "Toolkit.enableFinerDebug");
+                return true;
+            }
+        }
+        return false;*/
+    }
+
+    private Detectors()
+    {
+    }
+}

+ 1 - 1
WPCMGr/build.gradle

@@ -65,7 +65,7 @@ dependencies{
         compile "net.rubygrapefruit:native-platform:0.9"
 	compile "commons-io:commons-io:2.+"
 	compile 'org.apache.commons:commons-exec:1.3'
-	compile "org.yaml:snakeyaml:1.14"
+	compile "org.yaml:snakeyaml:+"
 	compile 'org.ini4j:ini4j:0.5.2'
 	compile 'mysql:mysql-connector-java:5.1.6'
         compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.1'

+ 65 - 0
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/CacheState.java

@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 iZc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.nplusc.izc.Utilities.WPCMgr;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+/**
+ *
+ * @author iZc <nplusc.de>
+ */
+public class CacheState
+{
+    private List<String> processedPackages;
+    private HashMap<String,PackageState> packages;
+    
+    public CacheState()
+    {
+        processedPackages=new ArrayList<>();
+        packages = new LinkedHashMap<>();
+        
+    }
+    
+    
+    public List<String> getProcessedPackages()
+    {
+        return processedPackages;
+    }
+
+    public void setProcessedPackages(List<String> processedPackages)
+    {
+        this.processedPackages = processedPackages;
+    }
+
+    public HashMap<String, PackageState> getPackages()
+    {
+        return packages;
+    }
+
+    public void setPackages(HashMap<String, PackageState> packages)
+    {
+        /*ArrayList tits = new ArrayList(packages.keySet());
+        if(tits.get(0)!=null&&!(tits.get(0) instanceof PackageState))
+        {
+            throw new Error("Fuck you yaml");
+        }*/
+        this.packages = packages;
+    }
+}

+ 39 - 0
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Constants.java

@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 iZc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.nplusc.izc.Utilities.WPCMgr;
+
+/**
+ *
+ * @author iZc <nplusc.de>
+ */
+public class Constants
+{
+    public static final int[][][] SCREENRATIOS={
+        {{16,9},{21,9},{16,10},{4,3}/*,{5,4}*/},
+        
+        {{32,9},{42,9},{32,10},{8,3}},
+                                                           
+        {{48,9},{63,9},{48,10}},//kein 3x 4:3 
+    
+        {{64,9},{84,9},{64,10},{16,3}}
+    };
+
+    private Constants()
+    {
+    }
+        
+}

+ 55 - 55
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Main.java

@@ -18,7 +18,9 @@
 package de.nplusc.izc.Utilities.WPCMgr;
 
 import java.io.FileNotFoundException;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
 import org.apache.commons.cli.DefaultParser;
@@ -66,12 +68,21 @@ public class Main
                 .hasArg()
                 .withArgName("TARGET")
                 .create("i"));
-        modes.addOption(OptionBuilder.withLongOpt("addScreen")
+        modes.addOption(OptionBuilder.withLongOpt("addMonitor")
                 .withDescription("add SCREEN with given settings (\"id,xpos,ypos,width,height\") to the screen registry of the selected cache, allows multiple screens to be defined at once. existing Screens with the same ID get overwritten"+
                         "Alternative Sybtax for screen is \"id,width,height\" to get a screen at default position of 0,0")
                 .hasArgs(Option.UNLIMITED_VALUES)
                 .withArgName("SCREEN")
                 .create());
+        modes.addOption(OptionBuilder.withLongOpt("addScreenstrip")
+                .withDescription("creates a Screen strip to define where multiscreen wallpapers may be stretched over morer than one screen."+
+                        "Syntax: \"id,screenid1,screenid2,...,screenidN\"")
+                .hasArgs(Option.UNLIMITED_VALUES)
+                .withArgName("SCREENSTRIP")
+                .create());
+        modes.addOption(OptionBuilder.withLongOpt("listScreens")
+                .withDescription("lists all registered Screens")
+                .create());
         options.addOptionGroup(modes);
         try
         {
@@ -87,6 +98,8 @@ public class Main
                 throw new ParseException("Folder undefined");
             }
             l.trace(folder);
+            
+            
             if (cl.hasOption("initDirectory"))
             {
                 String initArg = cl.getOptionValue("initDirectory");
@@ -94,9 +107,9 @@ public class Main
             }
             else
             {
-                if (cl.hasOption("addScreen"))
+                if (cl.hasOption("addMonitor"))
                 {
-                    String[] screendefs = cl.getOptionValues("addScreen");
+                    String[] screendefs = cl.getOptionValues("addMonitor");
                     
                     HashMap<String,Object> cfg = WPCUtils.getConfig(folder);
                     for (String screendef : screendefs)
@@ -131,14 +144,47 @@ public class Main
                     WPCUtils.saveConfig(folder, cfg);
                 }
                 else
-                {
-                    if(cl.hasOption("process"))
+                {   
+                    if(cl.hasOption("listScreens"))
                     {
-                        Synchronizer.main(folder);
+                        HashMap<String,Object> cfg = WPCUtils.getConfig(folder);
+                        List<Screen> screens = WPCUtils.getScreenlist(cfg);
+                        StringBuilder sb = new StringBuilder("\n----------------");
+                        for (Screen screen : screens)
+                        {
+                            sb.append("\nID:").append(screen.getID()).append("\nX:")
+                                    .append(screen.getX()).append("\nY:")
+                                    .append(screen.getX()).append("\nWidth:")
+                                    .append(screen.getW()).append("\nHeight:")
+                                    .append(screen.getH()).append("\n----------------");
+                        }
+                        l.info(sb+"");
                     }
-                    else
+                    else 
                     {
-                        throw new ParseException("No PARAMS");
+                        if(cl.hasOption("addScreenstrip"))
+                        {
+                            String[] screendefs = cl.getOptionValues("addScreenstrip");
+                             HashMap<String,Object> cfg = WPCUtils.getConfig(folder);
+                            for (String screendef : screendefs)
+                            {       
+                                String[] screenstrip = screendef.split(",");
+                                String[] screenIDs = Arrays.copyOfRange(screenstrip, 1, screenstrip.length);
+                                WPCUtils.addMonitorStrip(cfg, screenstrip[0], screenIDs);
+                            }
+                            WPCUtils.saveConfig(folder, cfg);
+                        }
+                        else
+                        {
+                            if(cl.hasOption("process"))
+                            {
+                                Synchronizer.main(folder,false);
+                            }
+                            else
+                            {
+                                throw new ParseException("No PARAMS");
+                            }
+                        }
                     }
                 }
                
@@ -177,55 +223,9 @@ public class Main
             formatter.printHelp("wpcmgr", options);
             System.exit(0);
         }
-        
-        /*
-        System.out.println(args.length);
-        if (args.length>0)
-        {
-            System.out.println(args[0]);
-            if(args[0].equals("--help")||args[0].equals("-h")||args[0].equals("/?"))
-            {
-                printHelp();
-            }
-            if(args.length>2)
-            {
-                System.out.println(args[1]);
-                System.out.println(args[2]);
-                switch (args[0])
-                {
-                    case "--wpcprocess":
-                        Synchronizer.main(new String[]{args[1],args[2]});
-                        break;
-                    case "--initDirectory":
-                        
-                        break;
-                    default:
-                        printHelp();
-                        break;
-                }
-            }
-            return;
-        }
-        printHelp();*/
-    }
-    
-    private static void printHelp()
-    {
-        System.out.println("Cmdline usage of WPC-Mgr");
-        System.out.println("wpc-mgr.jar [mode] <values>");
-        System.out.println("Modes and its values");
-        System.out.println("--wpcprocess : Processes the given cacheDictory");
-        System.out.println("usage: --wpcprocess P:\\ath\\to\\CacheDir screenWidthxScreenHeight");
-        System.out.println("--initDirectory : initializes a CacheDirectory for being used by wpcprocess");
-        System.out.println("P:\\ath\\to\\CacheDir");
-        System.out.println("T:\\arged\\Directory\\Of\\ProcessedFiles");
-        System.out.println("No parameter:");
-        System.out.println("currently help; later :starts in GUI-Mode to manage the last opened Cache");
-        
-        
     }
     
-        private static void setupLogging(boolean verbose)
+    private static void setupLogging(boolean verbose)
     {
         l=LogManager.getLogger(Main.class.getName());
         LoggerContext cx = (LoggerContext) LogManager.getContext(false);

+ 85 - 0
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/PackageState.java

@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 iZc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.nplusc.izc.Utilities.WPCMgr;
+
+import java.awt.Point;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author iZc <nplusc.de>
+ */
+public class PackageState
+{
+    private String path;
+    private List<Wallpaper> b_frames;
+    private List<Wallpaper> stretchablePics;
+    private List<Wallpaper> fixedRatioPics;
+    public PackageState(String path,List<Wallpaper> b_frames, List<Wallpaper> stretchablePics, List<Wallpaper> fixedRatioPics)
+    {
+        this.path=path;
+        this.b_frames = b_frames;
+        this.stretchablePics = stretchablePics;
+        this.fixedRatioPics = fixedRatioPics;
+    }
+
+    public PackageState()
+    {
+    }
+    
+    public String getPath()
+    {
+        return path;
+    }
+    
+    public void setPath(String path)
+    {
+        this.path = path;
+    }
+    
+    public List<Wallpaper> getB_frames()
+    {
+        return b_frames;
+    }
+
+    public void setB_frames(List<Wallpaper> b_frames)
+    {
+        this.b_frames = b_frames;
+    }
+
+    public List<Wallpaper> getStretchablePics()
+    {
+        return stretchablePics;
+    }
+
+    public void setStretchablePics(List<Wallpaper> stretchablePics)
+    {
+        this.stretchablePics = stretchablePics;
+    }
+
+    public List<Wallpaper> getFixedRatioPics()
+    {
+        return fixedRatioPics;
+    }
+
+    public void setFixedRatioPics(List<Wallpaper> fixedRatioPics)
+    {
+        this.fixedRatioPics = fixedRatioPics;
+    }
+}

+ 43 - 0
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/ResultWallpaper.java

@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 iZc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.nplusc.izc.Utilities.WPCMgr;
+
+/**
+ *
+ * @author iZc <nplusc.de>
+ */
+public class ResultWallpaper
+{
+    private final String destinationName;
+    private final String sourcePath;
+
+    public ResultWallpaper(String destinationName, String sourcePath)
+    {
+        this.destinationName = destinationName;
+        this.sourcePath = sourcePath;
+    }
+
+    public String getDestinationName()
+    {
+        return destinationName;
+    }
+
+    public String getSourcePath()
+    {
+        return sourcePath;
+    }
+}

+ 27 - 23
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Screen.java

@@ -23,40 +23,44 @@ package de.nplusc.izc.Utilities.WPCMgr;
 public class Screen
 {
     private final int x,y,w,h;
+    private final String ID;
     
-    public Screen(int x,int y,int w,int h)
+    public Screen(String ID, int x,int y,int w,int h)
     {
         this.x=x;
         this.y=y;
         this.w=w;
         this.h=h;
+        this.ID=ID;
     }
-    /**
-     * 
-     * @param other
-     * @return [rx,ry,w,h]
-     */
-    public int[] intersectArea(Screen other)
+
+    public int getX()
+    {
+        return x;
+    }
+
+    public int getY()
+    {
+        return y;
+    }
+
+    public int getW()
     {
-        if((this.x+w<=other.x&&this.y+h<=other.y)
-            ||(other.x+other.w<=w&&other.y+other.h<=h))
-        {
-            return new int[]{0,0,0,0};
-        }
-        if(this.x<other.x)
-        {
-            
-        }
-        else
-        {
-            
-        }
-        return new int[]{0,0};
+        return w;
     }
-    public int[] intersectArea(int[] basePoint,Screen other)
+
+    public int getH()
     {
-        return new int[]{0,0};
+        return h;
     }
+    
+    
+    
+    public String getID()
+    {
+        return ID;
+    }
+    
     public int[] getPosition()
     {
         return null;

+ 88 - 0
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/ScreenStrip.java

@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 iZc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.nplusc.izc.Utilities.WPCMgr;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ *
+ * @author iZc <nplusc.de>
+ */
+public class ScreenStrip
+{
+    private List<Screen> contents;
+    //private Screen[] contents;
+    private int[] ratio;
+    private int width;
+    private int height;
+    public ScreenStrip(Screen[] contents)
+    {
+        //this.alternativeSplit = alternativeSplit;
+        this.contents=new ArrayList<>();
+        this.contents.addAll(Arrays.asList(contents));
+        rebuildRatio();
+    }
+
+    public List<Screen> getContents()
+    {
+        return contents;
+    }
+
+    public void setContents(List<Screen> contents)
+    {
+        this.contents = contents;
+        rebuildRatio();
+    }
+    
+    public void appendScreen(Screen s)
+    {
+        contents.add(s);
+    }
+    public int[] getRatio()
+    {
+        return ratio;
+    }
+    /*packageprotected*/void rebuildRatio()
+    {
+        width=0;
+        height=0;
+        for (Screen content : contents)
+        {
+            width+=content.getW();
+            int h=content.getH();
+            if(h>height)
+            {
+                height=h;
+            }
+        }
+        
+        
+        ratio=WPCUtils.getRatio(width, height);
+    }
+
+    public int getWidth()
+    {
+        return width;
+    }
+    public int getHeight()
+    {
+        return height;
+    }
+    
+}

+ 525 - 10
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Synchronizer.java

@@ -19,16 +19,24 @@ package de.nplusc.izc.Utilities.WPCMgr;
 
 import de.nplusc.izc.tools.IOtools.FileTK;
 import de.nplusc.izc.tools.baseTools.Tools;
+import hu.ssh.progressbar.ProgressBar;
+import hu.ssh.progressbar.console.ConsoleProgressBar;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.io.IoBuilder;
 import org.yaml.snakeyaml.DumperOptions;
 import org.yaml.snakeyaml.Yaml;
 
@@ -39,38 +47,144 @@ import org.yaml.snakeyaml.Yaml;
 public class Synchronizer
 {
     private static final Logger l = LogManager.getLogger();
-    public static void main(String cachedir) throws FileNotFoundException
+    private static boolean debug=false;
+    private static HashMap<String,Screen> screenrepo = new HashMap<>();
+    private static HashMap<String,ScreenStrip> screenstriprepo = new HashMap<>();
+    private static String cachedir;
+    private static int screenHash;
+    private static final List<Screen> screens = new ArrayList<>();
+    private static int width;
+    private static int height;
+    private static int totalFiles=0;
+    private static int currentFile=0;
+    private static ConsoleProgressBar progressBar;
+    public static void main(String cachedir_param,boolean debugmode) throws FileNotFoundException
     {
+        
+        
+        cachedir=cachedir_param;
         //DEBUG
         //path="T:\\wpc";
         //res="1920x1080";
         LinkedHashMap<String,Object> data = (LinkedHashMap<String,Object>) WPCUtils.getConfig(cachedir);
         //calculate screen coverages
         //2x16:9 allowed in 3x4:3
-        
+        folderOptimize(cachedir);
         //structure
         //screenratio>screencount>[screenbase_coord[x,y],virtualsize[x,y]];
         
-        int[][] screenratios={{16,9},{21,9},{16,10},{4,3}/*,{5,4}*/};
-        
-        int[][] dualratios={{32,9},{42,9},{32,10},{8,3}};
-                                                           
-        int[][] tripleratios = {{48,9},{63,9},{48,10},{12,3}};
         
         //install hack for using certain ratio multiscreen WPs in other multiscreen ratios
         //int[][] tri
+
+        HashMap<String,List<Integer>> monitors = (HashMap<String,List<Integer>>) data.get("MONITORS");
+        HashMap<String,List<String>> monstrips = (HashMap<String,List<String>>) data.get("MONITORSTRIPS");
+        
+        
+        monitors.forEach((k,v)->{screenrepo.put(k,new Screen(k, v.get(0), v.get(1), v.get(2),v.get(3)));});
+        
+        l.trace("Monstrip building");
+        monstrips.forEach((k,v)->
+        {
+            
+            ScreenStrip s = new ScreenStrip(new Screen[]{});
+            v.forEach((x)->
+            {
+                l.trace("adding {}",x);
+                s.appendScreen(screenrepo.get(x));
+            });
+            screenstriprepo.put(k,s);
+            l.trace("Ending Monstrip {}",k);
+        });
+
+        String[] dirsExist = FileTK.getDirectoryContent(cachedir,true);
+        //final int pid[] = new int[]{0};
+        progressBar = ConsoleProgressBar.on(System.out)
+        .withFormat("[:bar] :percent% :elapsed/:total :msg")
+        .withTotalSteps(dirsExist.length);
+        progressBar.start();
+        progressBar.setMessage("Detecting Files...");
+        HashMap<String,Object> hashgen = new HashMap<>();
+        hashgen.put("MONITORS",monitors);
+        hashgen.put("MONITORSTRIPS",monstrips);
+        screenHash = new Yaml().dump(hashgen).hashCode();
+        l.trace("ScreenHash:{}",screenHash);
         
+        CacheState theState = WPCUtils.getCacheState(cachedir);
         
+        final int[] attr = {0,0,0,0};
         
         
-        folderOptimize(cachedir);
+        screenrepo.forEach((k,v)->
+        {
+            int x=v.getX();
+            int y=v.getY();
+            int x2=x+v.getW();
+            int y2=y+v.getH();
+            if(x<attr[0])
+            {
+                attr[0]=x;
+            }
+            if(y<attr[1])
+            {
+                attr[1]=y;
+            }
+            if(x2>attr[2])
+            {
+                attr[2]=x2;
+            }
+            if(y2>attr[3])
+            {
+                attr[3]=y2;
+            }
+            screens.add(v);
+        });
+        int minScreenX=attr[0];
+        int maxScreenX=attr[2];
+        int minScreenY=attr[1];
+        int maxScreenY=attr[3];
         
+        width = maxScreenX-minScreenX;
+        height = maxScreenY-minScreenY;
         
         
         
         
+        List<String> existingPKGs = theState.getProcessedPackages();
+        Map<String,PackageState> packages = theState.getPackages();
         
-        folderOptimize(cachedir);
+        List<String> appendedPKGs = new ArrayList<>();
+        
+        Arrays.stream(dirsExist).filter(t -> !t.startsWith("00_") && new File(cachedir+"\\" + t).isDirectory()).forEach(t ->
+        {
+            if(!existingPKGs.contains(t))
+            {
+                PackageState pst = new PackageState();
+                pst.setPath(t);
+                appendedPKGs.add(t);
+                packages.put(t,pst);
+            }
+            preProcessPackage(packages.get(t));
+            progressBar.tickOne();
+        });
+        l.trace("finalize pre");
+        progressBar.complete();
+        
+        progressBar = progressBar.withTotalSteps(totalFiles);
+        progressBar.start();
+        existingPKGs.addAll(appendedPKGs);
+        WPCUtils.saveCacheState(cachedir, theState);
+        
+        int i=0;
+        for (String pak : existingPKGs)
+        {
+                            //java.....
+            PackageState thePackage = packages.get(pak);
+            processPackage(i, thePackage);
+        }
+        progressBar.complete();
+        //optimizing the data structures after a processing pass
+        //folderOptimize(cachedir);
         /*
         try
         {
@@ -92,6 +206,407 @@ public class Synchronizer
         
     }
     
+    
+    private static void preProcessPackage(PackageState theState)
+    {
+        String path = cachedir+File.separator+theState.getPath();
+        String[] availablePackagesNormal = FileTK.getDirectoryContent(path+File.separator+"proc",true);
+        String[] availablePackagesNoResize = FileTK.getDirectoryContent(path+File.separator+"k-i-p",true);
+        String[] availablePackagesBFrames = FileTK.getDirectoryContent(path+File.separator+"b-frames",true);
+        List<Wallpaper> existingWPsN = theState.getStretchablePics();
+        List<Wallpaper> existingWPsF = theState.getFixedRatioPics();
+        List<Wallpaper> existingWPsB = theState.getB_frames();
+        if(existingWPsN==null)
+        {
+            existingWPsN= new ArrayList<>();
+            theState.setStretchablePics(existingWPsN);
+        }
+        if(existingWPsF==null)
+        {
+            existingWPsF= new ArrayList<>();
+            theState.setFixedRatioPics(existingWPsF);
+        }
+        if(existingWPsB==null)
+        {
+            existingWPsB= new ArrayList<>();
+            theState.setB_frames(existingWPsB);
+        }
+
+        
+        for (String wpp : availablePackagesNormal)
+        {
+            if(FileTK.getFileExt(wpp).equals("loc"))
+            {
+                wpp=path+File.separator+"src"+File.separator+FileTK.getFileName(wpp).replace(".loc", "");
+            }
+            else
+            {
+                wpp=path+File.separator+"proc"+File.separator+FileTK.getFileName(wpp);
+            }
+            Wallpaper wp = new Wallpaper(screenHash-1, wpp);
+            //int wpi = existingWPsN.indexOf(wp);
+            if(!existingWPsN.contains(wp))
+            {
+                existingWPsN.add(wp);
+            }
+            totalFiles++;
+        }
+        for (String wpp : availablePackagesNoResize)
+        {
+            if(FileTK.getFileExt(wpp).equals("loc"))
+            {
+                wpp=path+File.separator+"src"+File.separator+FileTK.getFileName(wpp);
+            }
+            else
+            {
+                wpp=path+File.separator+"k-i-p"+File.separator+FileTK.getFileName(wpp);
+            }
+            Wallpaper wp = new Wallpaper(screenHash-1, wpp);
+            //int wpi = existingWPsN.indexOf(wp);
+            if(!existingWPsF.contains(wp))
+            {
+                existingWPsF.add(wp);
+            }
+            totalFiles++;
+        }
+        for (String wpp : availablePackagesBFrames)
+        {
+            if(FileTK.getFileExt(wpp).equals("loc"))
+            {
+                wpp=path+File.separator+"src"+File.separator+FileTK.getFileName(wpp);
+            }
+            else
+            {
+                wpp=path+File.separator+"b-frames"+File.separator+FileTK.getFileName(wpp);
+            }
+            Wallpaper wp = new Wallpaper(screenHash-1, wpp);
+            //int wpi = existingWPsN.indexOf(wp);
+            if(!existingWPsB.contains(wp))
+            {
+                existingWPsB.add(wp);
+            }
+            totalFiles++;
+        }
+        l.trace("package pre");
+    }
+    
+    
+    private static List<ResultWallpaper> processPackage(int packageOffset,PackageState st)
+    {
+        
+        
+        List<String> bframes = new ArrayList<>();
+        
+        List<ResultWallpaper> resultFiles = new ArrayList<>();
+        
+        String outdir = cachedir+File.separator+st.getPath()+File.separator+"p"+File.separator;
+        String bframedir = outdir+"bframe"+File.separator;
+        FileTK.ensuredirExistence(bframedir+File.separator+"dummy");
+        List<Wallpaper> wpl = st.getB_frames();
+        Wallpaper lastSingleWP=null;
+        boolean lastPicIsSquashable=true;
+        
+        int i=0;
+        for (Wallpaper wallpaper : wpl)
+        {
+            lastSingleWP=wallpaper;
+
+            String targetfile = bframedir+"bframe_"+i+".jpg";
+            processWallpaperWithoutScreenStrip(wallpaper,targetfile);
+            bframes.add(targetfile);
+            i++;
+        }
+        progressBar.tickOne();
+        
+        int bframe_count = bframes.size();
+        int bframe_i=0;
+        wpl = st.getStretchablePics();
+        i=0; //zurücksetzen für die basePictures
+        for (Wallpaper wallpaper : wpl)
+        {
+            String targetFilenameBase = String.format("%04d", packageOffset)+"_"+String.format("%06d", i);
+            String targetfile = outdir+targetFilenameBase+".jpg";
+            boolean[] swp = processWallpaperWithScreenStrip(wallpaper,lastSingleWP,targetfile, true,lastPicIsSquashable);
+            i++;
+            if(swp[0])
+            {
+                lastSingleWP=wallpaper;
+                
+            }
+            if(!swp[1])
+            {
+                resultFiles.add(new ResultWallpaper(targetFilenameBase+".jpg", targetfile));
+                if(bframe_count>0&&i%5==0)
+                {
+                    resultFiles.add(new ResultWallpaper(targetFilenameBase+"b.jpg", bframes.get(bframe_i%bframe_count)));
+                    bframe_i++;
+                }
+            }
+            progressBar.tickOne();
+        }
+        wpl = st.getFixedRatioPics();
+        for (Wallpaper wallpaper : wpl)
+        {
+            String targetFilenameBase = String.format("%04d", packageOffset)+"_"+String.format("%06d", i);
+            String targetfile = outdir+targetFilenameBase+".jpg";
+            boolean[] swp=processWallpaperWithScreenStrip(wallpaper,lastSingleWP,targetfile, false,lastPicIsSquashable);
+            i++;
+            if(swp[0])
+            {
+                lastSingleWP=wallpaper;
+                lastPicIsSquashable=false;
+            }
+            if(!swp[1])
+            {
+                resultFiles.add(new ResultWallpaper(targetFilenameBase+".jpg", targetfile));
+                if(bframe_count>0&&i%5==0)
+                {
+                    resultFiles.add(new ResultWallpaper(targetFilenameBase+"b.jpg", bframes.get(bframe_i%bframe_count)));
+                    bframe_i++;
+                }
+            }
+            progressBar.tickOne();
+        }
+
+        return resultFiles;
+        
+        
+        
+        //kip = WxH>
+        //proc & BFrame= WxH!
+    }
+    
+    private static void processWallpaperWithoutScreenStrip(Wallpaper wallpaper,String targetfile)
+    {
+        if(wallpaper.getScreenHash()!=screenHash)
+        {
+            List<String> convertCmd = new ArrayList<>();
+            String[] convertPrefix = {"C:\\Program Files\\ImageMagick-6.8.8-Q16\\convert.exe","-respect-parentheses","-size",width+"x"+height,"xc:black"};
+            convertCmd.addAll(Arrays.asList(convertPrefix));
+            for (Screen screen : screens)
+            {
+                int x=screen.getX();
+                int y=screen.getY();
+                int sw = screen.getW();
+                int sh = screen.getH();//page +5+10  balloon.gif
+                String[] core = {"(",
+                    wallpaper.getFilepath(),"-resize",sw+"x"+sh+"!"    
+                ,")"};
+                insertIntoConvert(x, y, convertCmd, core);
+            }
+            String[] convertEnd = {"-layers" ,"flatten"  ,targetfile};
+            convertCmd.addAll(Arrays.asList(convertEnd));
+
+            Tools.runCmdWithPassthru(IoBuilder.forLogger("External.Imagick").buildPrintStream(), convertCmd.toArray(convertEnd));
+        }
+        
+    }
+
+
+    private static boolean[] processWallpaperWithScreenStrip(Wallpaper wallpaper,Wallpaper fallback,String targetfile,boolean allowStretch,boolean fallbackSquashable)
+    {
+        boolean wallpaperIsSingle = false;
+        boolean skipped=true;
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(baos);
+        Tools.runCmdWithPassthru(ps, new String[]{"C:\\Program Files\\ImageMagick-6.8.8-Q16\\identify.exe","-quiet","-format","%w %h",wallpaper.getFilepath()});
+        String content = new String(baos.toByteArray(), StandardCharsets.UTF_8);
+        l.trace(content);
+        String[] r = content.split(" ");
+        int wpX = Integer.parseInt(r[0].trim());
+        int wpY = Integer.parseInt(r[1].trim());
+        int[] ratio = WPCUtils.getRatio(wpX, wpY);
+        int screensofWP = WPCUtils.getScreensInRatio(ratio);
+        if(screensofWP==1||wpX<1500||(wpX<2500&&!allowStretch))//to prevent too small wallpapers from entering Multiscreen handling
+        {
+            wallpaperIsSingle=true;
+        }
+        
+        if(wallpaper.getScreenHash()!=screenHash)
+        {
+            skipped=false;
+            List<String> convertCmd = new ArrayList<>();
+            String[] convertPrefix = {"C:\\Program Files\\ImageMagick-6.8.8-Q16\\convert.exe","-respect-parentheses","-size",width+"x"+height,"xc:black"};
+            convertCmd.addAll(Arrays.asList(convertPrefix));
+            // identify rose.jpg
+            // rose.jpg JPEG 70x46 70x46+0+0 8-bit sRGB 2.36KB 0.000u 0:00.000
+            
+            if(wallpaperIsSingle)
+            {
+                l.trace("1");
+                for (Screen screen : screens)
+                {
+                    int x=screen.getX();
+                    int y=screen.getY();
+                    int sw = screen.getW();
+                    int sh = screen.getH();//page +5+10  balloon.gif
+                    String[] core = {"(","-size",sw+"x"+sh,debug?"xc:red":"xc:black","-gravity","center",
+                    wallpaper.getFilepath(),"-resize",sw+"x"+sh+(allowStretch?"!":">"),"-composite",")"};
+                    insertIntoConvert(x, y, convertCmd, core);
+                }
+            }
+            else
+            {
+                HashMap<String,Screen> workingSet = (HashMap<String,Screen>) screenrepo.clone();
+                final List<ScreenStrip> screenstrips = new ArrayList<>();
+                screenstriprepo.forEach((k,v)->{screenstrips.add(v);});
+                for (ScreenStrip screenstrip : screenstrips)
+                {
+                    screenstrip.rebuildRatio();
+                    int[]screenstripratio = screenstrip.getRatio();
+                    int stripwidth = WPCUtils.getScreensInRatio(ratio);
+                    l.trace("\n\n\n\n-----------------");
+                    l.trace(wallpaper.getFilepath());
+                    l.trace("ScreensOfWp={}",screensofWP);
+                    l.trace("ratio={}|{}",ratio[0],ratio[1]);
+                    l.trace("Screenstrip ratio={}|{}",screenstripratio[0],screenstripratio[1]);
+                    l.trace("res={}|{}",wpX,wpY);
+                    if(stripwidth>=screensofWP)
+                    {
+                        
+                        List<Screen> screens = screenstrip.getContents();
+                        l.trace("Screens in Strip={}",screens.size());
+                        int screensOfWP_internal=screensofWP;
+                        if(screens.size()<screensOfWP_internal)
+                        {
+                            screensOfWP_internal=screens.size();
+                        }
+                        int i=0;
+                        while(screens.size()-i>=screensOfWP_internal)
+                        {
+                            int targetWidth=0;
+                            int targetHeight=0;
+                            int base=i;
+                            int old_i=i;
+                            for(;i<screensOfWP_internal+base;i++)
+                            {
+                                Screen screen=screens.get(i);
+                                int screenheight = screen.getH();
+                                if(screenheight>targetHeight)
+                                {
+                                    targetHeight=screenheight;
+                                }
+                                l.trace("Adding {} to screenwidth",screen.getW());
+                                targetWidth+=screen.getW();
+                                l.trace("intermediate TargetWidth ={}",targetWidth);
+                            }
+                            l.trace("TargetWidth={}",targetWidth);
+                            int baseX=0;
+                            i=old_i;
+                            for(;i<screensOfWP_internal+base;i++)
+                            {
+                                /*
+                                set JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" &WPCMgrc.bat -f T:\tests\wpc\2 -p
+                                */
+                                Screen screen=screens.get(i);
+                                int x=screen.getX();
+                                int y=screen.getY();
+                                int sw = screen.getW();
+                                int sh = screen.getH();//page +5+10  balloon.gif
+                                /*String[] core = {"(",
+                                wallpaper.getFilepath(),"-resize",targetWidth+"x"+targetHeight+(allowStretch?"!":">")    
+                                ,")"};*/
+                                String[] wpreplacements = {"black"};
+                                if(debug)
+                                {
+                                    wpreplacements = new String[]{"gray","khaki","yellow","purple"};
+                                }
+                                String[] core = {
+                                "(",
+                                    "(",
+                                        "-size",targetWidth+"x"+targetHeight,"xc:"+wpreplacements[i%wpreplacements.length],"-gravity","center",
+                                        wallpaper.getFilepath(),"-resize",targetWidth+"x"+targetHeight+(allowStretch?"!":">"),"-composite",
+                                    ")",
+                                    "-gravity","northwest","-crop",sw+"x"+sh+"+"+baseX+"+0",
+                                ")"};
+                                l.trace("Screen {}x{}@{}",sw,sh,baseX);
+                                insertIntoConvert(x, y,convertCmd, core);
+
+                                baseX+=sw;
+                                workingSet.remove(screen.getID());
+                            }
+                        }
+                        if(debug)
+                        {
+                            for(;i<screens.size();i++)
+                            {
+                                Screen screen=screens.get(i);
+                                int x=screen.getX();
+                                int y=screen.getY();
+                                int sw = screen.getW();
+                                int sh = screen.getH();//page +5+10  balloon.gif
+                                /*String[] core = {"(",
+                                wallpaper.getFilepath(),"-resize",targetWidth+"x"+targetHeight+(allowStretch?"!":">")    
+                                ,")"};*/
+
+                                String[] core = {
+                                "(",
+                                    "-size",sw+"x"+sh,"xc:green",
+                                ")"};                          
+                                insertIntoConvert(x, y, convertCmd, core);
+                                workingSet.remove(screen.getID());
+                            }
+                        }
+                    }
+                }
+                workingSet.forEach((nothing,screen)->
+                {
+                    int x=screen.getX();
+                    int y=screen.getY();
+                    int sw = screen.getW();
+                    int sh = screen.getH();//page +5+10  balloon.gif
+                    /*String[] core = {"(",
+                    wallpaper.getFilepath(),"-resize",targetWidth+"x"+targetHeight+(allowStretch?"!":">")    
+                    ,")"};*/
+
+                    String[] core = {"(","-size",sw+"x"+sh,debug?"xc:blue":"xc:black","-gravity","center",
+                                fallback.getFilepath(),"-resize",sw+"x"+sh+(fallbackSquashable?"!":">"),"-composite",")"};                          
+                    insertIntoConvert(x, y, convertCmd, core);
+                });
+            }
+            //in_file -crop 40x30+10+10
+            String[] convertEnd = {"-layers" ,"flatten"  ,targetfile};
+            convertCmd.addAll(Arrays.asList(convertEnd));
+
+            Tools.runCmdWithPassthru(IoBuilder.forLogger("External.Imagick").buildPrintStream(), convertCmd.toArray(convertEnd));
+        }
+        return new boolean[]{wallpaperIsSingle,skipped};
+    }
+
+    private static void insertIntoConvert(int x,int y,List<String> convertCmd,String... section)
+    {
+        convertCmd.addAll(Arrays.asList(section));
+        String[] convertSegment;
+        convertSegment = new String[]
+        {
+                "-geometry", "+"+x+"+"+y,"-composite"  
+        };
+        convertCmd.addAll(Arrays.asList(convertSegment));
+        if(x<0)
+        {
+            convertCmd.addAll(Arrays.asList(section));
+            convertSegment = new String[]{
+            "-geometry", "+"+(width+x)+"+"+y,  "-composite"  
+            };
+            convertCmd.addAll(Arrays.asList(convertSegment));
+        }
+        if(y<0)
+        {
+            convertCmd.addAll(Arrays.asList(section));
+            convertSegment = new String[]{
+           "-geometry", "+"+x+"+"+(height+y),  "-composite"  
+            };
+            convertCmd.addAll(Arrays.asList(convertSegment));
+        }
+        if(x<0&&y<0)
+        {
+            convertCmd.addAll(Arrays.asList(section));
+            convertSegment = new String[]{
+            "-geometry", "+"+(width+x)+"+"+(height+y),  "-composite"  
+            };
+            convertCmd.addAll(Arrays.asList(convertSegment));
+        }
+    }
     public static void initPipeLine(String path,String res)
     {
         String[] dirsExist = FileTK.getDirectoryContent(/*args[0]*/path,true);
@@ -338,7 +853,7 @@ public class Synchronizer
         Arrays.stream(dirsExist).filter(t -> !t.startsWith("00_") && new File(basepath+"\\" + t).isDirectory()).forEach(t ->
         {
             
-            System.out.println("Optimieren: Verzeichnis "+t+"(@"+pos+")");
+            l.trace("Optimieren: Verzeichnis {}(@{})",t,pos);
             String path = basepath+"\\" + t;
             FileTK.verzeichnisKillen(new File(path+"\\p"));
             

+ 193 - 36
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/WPCUtils.java

@@ -20,10 +20,25 @@ import de.nplusc.izc.tools.IOtools.FileTK;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import org.apache.commons.cli.ParseException;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.TypeDescription;
 import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor;
+import org.yaml.snakeyaml.introspector.Property;
+import org.yaml.snakeyaml.nodes.Node;
+import org.yaml.snakeyaml.nodes.NodeId;
+import org.yaml.snakeyaml.nodes.NodeTuple;
+import org.yaml.snakeyaml.nodes.ScalarNode;
+import org.yaml.snakeyaml.nodes.Tag;
+import org.yaml.snakeyaml.representer.Representer;
 
 /**
  *
@@ -31,9 +46,13 @@ import org.yaml.snakeyaml.Yaml;
  */
 public class WPCUtils
 {
-    public static void initCache(String dir,String wptargetdir)
+
+    private static final Logger l = LogManager.getLogger();
+
+    public static void initCache(String dir, String wptargetdir)
     {
-        String[] dirs = new String[]{
+        String[] dirs = new String[]
+        {
             "00_meta",
             "00_template\\archv_srcs",
             "00_template\\b-frames",
@@ -45,66 +64,204 @@ public class WPCUtils
         for (String string : dirs)
         {
             //Scheiss gänsefüßchen haben richtiig zu sitzen
-            new File(dir+"\\"+string).mkdirs();
+            new File(dir + "\\" + string).mkdirs();
         }
-        FileTK.writeFile(getInitialMetaState(wptargetdir), dir+"\\00_meta\\state.yml");
-        if(!new File(dir+"\\readme.txt").exists())
+        FileTK.writeFile(getInitialMetaState(wptargetdir), dir + "\\00_meta\\state.yml");
+        if (!new File(dir + "\\readme.txt").exists())
         {
-        FileTK.writeFile("Die Struktur ab L10 ist wie folgt:\n" +
-                        "\n" +
-                        "-+    / Wirzelverzeichnis des Packages\n" +
-                        " +- archv_srcs Wenn Daten in ner Zip kamen diese hier einlagern\n" +
-                        " +- b-frames die wiederkehrenden Bilder des Packages (min 1 nötig)\n" +
-                        " +- k-i-p bilder die proportional bleiben müssen\n" +
-                        " +- p Bilder die verarbeitet wirden (bereits nummeriert)\n" +
-                        " +- proc unverarbeitete bilder die unproportional skaliert werden können\n" +
-                        " +- src unsortiertes Rohmaterial //kann auch in / liegen\n" +
-                        " \n" +
-                        " \n" +
-                        " 00_-verzeichnisse sind Meta-verzeichnisse ohne Pixelinhalt", dir+"\\readme.txt");
+            FileTK.writeFile("Die Struktur ab L10 ist wie folgt:\n"
+                    + "\n"
+                    + "-+    / Wirzelverzeichnis des Packages\n"
+                    + " +- archv_srcs Wenn Daten in ner Zip kamen diese hier einlagern\n"
+                    + " +- b-frames die wiederkehrenden Bilder des Packages (min 1 nötig)\n"
+                    + " +- k-i-p bilder die proportional bleiben müssen\n"
+                    + " +- p Bilder die verarbeitet wirden (bereits nummeriert)\n"
+                    + " +- proc unverarbeitete bilder die unproportional skaliert werden können\n"
+                    + " +- src unsortiertes Rohmaterial //kann auch in / liegen\n"
+                    + " \n"
+                    + " \n"
+                    + " 00_-verzeichnisse sind Meta-verzeichnisse ohne Pixelinhalt", dir + "\\readme.txt");
         }
     }
 
-    
     public static String getInitialMetaState(String wptargetDir)
     {
         DumperOptions yamlOptions = new DumperOptions();
         yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
-        LinkedHashMap<String,Object> m = new LinkedHashMap<>();
-        m.put("HEAD",null);//null heißt frisch
-        m.put("Outdir",wptargetDir);
+        LinkedHashMap<String, Object> m = new LinkedHashMap<>();
+        m.put("HEAD", null);//null heißt frisch
+        m.put("Outdir", wptargetDir);
         return new Yaml(yamlOptions).dump(m);
     }
-    
+
     public static void main(String[] args)
     {
         //FileTK.writeFile(getInitialMetaState(), "T:\\wpc\\00_meta\\state.yml");
     }
-    
-    public static HashMap<String,Object> getConfig(String folder) throws FileNotFoundException
+
+    public static HashMap<String, Object> getConfig(String folder) throws FileNotFoundException
+    {
+        return (LinkedHashMap<String, Object>) new Yaml().load(new FileInputStream(folder + "\\00_meta\\state.yml"));
+    }
+
+    public static void saveConfig(String folder, HashMap<String, Object> config)
+    {
+        DumperOptions yamlOptions = new DumperOptions();
+        yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+        LinkedHashMap<String, Object> m = new LinkedHashMap<>();
+        String o = new Yaml(yamlOptions).dump(config);
+        FileTK.writeFile(o, folder + "\\00_meta\\state.yml");
+    }
+
+    public static CacheState getCacheState(String folder) throws FileNotFoundException
+    {
+        try
+        {
+            return (CacheState) new Yaml(new CustomClassLoaderConstructor(CacheState.class.getClassLoader())).load(new FileInputStream(folder + "\\00_meta\\cachestate.yml"));
+        }
+        catch (FileNotFoundException e)
+        {
+            return new CacheState();
+        }
+    }
+
+    public static void saveCacheState(String folder, CacheState s)
     {
-        return (LinkedHashMap<String,Object>) new Yaml().load(new FileInputStream(folder+"\\00_meta\\state.yml"));
+        DumperOptions yamlOptions = new DumperOptions();
+        yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);//
+        String o = new Yaml(new Representer()
+        {
+
+            @Override
+            protected NodeTuple representJavaBeanProperty(Object javaBean,
+                    Property property,
+                    Object propertyValue,
+                    Tag customTag)
+            {
+                // Hack starts here...
+                //from here: http://stackoverflow.com/a/37809122/1405227
+
+                ScalarNode nodeKey = (ScalarNode) representData(property.getName());
+                // the first occurrence of the node must keep the tag
+                boolean hasAlias = this.representedObjects.containsKey(propertyValue);
+
+                Node nodeValue = representData(propertyValue);
+
+                if (propertyValue != null && !hasAlias)
+                {
+                    NodeId nodeId = nodeValue.getNodeId();
+                    if (customTag == null)
+                    {
+                        if (nodeId == NodeId.scalar)
+                        {
+                            if (propertyValue instanceof Enum<?>)
+                            {
+                                nodeValue.setTag(Tag.STR);
+                            }
+                        }
+            // Copy-paste ends here !!!
+                        // Ignore the else block --always maintain the tag.
+                    }
+                }
+
+                return new NodeTuple(nodeKey, nodeValue);
+            }
+
+        }, yamlOptions).dump(s);
+        FileTK.writeFile(o, folder + "\\00_meta\\cachestate.yml");
     }
+
     private WPCUtils()
     {
     }
+
     @SuppressWarnings("Convert2Diamond") //required, otherwise compiler thinks its too clever
-    public static void addMonitor(HashMap<String,Object> config,String ID,int x,int y,int w,int h)
+    public static void addMonitor(HashMap<String, Object> config, String ID, int x, int y, int w, int h)
     {
-        if(!config.containsKey("MONITORS"))
+        if (!config.containsKey("MONITORS"))
         {
             config.put("MONITORS", new LinkedHashMap<String, int[]>());
         }
-        LinkedHashMap<String,int[]> data = (LinkedHashMap<String,int[]>) config.get("MONITORS");
-        data.put(ID,new int[]{x,y,w,h});
+        LinkedHashMap<String, List<Integer>> data = (LinkedHashMap<String, List<Integer>>) config.get("MONITORS");
+        data.put(ID, Arrays.asList(new Integer[]
+        {
+            x, y, w, h
+        }));
     }
-    
-    public static void saveConfig(String folder,HashMap<String,Object> config)
+
+    public static List<Screen> getScreenlist(HashMap<String, Object> config)
     {
-        DumperOptions yamlOptions = new DumperOptions();
-        yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
-        LinkedHashMap<String,Object> m = new LinkedHashMap<>();
-        String o = new Yaml(yamlOptions).dump(config);
-        FileTK.writeFile(o, folder+"\\00_meta\\state.yml");
+        LinkedHashMap<String, List<Integer>> data = (LinkedHashMap<String, List<Integer>>) config.get("MONITORS");
+        final LinkedList<Screen> retval = new LinkedList<>();
+        data.forEach((k, v) ->
+        {
+            retval.add(new Screen(k, v.get(0), v.get(1), v.get(2), v.get(3)));
+        });
+        return retval;
+    }
+
+    @SuppressWarnings("Convert2Diamond")
+    public static void addMonitorStrip(HashMap<String, Object> config, String ID, String[] monitors) throws ParseException
+    {
+        if (!config.containsKey("MONITORS"))
+        {
+            throw new ParseException("No Monitors defined!, at least one is required to define a Monitor strip");
+        }
+        LinkedHashMap<String, List<Integer>> monitorBase = (LinkedHashMap<String, List<Integer>>) config.get("MONITORS");
+        for (String monitor : monitors)
+        {
+            if (!monitorBase.containsKey(monitor))
+            {
+                throw new ParseException("Invalid Monitor ID: " + monitor);
+            }
+        }
+        if (!config.containsKey("MONITORSTRIPS"))
+        {
+            config.put("MONITORSTRIPS", new LinkedHashMap<String, String>());
+        }
+        LinkedHashMap<String, List<String>> data = (LinkedHashMap<String, List<String>>) config.get("MONITORSTRIPS");
+        data.put(ID, Arrays.asList(monitors));
+    }
+
+    public static int[] getRatio(int width, int height)
+    {
+        double ratioWidth = ((double) width) / ((double) height) * 10.0d;
+
+        int[] closestRatio = null;
+        double closestRatioDistance = 100000.0d;
+
+        for (int[][] SCREENRATIOS : Constants.SCREENRATIOS)
+        {
+            for (int[] screenratio_element : SCREENRATIOS)
+            {
+                double newRatio = ((double) screenratio_element[0]) / ((double) screenratio_element[1]) * 10.0d;
+                double newdiff = Math.abs(newRatio - ratioWidth);
+                if (newdiff < closestRatioDistance)
+                {
+                    closestRatioDistance = newdiff;
+                    closestRatio = screenratio_element;
+                }
+            }
+        }
+        return closestRatio;
+    }
+    public static int getScreensInRatio(int[] ratio)
+    {
+        int i=0;
+        boolean found=false;
+        for(;i<Constants.SCREENRATIOS.length;i++)
+        {
+            if(Arrays.asList(Constants.SCREENRATIOS[i]).contains(ratio))
+            {
+                found=true;
+                break;
+            }
+        }
+        if(!found)
+        {
+            i=-2;
+        }
+        l.trace("raw screenratio={}",i);
+        return i+1;
     }
 }

+ 86 - 0
WPCMGr/src/main/java/de/nplusc/izc/Utilities/WPCMgr/Wallpaper.java

@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 iZc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.nplusc.izc.Utilities.WPCMgr;
+
+import java.util.Objects;
+
+/**
+ *
+ * @author iZc <nplusc.de>
+ */
+public class Wallpaper
+{
+    
+    public int getScreenHash()
+    {
+        return screenHash;
+    }
+
+    public void setScreenHash(int screenHash)
+    {
+        this.screenHash = screenHash;
+    }
+
+    public String getFilepath()
+    {
+        return filepath;
+    }
+
+    public void setFilepath(String filepath)
+    {
+        this.filepath = filepath;
+    }
+
+    public Wallpaper(int screenHash, String filepath)
+    {
+        this.screenHash = screenHash;
+        this.filepath = filepath;
+    }
+    
+    public Wallpaper(){};
+    
+    private int screenHash;
+    private String filepath;
+
+    @Override
+    public int hashCode()
+    {
+        int hash = 7;
+        hash = 23 * hash + Objects.hashCode(this.filepath);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == null)
+        {
+            return false;
+        }
+        if (getClass() != obj.getClass())
+        {
+            return false;
+        }
+        final Wallpaper other = (Wallpaper) obj;
+        if (!Objects.equals(this.filepath, other.filepath))
+        {
+            return false;
+        }
+        return true;
+    }
+    
+}

+ 2 - 2
WPCMGr/src/main/resources/log4j2.xml

@@ -10,7 +10,7 @@
         </Console>
         
         
-        <RollingFile name="logfile" fileName="izpl.log" filePattern="izpl-%i.log">
+        <RollingFile name="logfile" fileName="WallpaperManager.log" filePattern="WallpaperManager-%i.log">
         <Policies>
             <OnStartupTriggeringPolicy />
             </Policies>
@@ -18,7 +18,7 @@
             <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %l - %msg%n"/>
         </RollingFile>   
 
-        <RollingFile name="logfileExternal" fileName="izpl.log" filePattern="izpl-%i.log">
+        <RollingFile name="logfile" fileName="WallpaperManager.log" filePattern="WallpaperManager-%i.log">
         <Policies>
             <OnStartupTriggeringPolicy />
             </Policies>

+ 92 - 82
external/java-progressbar/src/main/java/hu/ssh/progressbar/AbstractProgressBar.java

@@ -1,82 +1,92 @@
-package hu.ssh.progressbar;
-
-public abstract class AbstractProgressBar<T extends AbstractProgressBar<?>> implements ProgressBar<T> {
-	protected final long totalSteps;
-
-	private long actualSteps = 0;
-	private long startTime = 0;
-
-	private long lastUpdate = 0;
-	private int lastUpdatePercent = 0;
-
-	protected AbstractProgressBar(final long totalSteps) {
-		this.totalSteps = totalSteps;
-	}
-
-	@Override
-	public final void start() {
-		refresh();
-	}
-
-	@Override
-	public final void tickOne() {
-		tick(1);
-	}
-
-	@Override
-	public final void tick(final long steps) {
-		setStartTimeIfNotStarted();
-
-		actualSteps += steps;
-
-		if (isRefreshNeeded()) {
-			refresh();
-		}
-	}
-
-	@Override
-	public final void refresh() {
-		setStartTimeIfNotStarted();
-
-		final Progress progress = getProgress();
-
-		lastUpdate = System.currentTimeMillis() / 1000;
-		lastUpdatePercent = (int) (progress.getPercentage() * 100);
-
-		updateProgressBar(progress);
-	}
-
-	@Override
-	public final void complete() {
-		setStartTimeIfNotStarted();
-
-		actualSteps = totalSteps;
-		refresh();
-	}
-
-	private Progress getProgress() {
-		return new Progress(totalSteps, actualSteps, System.currentTimeMillis() - startTime);
-	}
-
-	private void setStartTimeIfNotStarted() {
-		if (startTime == 0) {
-			startTime = System.currentTimeMillis();
-		}
-	}
-
-	private boolean isRefreshNeeded() {
-		if (lastUpdate != System.currentTimeMillis() / 1000) {
-			return true;
-		}
-
-		if (lastUpdatePercent != (int) (actualSteps * 100 / totalSteps)) {
-			return true;
-		}
-
-		return false;
-	}
-
-	protected abstract void updateProgressBar(final Progress progress);
-
-	protected abstract void finishProgressBar();
-}
+package hu.ssh.progressbar;
+
+public abstract class AbstractProgressBar<T extends AbstractProgressBar<?>> implements ProgressBar<T> {
+	protected final long totalSteps;
+
+	private long actualSteps = 0;
+	private long startTime = 0;
+        private String message = "";
+	private long lastUpdate = 0;
+	private int lastUpdatePercent = 0;
+
+	protected AbstractProgressBar(final long totalSteps) {
+		this.totalSteps = totalSteps;
+	}
+
+	@Override
+	public final void start() {
+		refresh();
+	}
+
+	@Override
+	public final void tickOne() {
+		tick(1);
+	}
+
+	@Override
+	public final void tick(final long steps) {
+		setStartTimeIfNotStarted();
+
+		actualSteps += steps;
+
+		if (isRefreshNeeded()) {
+			refresh();
+		}
+	}
+
+	@Override
+	public final void refresh() {
+		setStartTimeIfNotStarted();
+
+		final Progress progress = getProgress();
+
+		lastUpdate = System.currentTimeMillis() / 1000;
+		lastUpdatePercent = (int) (progress.getPercentage() * 100);
+
+		updateProgressBar(progress);
+	}
+
+	@Override
+	public final void complete() {
+		setStartTimeIfNotStarted();
+
+		actualSteps = totalSteps;
+		refresh();
+	}
+
+        public String getMessage()
+        {
+            return message;
+        }
+
+        public void setMessage(String message)
+        {
+            this.message = message;
+        }
+        
+	private Progress getProgress() {
+		return new Progress(totalSteps, actualSteps, System.currentTimeMillis() - startTime,message);
+	}
+
+	private void setStartTimeIfNotStarted() {
+		if (startTime == 0) {
+			startTime = System.currentTimeMillis();
+		}
+	}
+
+	private boolean isRefreshNeeded() {
+		if (lastUpdate != System.currentTimeMillis() / 1000) {
+			return true;
+		}
+
+		if (lastUpdatePercent != (int) (actualSteps * 100 / totalSteps)) {
+			return true;
+		}
+
+		return false;
+	}
+
+	protected abstract void updateProgressBar(final Progress progress);
+
+	protected abstract void finishProgressBar();
+}

+ 49 - 42
external/java-progressbar/src/main/java/hu/ssh/progressbar/Progress.java

@@ -1,43 +1,50 @@
-package hu.ssh.progressbar;
-
-public class Progress {
-	private static final int MINIMAL_ELAPSED = 100;
-
-	private final long totalSteps;
-	private final long actualSteps;
-	private final long elapsedTime;
-
-	public Progress(final long totalSteps, final long actualSteps, final long elapsedTime) {
-		this.totalSteps = totalSteps;
-		this.actualSteps = actualSteps;
-		this.elapsedTime = elapsedTime;
-	}
-
-	public final long getTotalSteps() {
-		return totalSteps;
-	}
-
-	public final long getActualSteps() {
-		return actualSteps;
-	}
-
-	public final long getElapsedTime() {
-		return elapsedTime;
-	}
-
-	public final float getPercentage() {
-		return (float) actualSteps / totalSteps;
-	}
-
-	public final long getRemainingTime() {
-		return getTotalTime() - elapsedTime;
-	}
-
-	public final long getTotalTime() {
-		return (long) (elapsedTime / getPercentage());
-	}
-
-	public final boolean isRemainingTimeReliable() {
-		return elapsedTime > MINIMAL_ELAPSED;
-	}
+package hu.ssh.progressbar;
+
+public class Progress {
+	private static final int MINIMAL_ELAPSED = 100;
+
+	private final long totalSteps;
+	private final long actualSteps;
+	private final long elapsedTime;
+        private final String message;
+
+	public Progress(final long totalSteps, final long actualSteps, final long elapsedTime, final String message) {
+		this.totalSteps = totalSteps;
+		this.actualSteps = actualSteps;
+		this.elapsedTime = elapsedTime;
+                this.message=message;
+	}
+
+	public final long getTotalSteps() {
+		return totalSteps;
+	}
+
+	public final long getActualSteps() {
+		return actualSteps;
+	}
+
+	public final long getElapsedTime() {
+		return elapsedTime;
+	}
+
+	public final float getPercentage() {
+		return (float) actualSteps / totalSteps;
+	}
+
+	public final long getRemainingTime() {
+		return getTotalTime() - elapsedTime;
+	}
+
+	public final long getTotalTime() {
+		return (long) (elapsedTime / getPercentage());
+	}
+
+	public final boolean isRemainingTimeReliable() {
+		return elapsedTime > MINIMAL_ELAPSED;
+	}
+
+        public final String getMessage() {
+		return message;
+        }
+        
 }

+ 196 - 192
external/java-progressbar/src/main/java/hu/ssh/progressbar/console/ConsoleProgressBar.java

@@ -1,193 +1,197 @@
-package hu.ssh.progressbar.console;
-
-import hu.ssh.progressbar.AbstractProgressBar;
-import hu.ssh.progressbar.Progress;
-import hu.ssh.progressbar.console.replacers.BarReplacer;
-import hu.ssh.progressbar.console.replacers.ElapsedTimeReplacer;
-import hu.ssh.progressbar.console.replacers.PercentageReplacer;
-import hu.ssh.progressbar.console.replacers.RemainingTimeReplacer;
-import hu.ssh.progressbar.console.replacers.Replacer;
-import hu.ssh.progressbar.console.replacers.TotalTimeReplacer;
-
-import java.io.PrintStream;
-import java.util.Collection;
-import java.util.Set;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableSet;
-
-/**
- * A console progress bar.
- * <p>
- * It can display a human readable progress bar with the specified format on the selected
- * output.
- * <p>
- * Here is a basic usage:
- *
- * <pre>
- * ProgressBar progressBar = ConsoleProgressBar.on(System.out);
- * progressBar.tick(20);
- * progressBar.finish();
- * </pre>
- *
- * It can be configured with custom format:
- *
- * <pre>
- * ProgressBar progressBar = ConsoleProgressBar.on(System.out)
- * 		.withFormat(&quot;[:bar]&quot;);
- * </pre>
- *
- * Or can be set to use custom number of steps instead of the default <code>100</code>:
- *
- * <pre>
- * ProgressBar progressBar = ConsoleProgressBar.on(System.out)
- * 		.withTotalSteps(25);
- * </pre>
- *
- * @author KARASZI István (github@spam.raszi.hu)
- */
-public final class ConsoleProgressBar extends AbstractProgressBar<ConsoleProgressBar> {
-	public static final char LINE_FEED = '\n';
-	public static final char CARRIAGE_RETURN = '\r';
-
-	public static final long DEFAULT_STEPS = 100;
-	public static final String DEFAULT_FORMAT = "[:bar] :percent% :eta";
-	public static final int DEFAULT_PROGRESSBAR_WIDTH = 60;
-	private static final Set<Replacer> DEFAULT_REPLACERS = getDefaultReplacers(DEFAULT_PROGRESSBAR_WIDTH);
-
-	private final Set<Replacer> replacers;
-	private final PrintStream streamToUse;
-	private final String outputFormat;
-
-	private int previousLength = 0;
-
-	private ConsoleProgressBar(
-			final PrintStream streamToUse,
-			final long totalSteps,
-			final String progressBarFormat,
-			final Set<Replacer> replacers)
-	{
-		super(totalSteps);
-
-		this.replacers = replacers;
-		this.streamToUse = streamToUse;
-		this.outputFormat = progressBarFormat;
-	}
-
-	/**
-	 * A console progress bar on the selected PrintStream.
-	 *
-	 * @param streamToUse
-	 *            the PrintStream on the ProgressBar should appear
-	 * @return a progress bar with the desired configuration
-	 */
-	public static ConsoleProgressBar on(final PrintStream streamToUse) {
-		Preconditions.checkNotNull(streamToUse);
-
-		return new ConsoleProgressBar(streamToUse,
-				DEFAULT_STEPS,
-				DEFAULT_FORMAT,
-				DEFAULT_REPLACERS);
-	}
-
-	/**
-	 * Changes the output format of the actual ProgressBar.
-	 *
-	 * @param outputFormat
-	 *            the new output format
-	 * @return a progress bar with the desired configuration
-	 */
-	public ConsoleProgressBar withFormat(final String outputFormat) {
-		Preconditions.checkNotNull(outputFormat);
-
-		return new ConsoleProgressBar(streamToUse,
-				totalSteps,
-				outputFormat,
-				replacers);
-	}
-
-	@Override
-	public ConsoleProgressBar withTotalSteps(final int totalSteps) {
-		Preconditions.checkArgument(totalSteps != 0);
-
-		return new ConsoleProgressBar(streamToUse,
-				totalSteps,
-				outputFormat,
-				replacers);
-	}
-
-	/**
-	 * Changes the replacers for the actual ProgressBar.
-	 *
-	 * @param replacers
-	 *            the new replacers to use
-	 * @return a progress bar with the desired configuration
-	 */
-	public ConsoleProgressBar withReplacers(final Collection<Replacer> replacers) {
-		Preconditions.checkNotNull(replacers);
-
-		return new ConsoleProgressBar(streamToUse,
-				totalSteps,
-				outputFormat,
-				ImmutableSet.copyOf(replacers));
-	}
-
-	/**
-	 * Gets the default replacers.
-	 *
-	 * @param progressBarWidth
-	 *            the width of the progress bar
-	 * @return the configured replacers
-	 */
-	public static Set<Replacer> getDefaultReplacers(final int progressBarWidth) {
-		return ImmutableSet.of(
-				new BarReplacer(progressBarWidth),
-				new PercentageReplacer(),
-				new RemainingTimeReplacer(),
-				new ElapsedTimeReplacer(),
-				new TotalTimeReplacer()
-				);
-	}
-
-	@Override
-	protected void updateProgressBar(final Progress progress) {
-		final String actualBar = getActualProgressBar(progress);
-
-		streamToUse.print(actualBar);
-		streamToUse.print(getGarbageCleaning(actualBar.length()));
-		streamToUse.print(CARRIAGE_RETURN);
-	}
-
-	@Override
-	protected void finishProgressBar() {
-		streamToUse.print(LINE_FEED);
-	}
-
-	private String getActualProgressBar(final Progress progress) {
-		String bar = outputFormat;
-
-		for (final Replacer replacer : replacers) {
-			final String identifier = replacer.getReplaceIdentifier();
-
-			if (!bar.contains(identifier)) {
-				continue;
-			}
-
-			bar = bar.replace(identifier, replacer.getReplacementForProgress(progress));
-		}
-
-		return bar;
-	}
-
-	private String getGarbageCleaning(final int actualLength) {
-		if (actualLength >= previousLength) {
-			return "";
-		}
-
-		final String garbageCleaner = Strings.repeat(" ", previousLength - actualLength);
-		previousLength = actualLength;
-
-		return garbageCleaner;
-	}
+package hu.ssh.progressbar.console;
+
+import hu.ssh.progressbar.AbstractProgressBar;
+import hu.ssh.progressbar.Progress;
+import hu.ssh.progressbar.console.replacers.BarReplacer;
+import hu.ssh.progressbar.console.replacers.ElapsedTimeReplacer;
+import hu.ssh.progressbar.console.replacers.PercentageReplacer;
+import hu.ssh.progressbar.console.replacers.RemainingTimeReplacer;
+import hu.ssh.progressbar.console.replacers.Replacer;
+import hu.ssh.progressbar.console.replacers.TotalTimeReplacer;
+
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.Set;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
+import hu.ssh.progressbar.console.replacers.MessageReplacer;
+
+/**
+ * A console progress bar.
+ * <p>
+ * It can display a human readable progress bar with the specified format on the selected
+ * output.
+ * <p>
+ * Here is a basic usage:
+ *
+ * <pre>
+ * ProgressBar progressBar = ConsoleProgressBar.on(System.out);
+ * progressBar.tick(20);
+ * progressBar.finish();
+ * </pre>
+ *
+ * It can be configured with custom format:
+ *
+ * <pre>
+ * ProgressBar progressBar = ConsoleProgressBar.on(System.out)
+ * 		.withFormat(&quot;[:bar]&quot;);
+ * </pre>
+ *
+ * Or can be set to use custom number of steps instead of the default <code>100</code>:
+ *
+ * <pre>
+ * ProgressBar progressBar = ConsoleProgressBar.on(System.out)
+ * 		.withTotalSteps(25);
+ * </pre>
+ *
+ * @author KARASZI István (github@spam.raszi.hu)
+ */
+public final class ConsoleProgressBar extends AbstractProgressBar<ConsoleProgressBar> {
+	public static final char LINE_FEED = '\n';
+	public static final char CARRIAGE_RETURN = '\r';
+
+	public static final long DEFAULT_STEPS = 100;
+	public static final String DEFAULT_FORMAT = "[:bar] :percent% :eta";
+	public static final int DEFAULT_PROGRESSBAR_WIDTH = 60;
+	private static final Set<Replacer> DEFAULT_REPLACERS = getDefaultReplacers(DEFAULT_PROGRESSBAR_WIDTH);
+
+	private final Set<Replacer> replacers;
+	private final PrintStream streamToUse;
+	private final String outputFormat;
+        
+        
+        
+	private int previousLength = 0;
+
+	private ConsoleProgressBar(
+			final PrintStream streamToUse,
+			final long totalSteps,
+			final String progressBarFormat,
+			final Set<Replacer> replacers)
+	{
+		super(totalSteps);
+
+		this.replacers = replacers;
+		this.streamToUse = streamToUse;
+		this.outputFormat = progressBarFormat;
+	}
+
+	/**
+	 * A console progress bar on the selected PrintStream.
+	 *
+	 * @param streamToUse
+	 *            the PrintStream on the ProgressBar should appear
+	 * @return a progress bar with the desired configuration
+	 */
+	public static ConsoleProgressBar on(final PrintStream streamToUse) {
+		Preconditions.checkNotNull(streamToUse);
+
+		return new ConsoleProgressBar(streamToUse,
+				DEFAULT_STEPS,
+				DEFAULT_FORMAT,
+				DEFAULT_REPLACERS);
+	}
+
+	/**
+	 * Changes the output format of the actual ProgressBar.
+	 *
+	 * @param outputFormat
+	 *            the new output format
+	 * @return a progress bar with the desired configuration
+	 */
+	public ConsoleProgressBar withFormat(final String outputFormat) {
+		Preconditions.checkNotNull(outputFormat);
+
+		return new ConsoleProgressBar(streamToUse,
+				totalSteps,
+				outputFormat,
+				replacers);
+	}
+
+	@Override
+	public ConsoleProgressBar withTotalSteps(final int totalSteps) {
+		Preconditions.checkArgument(totalSteps != 0);
+
+		return new ConsoleProgressBar(streamToUse,
+				totalSteps,
+				outputFormat,
+				replacers);
+	}        
+        
+	/**
+	 * Changes the replacers for the actual ProgressBar.
+	 *
+	 * @param replacers
+	 *            the new replacers to use
+	 * @return a progress bar with the desired configuration
+	 */
+	public ConsoleProgressBar withReplacers(final Collection<Replacer> replacers) {
+		Preconditions.checkNotNull(replacers);
+
+		return new ConsoleProgressBar(streamToUse,
+				totalSteps,
+				outputFormat,
+				ImmutableSet.copyOf(replacers));
+	}
+
+	/**
+	 * Gets the default replacers.
+	 *
+	 * @param progressBarWidth
+	 *            the width of the progress bar
+	 * @return the configured replacers
+	 */
+	public static Set<Replacer> getDefaultReplacers(final int progressBarWidth) {
+		return ImmutableSet.of(
+				new BarReplacer(progressBarWidth),
+				new PercentageReplacer(),
+				new RemainingTimeReplacer(),
+				new ElapsedTimeReplacer(),
+				new TotalTimeReplacer(),
+                                new MessageReplacer()
+				);
+	}
+
+	@Override
+	protected void updateProgressBar(final Progress progress) {
+		final String actualBar = getActualProgressBar(progress);
+
+		streamToUse.print(actualBar);
+		streamToUse.print(getGarbageCleaning(actualBar.length()));
+		streamToUse.print(CARRIAGE_RETURN);
+	}
+
+	@Override
+	protected void finishProgressBar() {
+		streamToUse.print(LINE_FEED);
+	}
+
+	private String getActualProgressBar(final Progress progress) {
+		String bar = outputFormat;
+
+		for (final Replacer replacer : replacers) {
+			final String identifier = replacer.getReplaceIdentifier();
+
+			if (!bar.contains(identifier)) {
+				continue;
+			}
+
+			bar = bar.replace(identifier, replacer.getReplacementForProgress(progress));
+		}
+
+		return bar;
+	}
+
+	private String getGarbageCleaning(final int actualLength) {
+		if (actualLength >= previousLength) {
+			return "";
+		}
+
+		final String garbageCleaner = Strings.repeat(" ", previousLength - actualLength);
+		previousLength = actualLength;
+
+		return garbageCleaner;
+	}
 }

+ 38 - 0
external/java-progressbar/src/main/java/hu/ssh/progressbar/console/replacers/MessageReplacer.java

@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 iZc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package hu.ssh.progressbar.console.replacers;
+
+import hu.ssh.progressbar.Progress;
+
+/**
+ *
+ * @author iZc <nplusc.de>
+ */
+public class MessageReplacer implements Replacer
+{
+    	private static final String IDENTIFIER = ":msg";
+
+	@Override
+	public final String getReplaceIdentifier() {
+		return IDENTIFIER;
+	}
+
+	@Override
+	public final String getReplacementForProgress(final Progress progress) {
+		return progress.getMessage();
+	}
+}

+ 30 - 30
external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestBarReplacer.java

@@ -1,30 +1,30 @@
-package hu.ssh.test.progressbar.console.replacers;
-
-import hu.ssh.progressbar.Progress;
-import hu.ssh.progressbar.console.replacers.BarReplacer;
-
-import java.util.Iterator;
-
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-public class TestBarReplacer {
-	@DataProvider
-	protected final Iterator<Object[]> getExampleBarContents() {
-		return ImmutableList.of(
-				new Object[] { new Progress(5, 0, 0), "-----" },
-				new Object[] { new Progress(5, 2, 0), "==---" },
-				new Object[] { new Progress(5, 3, 0), "===--" },
-				new Object[] { new Progress(5, 5, 0), "=====" }
-				).iterator();
-	}
-
-	@Test(dataProvider = "getExampleBarContents")
-	public final void testBarReplacer(final Progress progress, final String expectedContent) {
-		final BarReplacer replacer = new BarReplacer(5);
-		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
-	}
-}
+package hu.ssh.test.progressbar.console.replacers;
+
+import hu.ssh.progressbar.Progress;
+import hu.ssh.progressbar.console.replacers.BarReplacer;
+
+import java.util.Iterator;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestBarReplacer {
+	@DataProvider
+	protected final Iterator<Object[]> getExampleBarContents() {
+		return ImmutableList.of(
+				new Object[] { new Progress(5, 0, 0,""), "-----" },
+				new Object[] { new Progress(5, 2, 0,""), "==---" },
+				new Object[] { new Progress(5, 3, 0,""), "===--" },
+				new Object[] { new Progress(5, 5, 0,""), "=====" }
+				).iterator();
+	}
+
+	@Test(dataProvider = "getExampleBarContents")
+	public final void testBarReplacer(final Progress progress, final String expectedContent) {
+		final BarReplacer replacer = new BarReplacer(5);
+		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
+	}
+}

+ 31 - 31
external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestElapsedTimeReplacer.java

@@ -1,31 +1,31 @@
-package hu.ssh.test.progressbar.console.replacers;
-
-import hu.ssh.progressbar.Progress;
-import hu.ssh.progressbar.console.replacers.ElapsedTimeReplacer;
-
-import java.util.Iterator;
-
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-public class TestElapsedTimeReplacer {
-	@DataProvider
-	protected final Iterator<Object[]> getExampleTotalTimeContents() {
-		return ImmutableList.of(
-				new Object[] { new Progress(5, 0, 0), "0ms" },
-				new Object[] { new Progress(5, 2, 200), "200ms" },
-				new Object[] { new Progress(5, 3, 3000), "3s" },
-				new Object[] { new Progress(5, 5, 200), "200ms" }
-				).iterator();
-	}
-
-	@Test(dataProvider = "getExampleTotalTimeContents")
-	public final void testElapsedTimeReplacer(final Progress progress, final String expectedContent) {
-		final ElapsedTimeReplacer replacer = new ElapsedTimeReplacer();
-		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
-	}
-}
-
+package hu.ssh.test.progressbar.console.replacers;
+
+import hu.ssh.progressbar.Progress;
+import hu.ssh.progressbar.console.replacers.ElapsedTimeReplacer;
+
+import java.util.Iterator;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestElapsedTimeReplacer {
+	@DataProvider
+	protected final Iterator<Object[]> getExampleTotalTimeContents() {
+		return ImmutableList.of(
+				new Object[] { new Progress(5, 0, 0,""), "0ms" },
+				new Object[] { new Progress(5, 2, 200,""), "200ms" },
+				new Object[] { new Progress(5, 3, 3000,""), "3s" },
+				new Object[] { new Progress(5, 5, 200,""), "200ms" }
+				).iterator();
+	}
+
+	@Test(dataProvider = "getExampleTotalTimeContents")
+	public final void testElapsedTimeReplacer(final Progress progress, final String expectedContent) {
+		final ElapsedTimeReplacer replacer = new ElapsedTimeReplacer();
+		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
+	}
+}
+

+ 29 - 0
external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestMessageReplacer.java

@@ -0,0 +1,29 @@
+package hu.ssh.test.progressbar.console.replacers;
+
+import hu.ssh.progressbar.Progress;
+import hu.ssh.progressbar.console.replacers.MessageReplacer;
+
+import java.util.Iterator;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+
+public class TestMessageReplacer {
+	@DataProvider
+	protected final Iterator<Object[]> getExampleMessageContents() {
+		return ImmutableList.of(
+				new Object[] { new Progress(5, 0, 0,"AAA"), "AAA" },
+				new Object[] { new Progress(5, 2, 200,"Test"), "Test" }
+				).iterator();
+	}
+
+	@Test(dataProvider = "getExampleMessageContents")
+	public final void testTotalTimeReplacer(final Progress progress, final String expectedContent) {
+		final MessageReplacer replacer = new MessageReplacer();
+		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
+	}
+}

+ 30 - 30
external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestPercentageReplacer.java

@@ -1,30 +1,30 @@
-package hu.ssh.test.progressbar.console.replacers;
-
-import hu.ssh.progressbar.Progress;
-import hu.ssh.progressbar.console.replacers.PercentageReplacer;
-
-import java.util.Iterator;
-
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-public class TestPercentageReplacer {
-	@DataProvider
-	protected final Iterator<Object[]> getExamplePercentageContents() {
-		return ImmutableList.of(
-				new Object[] { new Progress(5, 0, 0), "  0.00" },
-				new Object[] { new Progress(5, 2, 200), " 40.00" },
-				new Object[] { new Progress(5, 3, 3000), " 60.00" },
-				new Object[] { new Progress(5, 5, 200), "100.00" }
-				).iterator();
-	}
-
-	@Test(dataProvider = "getExamplePercentageContents")
-	public final void testPercentageReplacer(final Progress progress, final String expectedContent) {
-		final PercentageReplacer replacer = new PercentageReplacer();
-		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
-	}
-}
+package hu.ssh.test.progressbar.console.replacers;
+
+import hu.ssh.progressbar.Progress;
+import hu.ssh.progressbar.console.replacers.PercentageReplacer;
+
+import java.util.Iterator;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestPercentageReplacer {
+	@DataProvider
+	protected final Iterator<Object[]> getExamplePercentageContents() {
+		return ImmutableList.of(
+				new Object[] { new Progress(5, 0, 0,""), "  0.00" },
+				new Object[] { new Progress(5, 2, 200,""), " 40.00" },
+				new Object[] { new Progress(5, 3, 3000,""), " 60.00" },
+				new Object[] { new Progress(5, 5, 200,""), "100.00" }
+				).iterator();
+	}
+
+	@Test(dataProvider = "getExamplePercentageContents")
+	public final void testPercentageReplacer(final Progress progress, final String expectedContent) {
+		final PercentageReplacer replacer = new PercentageReplacer();
+		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
+	}
+}

+ 30 - 30
external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestRemainingTimeReplacer.java

@@ -1,30 +1,30 @@
-package hu.ssh.test.progressbar.console.replacers;
-
-import hu.ssh.progressbar.Progress;
-import hu.ssh.progressbar.console.replacers.RemainingTimeReplacer;
-
-import java.util.Iterator;
-
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-public class TestRemainingTimeReplacer {
-	@DataProvider
-	protected final Iterator<Object[]> getExampleRemainingTimeContents() {
-		return ImmutableList.of(
-				new Object[] { new Progress(5, 0, 0), "?" },
-				new Object[] { new Progress(5, 2, 200), "300ms" },
-				new Object[] { new Progress(5, 3, 3000), "2s" },
-				new Object[] { new Progress(5, 5, 200), "0ms" }
-				).iterator();
-	}
-
-	@Test(dataProvider = "getExampleRemainingTimeContents")
-	public final void testRemaingingTimeReplacer(final Progress progress, final String expectedContent) {
-		final RemainingTimeReplacer replacer = new RemainingTimeReplacer();
-		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
-	}
-}
+package hu.ssh.test.progressbar.console.replacers;
+
+import hu.ssh.progressbar.Progress;
+import hu.ssh.progressbar.console.replacers.RemainingTimeReplacer;
+
+import java.util.Iterator;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestRemainingTimeReplacer {
+	@DataProvider
+	protected final Iterator<Object[]> getExampleRemainingTimeContents() {
+		return ImmutableList.of(
+				new Object[] { new Progress(5, 0, 0,""), "?" },
+				new Object[] { new Progress(5, 2, 200,""), "300ms" },
+				new Object[] { new Progress(5, 3, 3000,""), "2s" },
+				new Object[] { new Progress(5, 5, 200,""), "0ms" }
+				).iterator();
+	}
+
+	@Test(dataProvider = "getExampleRemainingTimeContents")
+	public final void testRemaingingTimeReplacer(final Progress progress, final String expectedContent) {
+		final RemainingTimeReplacer replacer = new RemainingTimeReplacer();
+		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
+	}
+}

+ 30 - 30
external/java-progressbar/src/test/java/hu/ssh/test/progressbar/console/replacers/TestTotalTimeReplacer.java

@@ -1,30 +1,30 @@
-package hu.ssh.test.progressbar.console.replacers;
-
-import hu.ssh.progressbar.Progress;
-import hu.ssh.progressbar.console.replacers.TotalTimeReplacer;
-
-import java.util.Iterator;
-
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-public class TestTotalTimeReplacer {
-	@DataProvider
-	protected final Iterator<Object[]> getExampleTotalTimeContents() {
-		return ImmutableList.of(
-				new Object[] { new Progress(5, 0, 0), "?" },
-				new Object[] { new Progress(5, 2, 200), "500ms" },
-				new Object[] { new Progress(5, 3, 3000), "5s" },
-				new Object[] { new Progress(5, 5, 200), "200ms" }
-				).iterator();
-	}
-
-	@Test(dataProvider = "getExampleTotalTimeContents")
-	public final void testTotalTimeReplacer(final Progress progress, final String expectedContent) {
-		final TotalTimeReplacer replacer = new TotalTimeReplacer();
-		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
-	}
-}
+package hu.ssh.test.progressbar.console.replacers;
+
+import hu.ssh.progressbar.Progress;
+import hu.ssh.progressbar.console.replacers.TotalTimeReplacer;
+
+import java.util.Iterator;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestTotalTimeReplacer {
+	@DataProvider
+	protected final Iterator<Object[]> getExampleTotalTimeContents() {
+		return ImmutableList.of(
+				new Object[] { new Progress(5, 0, 0,""), "?" },
+				new Object[] { new Progress(5, 2, 200,""), "500ms" },
+				new Object[] { new Progress(5, 3, 3000,""), "5s" },
+				new Object[] { new Progress(5, 5, 200,""), "200ms" }
+				).iterator();
+	}
+
+	@Test(dataProvider = "getExampleTotalTimeContents")
+	public final void testTotalTimeReplacer(final Progress progress, final String expectedContent) {
+		final TotalTimeReplacer replacer = new TotalTimeReplacer();
+		Assert.assertEquals(replacer.getReplacementForProgress(progress), expectedContent);
+	}
+}