View Javadoc
1   package com.github.celldynamics.quimp.utils;
2   
3   import java.io.IOException;
4   import java.net.URL;
5   import java.text.SimpleDateFormat;
6   import java.time.Instant;
7   import java.time.format.DateTimeFormatter;
8   import java.time.temporal.TemporalAccessor;
9   import java.util.Arrays;
10  import java.util.Date;
11  import java.util.Enumeration;
12  import java.util.jar.Attributes;
13  import java.util.jar.Manifest;
14  
15  import org.apache.commons.lang3.text.WordUtils;
16  import org.slf4j.Logger;
17  import org.slf4j.LoggerFactory;
18  
19  import com.github.celldynamics.quimp.Outline;
20  import com.github.celldynamics.quimp.PropertyReader;
21  import com.github.celldynamics.quimp.QuimP;
22  import com.github.celldynamics.quimp.QuimpVersion;
23  import com.github.celldynamics.quimp.Vert;
24  
25  /**
26   * Collection of tools used across QuimP.
27   * 
28   * @author Richard
29   * @author p.baniukiewicz
30   */
31  public class QuimpToolsCollection {
32  
33    /**
34     * The Constant LOGGER.
35     */
36    static final Logger LOGGER = LoggerFactory.getLogger(QuimpToolsCollection.class.getName());
37    /**
38     * Message returned by {@link #getQuimPBuildInfo()} if info is not found in jar.
39     */
40    public static final String defNote = "0.0.0";
41  
42    /**
43     * Prepare info plate for QuimP.
44     * 
45     * @return QuimP version
46     * 
47     * @see #getFormattedQuimPversion(QuimpVersion)
48     */
49    public String getQuimPversion() {
50      QuimpVersion quimpBuildInfo = getQuimPBuildInfo();
51      return getFormattedQuimPversion(quimpBuildInfo);
52    }
53  
54    /**
55     * Prepare info plate for QuimP.
56     * 
57     * <p>It contains version, names, etc. By general QuimpToolsCollection class is static. These
58     * methods can not be so they must be called:
59     * 
60     * <pre>
61     * <code>LOGGER.debug(new Tool().getQuimPversion());</code>
62     * </pre>
63     * 
64     * @param quimpBuildInfo info read from jar
65     * @return Formatted string with QuimP version and authors
66     * @see #getQuimPBuildInfo()
67     */
68    public static String getFormattedQuimPversion(QuimpVersion quimpBuildInfo) {
69      //!>
70      String infoPlate = "---------------------------------------------------------\n"
71              + "| QuimP, by                                             |\n"
72              + "| Richard Tyson (richard.tyson@warwick.ac.uk)           |\n"
73              + "| Till Bretschneider (Till.Bretschneider@warwick.ac.uk) |\n"
74              + "| Piotr Baniukiewicz (P.Baniukiewicz@warwick.ac.uk)     |\n"
75              + "| Web page: "
76              + new PropertyReader().readProperty("quimpconfig.properties", "webPage")
77              + "                     |\n"
78              + "---------------------------------------------------------\n";
79      //!<
80      infoPlate = infoPlate.concat("\n");
81      infoPlate = infoPlate.concat("QuimP version: " + quimpBuildInfo.getVersion());
82      infoPlate = infoPlate.concat("\n");
83      infoPlate = infoPlate.concat("Build by: " + quimpBuildInfo.getBuildstamp());
84      infoPlate = infoPlate.concat("\n");
85      infoPlate = infoPlate.concat("Internal name: " + quimpBuildInfo.getName());
86      infoPlate = infoPlate.concat("\n");
87      return infoPlate;
88    }
89  
90    /**
91     * Get build info read from jar file.
92     * 
93     * @return Formatted strings with build info and version.
94     */
95    public QuimpVersion getQuimPBuildInfo() {
96      String[] ret = new String[3];
97      try {
98        Enumeration<URL> resources = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
99        // get internal name - jar name
100       String iname = new PropertyReader().readProperty("quimpconfig.properties", "internalName");
101       while (resources.hasMoreElements()) {
102         URL reselement = resources.nextElement();
103         if (!reselement.toString().contains("/" + iname)) {
104           continue;
105         }
106         Manifest manifest = new Manifest(reselement.openStream());
107         Attributes attributes = manifest.getMainAttributes();
108         try {
109           String date = attributes.getValue("Implementation-Date");
110 
111           ret[1] = attributes.getValue("Built-By") + " on: " + implementationDateConverter(date);
112           ret[0] = attributes.getValue("Implementation-Version");
113           ret[2] = attributes.getValue("Implementation-Title");
114           LOGGER.trace(Arrays.toString(ret));
115         } catch (Exception e) {
116           ; // do not care about problems - just use defaults defined on beginning
117         }
118       }
119     } catch (IOException e) {
120       ; // do not care about problems - just use defaults defined on beginning
121     }
122     // replace possible nulls with default text
123     ret[0] = ret[0] == null ? defNote : ret[0];
124     ret[1] = ret[1] == null ? defNote : ret[1];
125     ret[2] = ret[2] == null ? defNote : ret[2];
126     // prepare output
127     QuimpVersionuimpVersion.html#QuimpVersion">QuimpVersion retmap = new QuimpVersion(ret[0], ret[1], ret[2]);
128     return retmap;
129   }
130 
131   /**
132    * Reformat date from jar (put there by Maven).
133    * 
134    * @param dateString string in format "2017-02-24T08:55:44+0000"
135    * @return String in format "yyyy-MM-dd hh:mm:ss"
136    */
137   public static String implementationDateConverter(String dateString) {
138     DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
139     TemporalAccessor accessor = timeFormatter.parse(dateString);
140     Date date = Date.from(Instant.from(accessor));
141     SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
142     return dt.format(date);
143   }
144 
145   /**
146    * S 2 d.
147    *
148    * @param s the s
149    * @return the double
150    */
151   public static double s2d(String s) {
152     Double d;
153     try {
154       d = new Double(s);
155     } catch (NumberFormatException e) {
156       d = null;
157     }
158     if (d != null) {
159       return (d.doubleValue());
160     } else {
161       return (0.0);
162     }
163   }
164 
165   /**
166    * Get file name without extension.
167    * 
168    * @param filename name of the file
169    * @return file (with path) without extension
170    */
171   public static String removeExtension(String filename) {
172     // extract fileName without extension
173 
174     int dotI = filename.lastIndexOf(".");
175     if (dotI > 0 && filename.length() - dotI <= 6) { // assume extension of length max 5+dot
176       filename = filename.substring(0, dotI);
177     }
178     return filename;
179   }
180 
181   /**
182    * Get file extension.
183    * 
184    * @param filename Name of file
185    * @return extension without dot
186    */
187   public static String getFileExtension(String filename) {
188     // extract fileName without extension
189 
190     int dotI = filename.lastIndexOf(".");
191     if (dotI > 0) {
192       filename = filename.substring(dotI + 1, filename.length());
193     }
194     return filename;
195   }
196 
197   /**
198    * Closest floor.
199    *
200    * @param o the o
201    * @param target the target
202    * @return the vert
203    */
204   public static Vert closestFloor(Outline o, double target) {
205     // find the vert with coor closest (floored) to target coordinate
206 
207     Vert v = o.getHead();
208     double coordA;
209     double coordB;
210 
211     do {
212       // coordA = v.fCoord;
213       // coordB = v.getNext().fCoord;
214       coordA = v.coord;
215       coordB = v.getNext().coord;
216       // System.out.println("A: " + coordA + ", B: "+ coordB);
217 
218       if ((coordA > coordB)) {
219         if (coordA <= target && coordB + 1 > target) {
220           break;
221         }
222 
223         if (coordA - 1 <= target && coordB > target) {
224           break;
225         }
226 
227       } else {
228         if (coordA <= target && coordB > target) {
229           break;
230         }
231       }
232       v = v.getNext();
233     } while (!v.isHead());
234 
235     return v;
236   }
237 
238   /**
239    * Distance to scale.
240    *
241    * @param value the value
242    * @param scale the scale
243    * @return the double
244    */
245   public static double distanceToScale(double value, double scale) {
246     // assums pixelwidth is in micro meters
247     return value * scale;
248   }
249 
250   /**
251    * Distance to scale.
252    *
253    * @param value the value
254    * @param scale the scale
255    * @return the double
256    */
257   public static double distanceToScale(int value, double scale) {
258     return value * scale;
259   }
260 
261   /**
262    * Area to scale.
263    *
264    * @param value the value
265    * @param scale the scale
266    * @return the double
267    */
268   public static double areaToScale(double value, double scale) {
269     // assums pixelwidth is in micro meters
270     return value * (scale * scale);
271   }
272 
273   /**
274    * Speed to scale.
275    *
276    * @param value the value
277    * @param scale the scale
278    * @param frameInterval the frame interval
279    * @return the double
280    */
281   public static double speedToScale(double value, double scale, double frameInterval) {
282     return (value * scale) / frameInterval;
283   }
284 
285   /**
286    * Speed to scale.
287    *
288    * @param value the value
289    * @param scale the scale
290    * @param frameInterval the frame interval
291    * @return the double
292    */
293   public static double speedToScale(int value, double scale, double frameInterval) {
294     return (value * scale) / frameInterval;
295   }
296 
297   /**
298    * Distance from scale.
299    *
300    * @param value the value
301    * @param scale the scale
302    * @return the double
303    */
304   public static double distanceFromScale(double value, double scale) {
305     return value / scale;
306   }
307 
308   /**
309    * Date as string.
310    *
311    * @return the string
312    */
313   public static String dateAsString() {
314     SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
315     Date date = new Date();
316     return formatter.format(date);
317   }
318 
319   /**
320    * Sets the limits equal.
321    *
322    * @param migLimits the mig limits
323    * @return the double[]
324    */
325   public static double[] setLimitsEqual(double[] migLimits) { // min and max
326     if (migLimits.length < 2) {
327       LOGGER.warn("Array to short. Needs a min and max");
328       return migLimits;
329     }
330     // Set limits to equal positive and negative
331     if (migLimits[1] < 0) {
332       migLimits[1] = -migLimits[0];
333     }
334     if (migLimits[0] > 0) {
335       migLimits[0] = -migLimits[1];
336     }
337 
338     // Make min and max equal for mig and conv
339     if (migLimits[0] < -migLimits[1]) {
340       migLimits[1] = -migLimits[0];
341     } else {
342       migLimits[0] = -migLimits[1];
343     }
344 
345     return migLimits;
346   }
347 
348   /**
349    * Insert \n character after given number of chars trying to not break words.
350    * 
351    * @param in Input string
352    * @param len line length
353    * @return Wrapped string
354    * @see <a href=
355    *      "link">http://stackoverflow.com/questions/8314566/splitting-a-string-on-to-several-different-lines-in-java</a>
356    */
357   public static String stringWrap(String in, int len) {
358     return stringWrap(in, len, "\n");
359   }
360 
361   /**
362    * Insert \n character after default number of chars trying to not break words.
363    * 
364    * @param in Input string
365    * @return Wrapped string
366    * @see <a href=
367    *      "link">http://stackoverflow.com/questions/8314566/splitting-a-string-on-to-several-different-lines-in-java</a>
368    */
369   public static String stringWrap(String in) {
370     return stringWrap(in, QuimP.LINE_WRAP, "\n");
371   }
372 
373   /**
374    * Insert any symbol after given number of chars trying to not break words.
375    * 
376    * <p>It preserve position of new line symbol if present in text.
377    * 
378    * @param in Input string
379    * @param len line length
380    * @param brek symbol to insert on line break
381    * @return Wrapped string
382    * @see <a href=
383    *      "link">http://stackoverflow.com/questions/8314566/splitting-a-string-on-to-several-different-lines-in-java</a>
384    */
385   public static String stringWrap(String in, int len, String brek) {
386     String[] sp = in.split("\n");
387     String str = "";
388     for (String s : sp) {
389       s = s.concat("\n");
390       str = str.concat(WordUtils.wrap(s, len, brek, false, "( |/|\\\\)"));
391     }
392     str = str.trim();
393     // String str = WordUtils.wrap(in, len, brek, false, "( |/|\\\\)");
394     return str;
395   }
396 
397 }