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    }