package org.autoplot.idlsupport; import java.io.File; import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Logger; import org.autoplot.datasource.AbstractDataSourceFactory; import org.autoplot.datasource.CompletionContext; import org.autoplot.datasource.DataSetURI; import org.autoplot.datasource.DataSource; import org.autoplot.datasource.URISplit; import org.autoplot.idlsupport.ReadIDLSav.ArrayDesc; import org.autoplot.idlsupport.ReadIDLSav.StructDesc; import org.autoplot.idlsupport.ReadIDLSav.TagDesc; import org.das2.util.LoggerManager; import org.das2.util.monitor.ProgressMonitor; /** * Factory for reading IDLSave files. * @author jbf */ public class IdlsavDataSourceFactory extends AbstractDataSourceFactory { private static Logger logger= LoggerManager.getLogger("apdss.idlsav"); @Override public DataSource getDataSource(URI uri) throws Exception { return new IdlsavDataSource(uri); } @Override public boolean reject(String surl, List problems, ProgressMonitor mon) { try { URISplit split= URISplit.parse(surl); Map params= URISplit.parseParams(split.params); String var= params.get(URISplit.PARAM_ARG_0); String x= params.get("X"); String y= params.get("Y"); String z= params.get("Z"); if ( var==null && x==null && y==null && z==null ) { problems.add("need variable name to read"); return true; } File file= DataSetURI.getFile( split.resourceUri, mon ); ByteBuffer buf= ReadIDLSav.readFileIntoByteBuffer(file); String[] names= new ReadIDLSav().readVarNames(buf); String[] vars=null; if ( var!=null ) { vars = var.split(",",-2); } else { if ( params.get("Z")!=null ) { vars= new String[3]; vars[2]= params.get("Z"); } if ( params.get("Y")!=null ) { if ( vars==null ) vars= new String[2]; vars[1]= params.get("Y"); } if ( params.get("X")!=null ) { if ( vars==null ) vars= new String[1]; vars[0]= params.get("X"); } } for (String var1 : vars) { var = var1; if ( var==null ) continue; boolean found= false; for (String name : names) { if (var.startsWith(name)) { found= true; } } if ( !found ) { problems.add("no plottable parameters start with "+var); } ReadIDLSav reader= new ReadIDLSav(); TagDesc t= reader.readTagDesc( buf, var ); if ( t==null ) { problems.add("no tag desc found for "+var); } else if ( t instanceof StructDesc ) { problems.add("tag is a structure: "+var); } } return problems.size()>0 ; } catch (IOException ex) { problems.add( ex.toString() ); return true; } } private void addCompletions( ReadIDLSav reader, String root, String key, ByteBuffer buf, List ccresult ) throws IOException { String keyn= root==null ? key : root + "." + key; if ( root!=null ) { Object o= reader.readVar( buf, root ); Map m= (Map)o; for ( Entry e: m.entrySet() ) { CompletionContext cc1= new CompletionContext( CompletionContext.CONTEXT_PARAMETER_NAME, keyn, this, "arg_0", root + "." + key, "", true ); ccresult.add(cc1); } } if ( reader.isStructure( buf, key ) ) { StructDesc desc= (StructDesc)reader.readTagDesc( buf, key ); for ( String t : desc.tagnames ) { CompletionContext cc1= new CompletionContext( CompletionContext.CONTEXT_PARAMETER_NAME, keyn+"." +t, this, "arg_0", keyn+"." +t, "", true ); ccresult.add(cc1); } } else if ( reader.isArray( buf, key ) ) { ArrayDesc desc= (ArrayDesc)reader.readTagDesc( buf, key ); String stype = ReadIDLSav.decodeTypeCode(desc.typecode); StringBuilder sqube= new StringBuilder(stype).append("[").append(String.valueOf(desc.dims[0])); for ( int i=1; i result= new ArrayList<>(); ByteBuffer buf= ReadIDLSav.readFileIntoByteBuffer(file); String[] names= new ReadIDLSav().readVarNames(buf); ReadIDLSav reader= new ReadIDLSav(); if ( completable.contains(".") ) { int i= completable.lastIndexOf('.'); String root= completable.substring(0,i); int i2= root.lastIndexOf(","); if ( i2>-1 ) { root= root.substring(i2+1); } Object o= reader.readVar( buf, root ); if ( o==null ) { return new String[0]; } Map m= (Map)o; for ( Entry e: m.entrySet() ) { if ( e.getValue() instanceof Map ) { for ( Entry e2: ((Map)e.getValue()).entrySet() ) { result.add( root + "." + e.getKey() + "."+ e2.getKey() ); } } else { result.add( root + "." + e.getKey() + "."+ e.getKey() ); } } return result.toArray( new String[result.size()] ); } else { return names; } } @Override public List getCompletions(CompletionContext cc, ProgressMonitor mon) throws Exception { if ( cc.context.equals(CompletionContext.CONTEXT_PARAMETER_NAME) ) { List ccresult= new ArrayList<>(); File file= DataSetURI.getFile( cc.resourceURI, mon ); ByteBuffer buf= ReadIDLSav.readFileIntoByteBuffer(file); String[] names= new ReadIDLSav().readVarNames(buf); ReadIDLSav reader= new ReadIDLSav(); Map params= URISplit.parseParams(cc.params); String completable= params.get(URISplit.PARAM_ARG_0); if ( completable.contains(".") ) { int i= completable.lastIndexOf('.'); String root= completable.substring(0,i); int i2= root.lastIndexOf(","); if ( i2>-1 ) { root= root.substring(i2+1); } //int i3= root.indexOf("="); //if ( i3>-1 ) { // root= root.substring(i3+1); //} Object o= reader.readVar( buf, root ); if ( o instanceof Map ) { Map m= (Map)o; for ( Entry e: m.entrySet() ) { if ( e.getValue() instanceof Map ) { for ( Entry e2: ((Map)e.getValue()).entrySet() ) { CompletionContext cc1= new CompletionContext( CompletionContext.CONTEXT_PARAMETER_NAME, root + "." + e.getKey() + "."+ e2.getKey(), this, "arg_0", root + "." + e.getKey()+ "."+ e2.getKey(), "", true ); ccresult.add(cc1); } } else { CompletionContext cc1= new CompletionContext( CompletionContext.CONTEXT_PARAMETER_NAME, root + "." + e.getKey(), this, "arg_0", root + "." + e.getKey(), "", true ); ccresult.add(cc1); } } } else { logger.fine("not a Map, which was expected"); } } else { getCompletionsWithStructs(names, reader, buf, ccresult, null ); } ccresult.add(new CompletionContext(CompletionContext.CONTEXT_PARAMETER_NAME, "xunits=", "units for the x values")); ccresult.add(new CompletionContext(CompletionContext.CONTEXT_PARAMETER_NAME, "yunits=", "units for the y values")); ccresult.add(new CompletionContext(CompletionContext.CONTEXT_PARAMETER_NAME, "units=", "units for the values")); ccresult.add(new CompletionContext(CompletionContext.CONTEXT_PARAMETER_NAME, "X=", "variable for the x values")); ccresult.add(new CompletionContext(CompletionContext.CONTEXT_PARAMETER_NAME, "Y=", "variable for the y values")); ccresult.add(new CompletionContext(CompletionContext.CONTEXT_PARAMETER_NAME, "Z=", "variable for the z values")); return ccresult; } else if ( cc.context.equals(CompletionContext.CONTEXT_PARAMETER_VALUE ) ) { String paramName = CompletionContext.get(CompletionContext.CONTEXT_PARAMETER_NAME, cc); switch (paramName) { case "X": case "Y": case "Z": List ccresult= new ArrayList<>(); File file= DataSetURI.getFile( cc.resourceURI, mon ); ByteBuffer buf= ReadIDLSav.readFileIntoByteBuffer(file); String[] names= new ReadIDLSav().readVarNames(buf); ReadIDLSav reader= new ReadIDLSav(); getCompletionsWithStructs(names, reader, buf, ccresult, paramName); return ccresult; case "xunits": List result = new ArrayList<>(); result.add(new CompletionContext(CompletionContext.CONTEXT_PARAMETER_VALUE, "t1970", "seconds since 1970-01-01T00:00" ) ); result.add(new CompletionContext(CompletionContext.CONTEXT_PARAMETER_VALUE, "cdfTT2000", "cdf times" ) ); result.add(new CompletionContext(CompletionContext.CONTEXT_PARAMETER_VALUE, "hours+since+2015-01-01T00:00", "arbitrary time base" ) ); return result; default: return super.getCompletions(cc, mon); } } else { return super.getCompletions(cc, mon); } } private void getCompletionsWithStructs(String[] names, ReadIDLSav reader, ByteBuffer buf, List ccresult, String paramName) throws IOException { for (String name : names) { String root= name; if ( reader.isStructure(buf, name ) ) { Object o= reader.readVar( buf, name ); if ( o instanceof Map ) { Map m= (Map)o; for ( Entry e: m.entrySet() ) { if ( e.getValue() instanceof Map ) { for ( Entry e2: ((Map)e.getValue()).entrySet() ) { if ( paramName==null ) { CompletionContext cc1= new CompletionContext( CompletionContext.CONTEXT_PARAMETER_NAME, root + "." + e.getKey() + "."+ e2.getKey(), this, "arg_0", root + "." + e.getKey()+ "."+ e2.getKey(), "", true ); ccresult.add(cc1); } else { CompletionContext cc1= new CompletionContext( CompletionContext.CONTEXT_PARAMETER_VALUE, root + "." + e.getKey() + "."+ e2.getKey(), this, paramName, root + "." + e.getKey()+ "."+ e2.getKey(), "", true ); ccresult.add(cc1); } } } else { if ( paramName==null ) { CompletionContext cc1= new CompletionContext( CompletionContext.CONTEXT_PARAMETER_NAME, root + "." + e.getKey(), this, "arg_0", root + "." + e.getKey(), "", true ); ccresult.add(cc1); } else { CompletionContext cc1= new CompletionContext( CompletionContext.CONTEXT_PARAMETER_VALUE, root + "." + e.getKey(), this, paramName, root + "." + e.getKey(), "", true ); ccresult.add(cc1); } } } } } else { addCompletions(reader, null, name, buf, ccresult); } } } @Override public String getDescription() { return "IDL Savesets"; } }