/* * FileStorageModel.java * * Created on March 31, 2004, 9:52 AM */ package org.das2.fsm; import org.das2.datum.TimeUtil.TimeStruct; import org.das2.util.filesystem.FileObject; import org.das2.util.filesystem.FileSystem; import org.das2.datum.Datum; import org.das2.datum.DatumRange; import org.das2.datum.TimeUtil; import org.das2.datum.Units; import org.das2.util.DasExceptionHandler; import org.das2.util.monitor.ProgressMonitor; import org.das2.util.monitor.NullProgressMonitor; import org.das2.util.monitor.SubTaskMonitor; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.text.*; import java.util.*; import java.util.regex.*; import org.das2.DasApplication; /** * Represents a method for storing data sets in a set of files by time. The * client provides a regex for the files and how each group of the regex is * interpreted as a time digit. The model can then be used to provide the set * of files that cover a time range, etc. * * @see FileStorageModel FileStorageModel should be used in new applications. * @author Jeremy */ public class FileStorageModelOld { private Pattern pattern; private String regex; private FieldHandler[] fieldHandlers; private int timeWidth; /* in TimeUtil enum */ private int timeWidthMultiplier; /* 7 days */ private Datum timePhase= null; /* a file boundary */ private boolean[] copyToEndTime; /* indexed by TimeUtil enum */ FileStorageModelOld parent; FileSystem root; public static final int StartYear4=100; public static final int StartYear2=101; public static final int StartMonth=102; public static final int StartMonthName=108; public static final int StartDay=103; public static final int StartDoy=104; public static final int StartHour=105; public static final int StartMinute=106; public static final int StartSecond=107; public static final int EndYear4=200; public static final int EndYear2=201; public static final int EndMonth=202; public static final int EndMonthName=208; public static final int EndDay=203; public static final int EndDoy=204; public static final int EndHour=205; public static final int EndMinute=206; public static final int EndSecond=207; public static final int Ignore=300; HashMap fileNameMap=null; /* need to map back to TimeUtil's enums, note that we have an extra for the 2 digit year */ private int toTimeUtilEnum( int i ) { if ( i<100 || i > 300 ) { throw new IllegalArgumentException( "enumeration is not of the correct type"); } i= i % 100; if ( i==0 ) i=1; return i; } //TODO: add // public string format( DatumRange dr ); // public interface FieldHandler { public void handle( String s, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ); public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ); } public static abstract class IntegerFieldHandler implements FieldHandler { public void handle( String s, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { handleInt( Integer.parseInt(s), ts1, ts2 ); } abstract void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ); public abstract String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ); } static final NumberFormat nf4= new DecimalFormat("0000"); static final NumberFormat nf3= new DecimalFormat("000"); static final NumberFormat nf2= new DecimalFormat("00"); private final static String[] mons= new String [] { "", "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" } ; private static final FieldHandler StartMonthNameHandler= new FieldHandler() { public void handle( String s, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { try { ts1.month= TimeUtil.monthNumber( s ); } catch ( ParseException e ) { DasApplication.getDefaultApplication().getExceptionHandler().handle(e); } } public String format(TimeStruct ts1, TimeStruct ts2) { return mons[ ts1.month ]; } }; private static final FieldHandler EndMonthNameHandler= new FieldHandler() { public void handle( String s, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { try { ts2.month= TimeUtil.monthNumber( s ); } catch ( ParseException e ) { DasApplication.getDefaultApplication().getExceptionHandler().handle(e); } } public String format(TimeStruct ts1, TimeStruct ts2) { return mons[ ts2.month ]; } }; private static final FieldHandler StartYear4Handler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts1.year= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf4.format(ts1.year); } }; private static final FieldHandler StartYear2Handler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts1.year= i<58 ? i+2000 : i+1900; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts1.year % 100 ); } }; private static final FieldHandler StartMonthHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts1.month= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts1.month ); } }; private static final FieldHandler StartDayHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts1.day= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts1.day ); } }; private static final FieldHandler StartDoyHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts1.doy= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf3.format( ts1.doy ); } }; private static final FieldHandler StartHourHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts1.hour= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts1.hour ); } }; private static final FieldHandler StartMinuteHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts1.minute= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts1.minute ); } }; private static final FieldHandler StartSecondHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts1.seconds= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts1.seconds ); } }; private static final FieldHandler EndYear4Handler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts2.year= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf4.format( ts2.year ); } }; private static final FieldHandler EndYear2Handler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts2.year= i<58 ? i+2000 : i+1900; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts2.year ); } }; private static final FieldHandler EndMonthHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts2.month= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts2.month ); } }; private static final FieldHandler EndDayHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts2.day= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts2.day ); } }; private static final FieldHandler EndDoyHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts2.doy= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf3.format( ts2.doy ); } }; private static final FieldHandler EndHourHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts2.hour= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts2.hour ); } }; private static final FieldHandler EndMinuteHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts2.minute= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts2.minute ); } }; private static final FieldHandler EndSecondHandler= new IntegerFieldHandler() { public void handleInt( int i, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { ts2.seconds= i; } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return nf2.format( ts2.seconds ); } }; private static final FieldHandler IgnoreHandler= new FieldHandler() { public void handle( String s, TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { } public String format( TimeUtil.TimeStruct ts1, TimeUtil.TimeStruct ts2 ) { return "*"; } }; private void checkArgs( String regex, int[] digitList ) { int startLsd=0, endLsd=0; int[] startDigits= new int[7]; int[] endDigits= new int[7]; copyToEndTime= new boolean[8]; /* indexed by TimeUtil enum */ int startBase=100; int endBase=200; int ignoreBase=300; for ( int i=0; istartLsd ) startLsd= 103; } else if ( digitList[i]==EndDoy ) { endDigits[1]=1; endDigits[2]=1; if ( 203>endLsd ) endLsd= 203; } else if ( digitList[i]>=startBase && digitList[i]startLsd ) startLsd= digitList[i]; } else if ( digitList[i]>=endBase && digitList[i]endLsd ) endLsd= digitList[i]; } } if ( startDigits[StartYear2-startBase]==1 ) startDigits[StartYear4-startBase]=1; if ( startDigits[StartYear4-startBase]==1 ) startDigits[StartYear2-startBase]=1; if ( startDigits[StartDoy-startBase]==1 ) { startDigits[StartMonth-startBase]=1; startDigits[StartDay-startBase]=1; } if ( endDigits[EndYear2-endBase]==1 ) endDigits[EndYear4-endBase]=1; if ( startDigits[EndYear4-endBase]==1 ) startDigits[EndYear2-endBase]=1; if ( endDigits[EndDoy-endBase]==1 ) { endDigits[EndMonth-endBase]=1; endDigits[EndDay-endBase]=1; } for ( int i=0; i0 && startDigits[i]==1 && startDigits[i-1]!=1 ) { throw new IllegalArgumentException( "more significant digits missing in startTime"); } if ( i>0 && startDigits[i]==0 && startDigits[i-1]==1 ) { timeWidth= toTimeUtilEnum( startLsd ); timeWidthMultiplier= 1; } } boolean canUse= true; for ( int i=startLsd-startBase; i>=0; i-- ) { if ( endDigits[i]==0 ) canUse=false; if ( !canUse ) endDigits[i]= 0; } for ( int i=0; i=100 && digitList[i]<200 ) { fieldHandlerList.add(i,startHandlers[digitList[i]-100]); } else if (digitList[i]>=200 && digitList[i]<300 ) { fieldHandlerList.add(i,endHandlers[digitList[i]-200]); } else if ( digitList[i]==300 ) { fieldHandlerList.add(i,IgnoreHandler); } else { throw new IllegalArgumentException("unknown field handler: "+digitList[i]); } } return (FieldHandler[])fieldHandlerList.toArray( new FieldHandler[fieldHandlerList.size()] ); } /* * extract time range for file or directory from its name. * The least significant time digit is considered to be the implicitTimeWidth, * and if the width is not stated explicitly, it will be used. When * a set timeDigits are encountered twice, then the second occurrence * is considered be the end time. * * .../FULL1/T8709_12/T871118.DAT *'.../FULL1/T'YYMM_MM/TYYMMDD'.DAT' */ private DatumRange getDatumRangeFor( String filename ) { if ( fieldHandlers.length==0 ) { // e.g. FULL1 doesn't constrain time return DatumRange.newDatumRange( -1e30, 1e30, Units.mj1958 ); } TimeUtil.TimeStruct ts1= new TimeUtil.TimeStruct(); ts1.year=0; ts1.day=0; ts1.month=1; ts1.doy=0; ts1.hour=0; ts1.minute=0; ts1.seconds=0; TimeUtil.TimeStruct ts2= new TimeUtil.TimeStruct(); if ( File.separatorChar=='\\' ) filename= filename.replaceAll("\\\\", "/"); Matcher m= pattern.matcher(filename); if ( m.matches() ) { for ( int i=0; i0 ) { String ff= names[i].equals("") ? files1[0] : names[i]+"/"+files1[0]; if ( ff.endsWith("/") ) ff=ff.substring(0,ff.length()-1); result= ff; } } return result; } public File[] getFilesFor( final DatumRange targetRange ) throws IOException { return getFilesFor( targetRange, new NullProgressMonitor() ); } public DatumRange getRangeFor( String name ) { return getDatumRangeFor( name ); } /** * returns true if the file came (or could come) from this FileStorageModel. */ public boolean containsFile( File file ) { maybeCreateFileNameMap(); if ( !fileNameMap.containsKey(file) ) { return false; } else { String result= (String)fileNameMap.get(file); String name= getNameFor( file ); Matcher m= pattern.matcher( name ); return m.matches(); } } /** * Need a way to recover the model name of a file. The returned File from getFilesFor can be anywhere, * so it would be good to provide a way to get it back into a FSM name. */ public String getNameFor( File file ) { String result= (String)fileNameMap.get(file); if ( result==null ) { throw new IllegalArgumentException( "File didn't come from this FileStorageModel" ); } else { return result; } } private synchronized void maybeCreateFileNameMap() { if ( fileNameMap==null ) fileNameMap= new HashMap(); } /** * retrieve the file for the name. * @throws IOException if the file cannot be transferred. */ public File getFileFor( String name, ProgressMonitor monitor ) throws FileNotFoundException, IOException { FileObject o= root.getFileObject( name ); File file= o.getFile( monitor ); maybeCreateFileNameMap(); fileNameMap.put( file, name ); return file; } /** * returns a list of files that can be used */ public File[] getFilesFor( final DatumRange targetRange, ProgressMonitor monitor ) throws IOException { String[] names= getNamesFor( targetRange ); File[] files= new File[names.length]; maybeCreateFileNameMap(); if ( names.length>0 ) monitor.setTaskSize( names.length * 10 ); for ( int i=0; i1 ) { dirRegex= s[0]; for ( int i=1; i