001 /*******************************************************************************
002 * Filename : ToolBox.java
003 * Created : 13-Sep-2003
004 *
005 * History
006 */
007
008 package ifs.util;
009
010 import java.io.*;
011 import java.util.*;
012 import org.apache.log4j.*;
013
014 /** Several auxiliary static methods.
015 *
016 * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
017 * @version 1.0
018 */
019 public class ToolBox {
020 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(ToolBox.class);
021 private static long sSeed = System.currentTimeMillis();
022 private static Random sRandom = new Random(sSeed);
023
024 /** Returns random number (int) from the set 0 .. limit - 1 */
025 public static int random(int limit) {
026 return (int)(random()*limit);
027 }
028
029 /** Returns random element from the given set of elements */
030 public static Object random(Collection set) {
031 if (set==null || set.size()==0) return null;
032 Vector v = (set instanceof Vector?(Vector)set:new Vector(set));
033 return v.elementAt(random(v.size()));
034 }
035
036 /** Returns a randomly generated subset of the given set
037 * @param set set
038 * @param part probability of selection of an element into the resultant subset
039 */
040 public static Collection subSet(Collection set, double part) {
041 return subSet(set,part,1);
042 }
043
044 /** Swaps two elements in the list */
045 private static void swap(ArrayList list, int first, int second) {
046 Object o = list.get(first);
047 list.set(first,list.get(second));
048 list.set(second,o);
049 }
050
051 /** Returns a randomly generated subset of the given set
052 * @param set set
053 * @param part probability of selection of an element into the resultant subset
054 * @param minSize minimal size of the returned subset
055 */
056 public static Collection subSet(Collection set, double part, int minSize) {
057 if (set.size()<=minSize || part>=1.0) return set;
058 ArrayList subSet = new ArrayList(set);
059 int size = set.size();
060 int numberToSelect = Math.max(minSize,(int)(part*set.size()));
061 for (int idx=0;idx<numberToSelect;idx++) {
062 swap(subSet, idx, idx+(int)(random()*(size-idx)));
063 }
064 return subSet.subList(0, numberToSelect);
065 }
066
067 /** Trim a string to have given length */
068 public static String trim(String s, int length) {
069 if (s.length()>length) return s.substring(0,length);
070 StringBuffer sb = new StringBuffer(s);
071 while (sb.length()<length) sb.append(" ");
072 return sb.toString();
073 }
074
075 /** Multiline representation of a colection */
076 public static String col2string(Collection col, int tab) {
077 StringBuffer tabsb = new StringBuffer();
078 while (tabsb.length()<2*tab)
079 tabsb.append(" ");
080 StringBuffer sb = new StringBuffer("[\n");
081 for (Iterator i=col.iterator();i.hasNext();) {
082 sb.append(tabsb+" "+i.next()+(i.hasNext()?",":"")+"\n");
083 }
084 sb.append(tabsb+"]");
085 return sb.toString();
086 }
087
088 /** Multiline representation of a dictionary */
089 public static String dict2string(Dictionary dict, int tab) {
090 StringBuffer tabsb = new StringBuffer();
091 while (tabsb.length()<2*tab)
092 tabsb.append(" ");
093 StringBuffer sb = new StringBuffer("[\n");
094 for (Enumeration e=sortEnumeration(dict.keys());e.hasMoreElements();) {
095 Object key = e.nextElement();
096 Object value = dict.get(key);
097 sb.append(tabsb+" "+key+": "+value+"\n");
098 }
099 sb.append(tabsb+"]");
100 return sb.toString();
101 }
102
103 /** Root mean square
104 * @param n number of tests
105 * @param x total value of all tests
106 * @param x2 total value^2 of all tests
107 */
108 public static double rms(int n, double x, double x2) {
109 double var = x2/n ;
110 double mean = x/n;
111 return Math.sqrt(Math.abs(var-mean*mean));
112 }
113
114 /** Sort enumeration
115 * @param e an enumeration
116 * @return sorted enumeration
117 */
118 public static Enumeration sortEnumeration(java.util.Enumeration e) {
119 return sortEnumeration(e,null);
120 }
121
122 /** Sort enumeration
123 * @param e an enumeration
124 * @param c comparator of two objects in enumeration e
125 * @return sorted enumeration
126 */
127 public static Enumeration sortEnumeration(java.util.Enumeration e, java.util.Comparator c) {
128 Vector v = new Vector();
129 for (;e.hasMoreElements();) v.addElement(e.nextElement());
130 Collections.sort(v,c);
131 return v.elements();
132 }
133
134 /** Merge source with target */
135 public static void merge(Vector target, Collection source) {
136 for (Iterator i=source.iterator(); i.hasNext();) {
137 Object o = i.next();
138 if (!target.contains(o)) target.addElement(o);
139 }
140 }
141
142 /** Returns intersection of two collections */
143 public static Vector intersect(Collection source1, Collection source2) {
144 Vector target = new FastVector();
145 for (Iterator i=source1.iterator(); i.hasNext();) {
146 Object o = i.next();
147 if (!source2.contains(o)) target.addElement(o);
148 }
149 return target;
150 }
151
152 /** Sets seeds for {@link ToolBox#getRandom()} and {@link ToolBox#random()} methods. */
153 public static void setSeed(long seed) {
154 sSeed = seed;
155 sRandom = new Random(sSeed);
156 }
157
158 /** Gets current seed */
159 public static long getSeed() {
160 return sSeed;
161 }
162 /** Gets random number generator */
163 public static Random getRandom() {
164 return sRandom;
165 }
166 /** Generates random double number */
167 public static double random() {
168 return sRandom.nextDouble();
169 }
170
171 /** Configurates log4j loging */
172 public static void configureLogging() {
173 Properties props = new Properties();
174 props.setProperty("log4j.rootLogger", "DEBUG, A1");
175 props.setProperty("log4j.appender.A1", "org.apache.log4j.ConsoleAppender");
176 props.setProperty("log4j.appender.A1.layout", "org.apache.log4j.PatternLayout");
177 props.setProperty("log4j.appender.A1.layout.ConversionPattern","%-5p %c{2}: %m%n");
178 PropertyConfigurator.configure(props);
179 }
180
181 /** Configurates log4j loging
182 * @param logDir output folder
183 * @param properties some other log4j properties
184 */
185 public static void configureLogging(String logDir, Properties properties) {
186 configureLogging(logDir, properties, false);
187 }
188
189 /** Configurates log4j loging
190 * @param logDir output folder
191 * @param properties some other log4j properties
192 * @param timeInFileName if true log file is named debug_yyyy-MM-dd_(HH.mm.ss).log, it is named debug.log otherwise
193 */
194 public static void configureLogging(String logDir, Properties properties, boolean timeInFileName) {
195 String time = new java.text.SimpleDateFormat( "yyyy-MM-dd_(HH.mm.ss)",java.util.Locale.US).format(new Date());
196 (new File(logDir)).mkdirs();
197 String fileName = logDir+File.separator+(timeInFileName?"debug_"+time:"debug")+".log";
198 Properties props = (properties!=null?properties:new Properties());
199 if (!props.containsKey("log4j.rootLogger")) {
200 props.setProperty("log4j.rootLogger", "debug, LogFile");
201 props.setProperty("log4j.appender.LogFile","org.apache.log4j.RollingFileAppender");
202 props.setProperty("log4j.appender.LogFile.MaxFileSize", "5MB");
203 props.setProperty("log4j.appender.LogFile.File",fileName);
204 props.setProperty("log4j.appender.LogFile.MaxBackupIndex","5");
205 props.setProperty("log4j.appender.LogFile.layout","org.apache.log4j.PatternLayout");
206 props.setProperty("log4j.appender.LogFile.layout.ConversionPattern","%d{dd-MMM-yy HH:mm:ss.SSS} [%t] %-5p %c{2}> %m%n");
207 }
208 PropertyConfigurator.configure(props);
209 Logger log = Logger.getRootLogger();
210 log.info("IFS debug file");
211 log.info("");
212 log.info("Created: "+new Date());
213 log.info("");
214 log.info("System info:");
215 log.info("System: "+System.getProperty("os.name")+" "+System.getProperty("os.version")+" "+System.getProperty("os.arch"));
216 log.info("CPU: "+System.getProperty("sun.cpu.isalist")+" endian:"+System.getProperty("sun.cpu.endian")+" encoding:"+System.getProperty("sun.io.unicode.encoding"));
217 log.info("Java: "+System.getProperty("java.vendor")+", "+System.getProperty("java.runtime.name")+" "+System.getProperty("java.runtime.version",System.getProperty("java.version")));
218 log.info("User: "+System.getProperty("user.name"));
219 log.info("Timezone: "+System.getProperty("user.timezone"));
220 log.info("Working dir: "+System.getProperty("user.dir"));
221 log.info("Classpath: "+System.getProperty("java.class.path"));
222 log.info("");
223 }
224
225 /** Loads data properties. If there is INCLUDE property available, it is interpreted as semi-colon separated list of
226 * porperty files which should be also loaded (works recursively).
227 *
228 */
229 public static DataProperties loadProperties(File propertyFile) {
230 try {
231 DataProperties ret = new DataProperties();
232 FileInputStream is = new FileInputStream(propertyFile);
233 ret.load(is);
234 is.close();
235 if (ret.getProperty("INCLUDE")!=null) {
236 is=null;
237 StringTokenizer stk = new StringTokenizer(ret.getProperty("INCLUDE"),";");
238 while (stk.hasMoreTokens()) {
239 String aFile = stk.nextToken();
240 System.out.println(" Loading included file '"+aFile+"' ... ");
241 if ((new File(aFile)).exists())
242 is = new FileInputStream(aFile);
243 if ((new File(propertyFile.getParent()+File.separator+aFile)).exists())
244 is = new FileInputStream(propertyFile.getParent()+File.separator+aFile);
245 if (is==null) System.err.println("Unable to find include file '"+aFile+"'.");
246 ret.load(is);
247 is.close();
248 }
249 ret.remove("INCLUDE");
250 }
251 return ret;
252 } catch (Exception e) {
253 System.err.println("Unable to load property file "+propertyFile);
254 e.printStackTrace();
255 return new DataProperties();
256 }
257 }
258 }