diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6b468b6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.class diff --git a/festc_bootstrap/.project b/festc_bootstrap/.project index 4792ef0..845d3dc 100644 --- a/festc_bootstrap/.project +++ b/festc_bootstrap/.project @@ -1,17 +1,17 @@ - - - festc_bootstrap - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - + + + festc_bootstrap + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/festc_core/bin/.gitignore b/festc_bootstrap/bin/.gitignore similarity index 100% rename from festc_core/bin/.gitignore rename to festc_bootstrap/bin/.gitignore diff --git a/festc_bootstrap/bin/gov/epa/festc/boot/FestcClassLoader.class b/festc_bootstrap/bin/gov/epa/festc/boot/FestcClassLoader.class deleted file mode 100644 index 1ff0205..0000000 Binary files a/festc_bootstrap/bin/gov/epa/festc/boot/FestcClassLoader.class and /dev/null differ diff --git a/festc_bootstrap/bin/gov/epa/festc/boot/FestcLifecycleHandler.class b/festc_bootstrap/bin/gov/epa/festc/boot/FestcLifecycleHandler.class deleted file mode 100644 index 6ea9736..0000000 Binary files a/festc_bootstrap/bin/gov/epa/festc/boot/FestcLifecycleHandler.class and /dev/null differ diff --git a/festc_bootstrap/boot.properties b/festc_bootstrap/boot.properties index 8d371b3..b8b249a 100644 --- a/festc_bootstrap/boot.properties +++ b/festc_bootstrap/boot.properties @@ -1,19 +1,20 @@ -# Comma separated list of folders with plug-ins -# (plug-in repositories) -#pluginFolders = ../,./lib,../festc_core, -pluginFolders = ./,./lib,../festc_core,../festc_saf_ui -org.java.plugin.standard.PluginLifecycleHandler = gov.epa.festc.boot.FestcLifecycleHandler - -log4j.rootLogger=warn, console, R -log4j.logger.org.java = warn - -log4j.appender.console = org.apache.log4j.core.appender.ConsoleAppender -log4j.appender.console.layout = org.apache.log4j.core.Layout.PatternLayout -log4j.appender.console.layout.conversionPattern = %d [%t] %-5p %c %m%n - -log4j.appender.R=org.apache.log4j.core.appender.RollingFileAppender -log4j.appender.R.File=${user.home}/festc/festc.log -log4j.appender.R.MaxFileSize=100KB -log4j.appender.R.MaxBackupIndex=1 -log4j.appender.R.layout=org.apache.log4j.core.Layout.PatternLayout -log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p %c %m%n +# Comma separated list of folders with plug-ins +# (plug-in repositories) +#pluginFolders = ../,./lib,../festc_core, +#pluginFolders = ./,./lib,../festc_core,../festc_saf_ui +pluginFolders = ./,./lib,../core,../saf.core.ui +org.java.plugin.standard.PluginLifecycleHandler = gov.epa.festc.boot.FestcLifecycleHandler + +log4j.rootLogger=warn, console, R +log4j.logger.org.java = warn + +log4j.appender.console = org.apache.log4j.core.appender.ConsoleAppender +log4j.appender.console.layout = org.apache.log4j.core.Layout.PatternLayout +log4j.appender.console.layout.conversionPattern = %d [%t] %-5p %c %m%n + +log4j.appender.R=org.apache.log4j.core.appender.RollingFileAppender +log4j.appender.R.File=${user.home}/festc/festc.log +log4j.appender.R.MaxFileSize=100KB +log4j.appender.R.MaxBackupIndex=1 +log4j.appender.R.layout=org.apache.log4j.core.Layout.PatternLayout +log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p %c %m%n diff --git a/festc_bootstrap/bootstrap.iml b/festc_bootstrap/bootstrap.iml index 5687a96..10cedfe 100644 --- a/festc_bootstrap/bootstrap.iml +++ b/festc_bootstrap/bootstrap.iml @@ -1,88 +1,88 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/festc_bootstrap/dist_boot.properties b/festc_bootstrap/dist_boot.properties index 13112e1..61148e1 100644 --- a/festc_bootstrap/dist_boot.properties +++ b/festc_bootstrap/dist_boot.properties @@ -1,19 +1,19 @@ -# Comma separated list of folders with plug-ins -# (plug-in repositories) -#pluginFolders = ../,./lib,../festc_core, -pluginFolders = ./,./lib,../core,../saf.core.ui -org.java.plugin.standard.PluginLifecycleHandler = gov.epa.festc.boot.FestcLifecycleHandler - -log4j.rootLogger=warn, console, R -log4j.logger.org.java = warn - -log4j.appender.console = org.apache.log4j.core.appender.ConsoleAppender -log4j.appender.console.layout = org.apache.log4j.core.Layout.PatternLayout -log4j.appender.console.layout.conversionPattern = %d [%t] %-5p %c %m%n - -log4j.appender.R=org.apache.log4j.core.appender.RollingFileAppender -log4j.appender.R.File=${user.home}/festc/festc.log -log4j.appender.R.MaxFileSize=100KB -log4j.appender.R.MaxBackupIndex=1 -log4j.appender.R.layout=org.apache.log4j.core.Layout.PatternLayout -log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p %c %m%n +# Comma separated list of folders with plug-ins +# (plug-in repositories) +#pluginFolders = ../,./lib,../festc_core, +pluginFolders = ./,./lib,../core,../saf.core.ui +org.java.plugin.standard.PluginLifecycleHandler = gov.epa.festc.boot.FestcLifecycleHandler + +log4j.rootLogger=warn, console, R +log4j.logger.org.java = warn + +log4j.appender.console = org.apache.log4j.core.appender.ConsoleAppender +log4j.appender.console.layout = org.apache.log4j.core.Layout.PatternLayout +log4j.appender.console.layout.conversionPattern = %d [%t] %-5p %c %m%n + +log4j.appender.R=org.apache.log4j.core.appender.RollingFileAppender +log4j.appender.R.File=${user.home}/festc/festc.log +log4j.appender.R.MaxFileSize=100KB +log4j.appender.R.MaxBackupIndex=1 +log4j.appender.R.layout=org.apache.log4j.core.Layout.PatternLayout +log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p %c %m%n diff --git a/festc_bootstrap/help/userManual.htm b/festc_bootstrap/help/userManual.htm index 22b7929..028525b 100644 --- a/festc_bootstrap/help/userManual.htm +++ b/festc_bootstrap/help/userManual.htm @@ -1,9718 +1,9718 @@ - - - - - -NOTE: Review and QA of all work products is included with the hours for -those work products - - - - - - -
- -

  -

- -

 

- -

 

- -

 

- -

 

- -

 

- -

- - - - - - - - - -
- - 

- -

 

- -
- -

User’s Guide for the Fertilizer -Emission Scenario Tool for CMAQ (FEST-C) Version 1.4

- -

 

- -

 

- -

 

- -

 

- -

Limei Ran1, Ellen Cooter1, -Dongmei Yang2, Verel Benson3, Yongping Yuan4, Adel -Hanna2, Val Garcia1

- -

 

- -

 

- -

1Atmospheric Model Application and -Analysis Branch, Computational Exposure Division, USEPA/ORD/NERL, Research -Triangle Park, NC 27711

- -

 

- -

2Institute for the Environment, University -of North Carolina at Chapel Hill, 100 Europa Dr., Chapel Hill, NC 27517

- -

 

- -

3Benson Consulting, Columbia, Missouri, -USA

- -

 

- -

4Integrated Environmental Modeling Branch, -Systems Exposure Division, USEPA/ORD/NERL, Research Triangle Park, NC 27711

- -

 

- -

 

- -

                                                                       

- -

 

- -

Date:                     September -20, 2018

- -
-
- -

 

- -

Disclaimer

- -

 

- -

The information in this operational guidance document has -been funded wholly or in part by the United States Environmental Protection -Agency. The draft version of this document has not been subjected to the -Agency’s peer and administrative review, nor has it been approved for -publication as an EPA document. The draft document has been subjected to review -by the Community Modeling and Analysis System Center only; this content has not -yet been approved by the EPA. Mention of trade names or commercial products -does not constitute endorsement or recommendation for use.

- -

 

- -

Acknowledgments

- -

 

- -

The development of the FEST-C -system is currently being supported by the U.S. EPA’s Computational Exposure -Division (CED) under U.S. EPA contract EP-W-16-014, “Operation of the Center -for Community Air Quality Modeling and Analysis (CMAS)” in support of Office of -Research and Development Air Climate and Energy, Safe and Sustainable Waters -and Safe and Healthy Communities Research Programs.  This work was also -supported under prior U.S. EPA contracts: EP W 09 023, “Operation of the Center -for Community Air Quality Modeling and Analysis (CMAS),” and EP D-12-044, -“Emissions, Air Quality, and Meteorological Modeling Support (EMAQ).”  We -greatly appreciate the continuing and generous intellectual support we have -received from Dr. Jimmy R. Williams at Texas A&M AgriLife Research, -Blackland Research & Extension Center (Temple, TX).  We thank Joe Slater, -Manager of Fertilizer/AG Lime Control Services, University of Missouri -Agricultural Experiment Station at Columbia, MO, for his invaluable insights -regarding fertilizer sales and use.  Finally, we thank Dr. Qun He for his -design and support on the FEST-C interface.

- -
-
- -

 

- -

 

- -

 

- -

Contents

- -

1. The -FEST-C System.. 1

- -

1.1 -Introduction. 1

- -

1.2 -Components. 3

- -

1.3 -Installation and Requirements. 4

- -

1.4 -Interface Launch. 5

- -

2. File Structures -for EPIC Modeling. 7

- -

3. Scenario -Management Selections under the File Menu. 17

- -

4. The -Pre-EPIC File Generation Tools. 21

- -

4.1 BELD4 -Data Generation. 23

- -

4.2 Crop -Site Info Generation. 27

- -

4.3 WRF/CMAQ -to EPIC.. 29

- -

5. EPIC -Spin-up Run Tools. 32

- -

5.1 EPIC -Site File Generation. 32

- -

5.2 Soil -Match for EPIC Spinup. 34

- -

5.3 -Management File Generation for Spinup. 35

- -

5.4 -View/Edit EPIC Inputs. 37

- -

5.5 EPIC -Runs for Spinup. 38

- -

6. EPIC -Application Run Tools. 41

- -

6.1 -Management File Generation for Application. 41

- -

6.2 EPIC -Runs for Application. 43

- -

7. Output -Processing and Visualizing Tools. 46

- -

7.1 EPIC -Yearly Extraction. 46

- -

7.2 EPIC to -CMAQ.. 49

- -

7.3 EPIC to -SWAT. 52

- -

7.4 -Visualization. 56

- -

8. Future Work. 57

- -

 

- -

 

- -
- -
-
- -
- -

1. The FEST-C System

- -

1.1 Introduction

- -

The Fertilizer -Emission Scenario Tool for CMAQ (FEST-C) (http://www.cmascenter.org/fest-c/) -is a Java-based interface system that facilitates the integration of -agriculture, atmosphere, and hydrology simulations at large scales.  With an -adapted Environmental Policy Integrated Climate (EPIC) model (http://epicapex.tamu.edu/ -epic/) for grassland and crop production, the system is primarily -used to simulate daily soil carbon (C), nitrogen (N), and phosphorus (P) cycles -on agricultural lands with atmospheric conditions and management practices -including fertilization and irrigation.  The FEST-C interface -with simple tool buttons guides users through EPIC simulations and output -extractions to generate the required input for bidirectional NH3 -modeling performed using the Community -Multiscale Air Quality (CMAQ) modeling system (http://www.cmascenter.org/cmaq/).  In addition to its application for air quality -modeling, the system has been enhanced to integrate with the Soil and Water -Assessment Tool (SWAT, https://swat.tamu.edu/) -for watershed hydrological simulations.   FEST-C enables the extraction of -SWAT-ready input files with nutrients and water runoffs from agricultural lands -and weather and N deposition from atmospheric models for simulating nitrogen -fate and transport in watersheds.  The FEST-C system is developed by EPA -scientists, Institute for the Environment at the University of North Carolina -at Chapel Hill (UNC), and Benson Consulting with the help from the Texas A&M AgriLife Research.  UNC and Benson -Consulting were supported under contract to the U.S. EPA Office of Research and -Development.

- -

The EPA EPIC -implementation requires no previous estimates of fertilizer application; it estimates -daily soil N conditions with fertilizer applications based entirely on -simulated plant demand in response to local soil and weather conditions.  The -FEST-C interface associates EPIC simulations spatially to the CMAQ domain covering -the conterminous United States (CONUS) and resolution through the current -release of the Spatial Allocator (SA) Raster Tools system (http://www.cmascenter.org/sa-tools/) -that has been developed under the Community Modeling and Analysis System (CMAS) -Center.  Figure 1 displays the process diagram of FEST-C linkage with the Weather -Research and Forecasting (WRF, http://www2.mmm.ucar.edu/wrf/users/), -CMAQ, and SWAT modeling systems.  The Biogenic Emissions Landcover Database -version 4 (BELD4), which is generated using the BELD4 tool in the SA Raster -Tools system, is consistently used in the FEST-C system as well as the WRF/CMAQ -modeling system.  Previous WRF/CMAQ system results provide daily weather inputs -and N deposition (optional), to the FEST-C system.  In return, FEST-C generates -soil properties (e.g. texture, moisture, and pH) and daily ammonium and nitrate -N pool status for specific crops assigned to agricultural land areas in each of -the CMAQ bidirectional NH3 modeling grids.  With the integrated -land-air-water models, FEST-C can be used in assessing not only the impacts of -agricultural fertilization and management practices on water quantity and -quality, air quality (NH3), and climate (N2O), but also -the impacts of meteorology/climate and air quality (N deposition) on crop -yield, soil erosion, watershed hydrology and quality, and overall C-N-P -biogeochemical status of the agricultural ecosystem. 

- -

- -

Figure 1. The FEST-C process diagram.  The system -works for any domains covering the CONUS and for any of the four WRF -projections (longitude/latitude, Lambert Conformal Conic, Universal Polar Stereographic, -and Mercator).

- -

FEST-C is designed to be used -for CMAQ domains in North America, particularly for domains covering CONUS.  -The current version of the EPIC system for CMAQ has complete modeling -capabilities for grids located within the U.S. To apply this system to other -regions, users must modify the databases (particularly for soil) that were -created within the FEST-C system and to change the agricultural management file -generation, as different regions will likely have different agricultural -management practices in addition to different soil properties.  For areas -outside the U.S., the bidirectional CMAQ internally estimates these inputs for -regions in Canada and Mexico.  The system works for domains at different -resolutions and in any of the four WRF projection coordinate systems: -longitude/latitude, Lambert Conformal Conic, Universal Polar Stereographic, and -Mercator.     

- -

1.2 Components

- -

The version 1.4 release -of the FEST-C system (FEST-C v1.4), which includes Java interface programs, -EPIC FORTRAN codes, and associated data sets, was developed for Linux-based -operating systems.  The FEST-C Java interface is licensed under the Gnu Public -License (GPL) version 3.  The downloaded FEST-C system contains the following -two directories:

- -

·         -festc – contains the Java-based interface.

- -

·         -epic – stores EPIC model version 0509, which has been modified to -meet CMAQ input requirements; and related utilities and data for FEST-C v1.4.  -The original EPIC model description can be obtained from the Texas A&M -AgriLife Research web site (http://epicapex.tamu.edu/files/2013/02/epic0509usermanualupdated.pdf -).  The documentation of the modified EPIC modeling system for CMAQ is included -in the release of the FEST-C system.  It provides detailed information on how -this particular application of EPIC was developed. 

- -

The FEST-C system -requires that the SA Raster Tools system be installed on the same computer system -where FEST-C resides.  For visualization, users can configure FEST-C to view NetCDF -files using the Visualization Environment for Rich Data Interpretation (VERDI) -or NCVIEW.  Both the SA Raster Tools and the VERDI system and their -documentation can be obtained from the CMAS web site (https://www.cmascenter.org/). 

- -

1.3 Installation and Requirements

- -

Users need to -untar the obtained FEST-C and SA packages in their system from the CMAS Center -Software Clearinghouse, https://www.cmascenter.org.  The -programs under FEST-C do not need any compiling, as the system comes with -static compiled tools.  The Raster Tools under SA, which are required by -FEST-C, are not statically pre-compiled with the package.  Depending on the -system configuration, users may need to recompile the SA Raster tools if there -is a library call error when running the tools using FEST-C.  Assuming the -downloaded FEST-C system is installed under the ${FESTC_HOME} directory -and the Spatial Allocator is installed under the ${SA_HOME} directory, -users should perform the following steps:

- -

1.      -Modify ${FESTC_HOME}/festc/config.properties to set:

- -

·         -work.dir – working directory for scenarios.

- -

·         -epic.home – epic home directory, which should be ${FESTC_HOME}/epic; - includes common data and executables for both EPIC and utilities.

- -

·         -sa.home – installed Spatial Allocator directory, which should be ${SA_HOME}.

- -

·         -visual.program.home – directory containing VERDI program.

- -

·         -queue.cmd – queue job submission command such as qsub or bsub.  -Queue configuration (includes queue.name and queue.bigmem as well) for job -submission has to be modified based on the user’s Linux system.  Comment out -(place # sign in the front) the three queue configurations if user’s systems do -not have batch job queuing systems.

- -

·         -queue.name – queue name.

- -

·         -queue.bigmem – big memory setup to be used by the EPIC-to-CMAQ -tool.

- -

·         -debug – set to “true” to print out debug message.  It is -recommended that users not change this setting.

- -

·         -allow.diff.check – set to “true” for checking consistent input in -"Minimum Crop Acres" and "Fertilizer Year" fields -from different subinterfaces.  It is recommended that users not change this -setting.   

- -

2.      -Make a directory called “festc” under the user’s home directory, -which is assumed to be ${USER_HOME}, then copy ${FESTC_HOME}/config.properties -to the ${USER_HOME}/festc directory.  Change the work.dir setting if -needed. 

- -

3.      -Modify ${FESTC_HOME}/festc/festc.sh file to set:

- -

·         -FESTC_HOME to ${FESTC_HOME}/festc.

- -

·         --Xmx1024M to -Xmx2048M (optional) if users want to use 2 GB of -RAM to run the interface.

- -

·         -JAVA path (optional) if users do not want to use the Standard -Edition Runtime Environment (JRE) version 8 for Linux 32-bit and 64-bit systems -that is included in the FEST-C release.

- -

4.      -Modify ${FESTC_HOME}/festc/festc_setup.csh to:

- -

·         -Set the ${FESTC_HOME} and ${SA_HOME} directories.

- -

·         -Source the file in the user’s .cshrc file.

- -

5.      -Launch FEST-C 1.4 interface by typing:

- -

·         -Type festc in any directory with the x-window capability.

- -

Troubleshooting -for the SA Raster Tools:

- -

The SA Raster -Tools have compiled tools which are stored under ${SA_HOME}/bin/64bits.  -The executable tools may not work depending on the system configuration.  If -there is a library error in running the SA Raster Tools within FEST-C, users -should:

- -

·         -Recompile all libraries under ${SA_HOME}/src/libs -following instructions in the ${SA_HOME}/src/libs/README file.

- -

·         -Modiy ${SA_HOME}/src/raster/Makefile for correct paths.

- -

·         -Type “make clean” to clean previous compiled programs.

- -

·         -Type “make” to compile the tools.

- -

·         -Type “make -B install” or “make install” to install compiled -tools.

- -

1.4 Interface Launch

- -

The FEST-C -interface facilitates the creation of the spatial associations, input files, -soil initial­ization, and application processes required by EPIC.  After -preliminary site information and soils are assigned to each grid cell, a -25-year “spin-up” simulation is required to generate initial soil and annual -nitrogen demand conditions that represent the management system the user has -defined.  These initial conditions are provided to the year-specific -application and management scheme.  To launch the FEST-C interface -system, type:

- -

·         -festc or ${FESTC_HOME}/festc/festc.sh

- -

 

- -

The FEST-C interface allows the -user to create, select, and manage different scenario manage­ment schemes under -the File menu for EPIC modeling and sub-interface tools (see Figure 2). 

- -

- -

Figure 2. The -FEST-C interface system.

- -

The system is described in detail -in the remaining sections of this document:

- - - -

1.      -BELD4 Data Generation

- -

2.      -Crop Site Info Generation

- -

3.      -WRF/CMAQ to EPIC

- - - -

1.      EPIC -Site File Generation

- -

2.      Soil -Match for EPIC Spin-up

- -

3.      -Management File Generation for Spin-up

- -

4.      -View/Edit EPIC Inputs

- -

5.      -EPIC Runs for Spin-up

- - - -

1.      -Management File Generation for Application

- -

2.      -EPIC Runs for Application

- - - -

1.      -EPIC Yearly Extraction

- -

2.      -EPIC to CMAQ

- -

3.      -EPIC to SWAT

- -

4.      -Visualization

- -

·         -Section 8: Future Work

- -

2. File Structures for EPIC Modeling

- -

The EPIC model -and related utilities and data are stored under the ${FESTC_HOME}/epic directory.  -The working directory, which is named “scenarios”, is defined by work.dir -in the user’s config.properties file.  In the released tar, “scenarios” -with a sample “test_case” scenario is provided for users to test the -system under the epic directory.  After the installation, users can move -the “scenarios” directory to their working space and modify the work.dir -entry for the new location.  The file structure for EPIC modeling within the -FEST-C system is displayed in Figure 3. 

- -

- -

Figure 3. File -structure for EPIC modeling (directory names in black and files in blue)

- -

The epic -directory contains four subdirectories: model, util, common_data, and doc; -scenarios is under work.dir, which is specified in config file under home -directory. These are described below.

- -

·         -model – used to store the EPIC0509 model for FESTCv1.4.  It -includes one subdirectory:

- -

-        -current: contains two EPIC models for spin-up and -application simulations modified from EPIC0509 for CMAQ modeling.  The EPIC0509 -with many updates were obtained from the Texas A&M AgriLife Research.

- -

·         -doc – contains the documentation on the development of the -EPIC modeling system for CMAQ (EPA_EPIC_application_v1_10252013.pdf).

- -

·         -util – contains utility programs developed by Benson -Consulting to generate site, soil, and management input files required by EPIC. -It has four subdirectories:

- -

-        -siteCreate: contains two programs used by the EPIC Site -File Generation tool.  The programs will not only generate EPIC site files but -also link EPIC sites (grid cell centroids) to the BELD4 crop grid assignments -and the 8-digit hydrologic cataloging units (HUCs) that contain the grid cells -to be used in the soil matching program.  Based on BELD4, this program assigns -only those crops to a grid cell that BELD4 indicates are present at that -location.  This minimizes the number of crop-specific simulations performed -across large domains.  Users need to input the minimum crop acres, usually 0 or -40 acres, but can be any value, to be included in EPIC simulations.  The larger -the cropland area minimum, the fewer crops that will be identified within a -grid for EPIC, the fewer the grid-level simulations and the faster the overall -system execution time.

- -

-        -soilMatch: contains six soil matching programs used by the -Soil Match for EPIC Spinup tool.  Soils are selected based on the U.S. -Department of Agriculture (USDA) 1997 Natural Resource Inventory (NRI) -assignment of each crop in each 8-digit HUC to its most common HUC-8 soil type. -

- -

-        -manageCreate: contains programs to create EPIC management -files for spin-up and application simulations by the Management File -Generation for Spinup and Management File Generation for Application -tools.

- -

-        -swat: contains R codes and associated sample c-shell -scripts to extract daily EPIC outputs, nitrogen deposition, and daily weather -and to transfer them to SWAT input by clicking “EPIC”, “NDEP”, “DailyWETH”, and -“SWAT INPUTS” sequentially.  “SWAT INPUTS” is the last button users should click -for aggregating all input data generated from the first three buttons into SWAT -input format.  The tool associated with “SWAT INPUTS” button requires a text -file including delivery ratios for EPIC to SWAT integration.  The sample text -file is provided in the “share_data” directory under the test_case -scenario as “subbasins-mapping_test_case.csv”.  Users need to create this file -for their corresponding watershed SWAT simulations. 

- -

-        -misc: contains utility programs for converting the -generated BELD4 land use file in NetCDF format to be in IO/API format for the -CMAQ bi-directional modeling (used by the BELD4 tool script), aggregating EPIC -variables from yearly average extraction output by regions (e.g. 8-digit -hydrologic units, states, counties, and the whole domain) and by crops (e.g. 42 -crops), summarizing N fertilizer application from extracted daily files for -CMAQ, and generating files with selected EPIC daily output variables for the -8-digit HUC areas.  Users can access the README file in the directory and modify -the C shell scripts in the subdirectories to use the tools. Users must have the -required R libraries installed to run the R tool utilities.      

- -

·         -common_data – contains data sets needed for EPIC and -utility programs.  Also provided under this subdirectory is the file EPIC_42crop_names.txt, -which contains the crop names and numbers, used in the FEST-C system.  This -directory has the following subdirectories:

- -

-        -BaumerSoils: contains the soil data sets (22,838 soils) built -with soil parameters from the Baumer database developed by Dr. Otto Baumer of National -Soil Survey Laboratory (NSSL) at USDA.  Dr. Baumer used the SOILS5 database and -soil pedon data to develop the representative EPIC data sets.  Benson -Consulting utilized this information to create a subset of soil parameters in -22,838 soil files to be used with EPIC.  Detailed information on the data set -creation can be obtained from the documentation of the EPIC modeling system for -CMAQ.   The raw soil profiles have been QA’d and missing descriptors have been -filled so that they may be similar, but are not identical to the profiles available -through the USGS STATSGO and SURRGO databases.

- -

-        -EPIC_model: contains two 5-year average CMAQ N deposition -daily and NetCDF files and the following two directories, which have common -data files required by EPIC spin-up and application runs.  The two 5-year -average N deposition daily files under dailyNDep_2004 and dailyNDep_2008 -directories provide 5-year average CMAQ-simulated N deposition estimates for -each calendar day over the periods 2002-2006 (referred to as “2002-2006 5-year -CMAQ average” and 2006-2010 (referred to as “2006-2010 5-year CMAQ average”.  These -periods are provided to reflect the documented non-stationarity of N deposition -trends.  The average N deposition data are from the U.S. CMAQ domain which has -the following properties:

- -

GRID_PROJ    -"+proj=lcc +a=6370000.0 +b=6370000.0 +lat_1=33 +lat_2=45 +lat_0=40 -+lon_0=-97"

- -

GRID_ROWS     -299

- -

GRID_COLUMNS  -459

- -

GRID_XMIN    --2556000.0

- -

GRID_YMIN    --1728000.0

- -

GRID_XCELLSIZE -12000.0

- -

GRID_YCELLSIZE -12000.0

- -

The -N deposition data from the nearest grid point in the average daily sets is selected -in EPIC simulations.

- -

·         -spinup – has common files used for EPIC spin-up -simulations. For all crops except potatoes, the spin-up is set to run for 25 -years using the EPIC statistical weather generator (see the weather generator discussion -in the EPIC documenta­tion from the Texas A&M AgriLife Research).  We have -arbitrarily set the starting year as 1978 in EPICCONT.DAT.  The termination -date is not used by any subsequent codes and, since the driving data are -statistically generated, do not exactly correspond to any observation year.  For -potatoes, the spin-up is set to run for 100 years from 1903 in EPICCONT_POTATOES.DAT. - 

- -

·         -app – contains common files used for EPIC application -simulations.  In the FEST-C system, users input the target year (1 year only) -for the EPIC application simulation.  When a new scenario is created, -EPICCONT.DAT from this directory is copied to the scenarios/“scenario -name”/share_data directory and the simulation period is changed to 2 years -starting from the year previous to the simulation year.  Two years’ worth of -weather data are needed to support production of fall-sown crops.  At present, -the same weather is used for both years.  In the future, an option may be added -to support input of two unique weather time series. 

- -

-        -gisFiles: includes U.S. counties, U.S. states plus some -boundary areas in Canada and Mexico, U.S. 8-digit HUC shapefiles, and elevation -and slope raster files.  The readme file in the directory describes each file -and associated attributes in detail. 

- -

-        -statWeath: contains weather station climate statistics -files distributed with the standard EPIC package.

- -

-        -util: includes common files used by the utility programs.  -This directory has two subdirectories:

- -

·         -soilMatch – has input files used by the soil matching -program to create EPIC soil files for the EPIC Runs for Spinup tool.

- -

·         -manageCreate – contain files to be used in generating EPIC -spin-up and application management files.  We developed management data with -fertilizer types applied in 2001 and 2006 for each of 10 production regions -(Northeast, Appalachia, Southeast, Lake States, Corn Belt, Delta States, -Northern Plains, Southern Plains, Mountain, and Pacific) (see the region map in -Cooter et al. [2012], which is listed in the “Online Resources” section of the -FEST-C web site (http://www.cmascenter.org/fest-c/).  -Fertilizer types (but not amounts) applied are based on fertilizer sales of 62 -major fertilizer types by state.  Users can obtain detailed information from -the docu­mentation for the EPIC modeling system for CMAQ.  It is recommended -that 2001 be used for applications prior to 2006, and that 2006 be used for -applications from 2006 through 2010.  We anticipate that a 2011 fertilizer type -file will be included in the next interim release.  Fertilizer types applied -are used by the EPIC management file generation for application, and they are -stored under the following two subdirectories: 

- -

-        -2001: for 2001 fertilizer year management file -generation. 

- -

-        -2006: for 2006 fertilizer year management file -generation. 

- -

In -both cases, regional fertilizer data information is stored under the directory:

- -

-        -regionFert 

- -

·         -scenarios – contains EPIC application scenarios and it is -the working directory for a user.  The directory is described separately below -this bulleted list.

- -

 

- -

In general, users should not change -the data files described in the above directories.  All files generated by -users’ applications are stored under the scenarios directory.  When the -user creates a scenario by selecting “New Scenario” under the File menu, -the following items are created:

- -

·         -scenariosInfo – a metadata file that stores information for -the created scenario, which is assumed to be named by the user as “scenario -name”.  This directory contains:

- -

-        -“scenario name”: an XML file that stores the scenario information.  -

- -

-        -logs: directory containing the script file used to create (or -copy or delete as well) the scenario and execution log file.

- -

·         -“scenario name” – scenario directory that will contain all -generated files for this scenario.

- -

Under each scenario directory, the -following directories are created for EPIC modeling:

- -

·         -share_data – contains all data sets generated for EPIC -modeling and to be used by all crops modeled.  The following two data subdirectories -which store generated EPIC site files and daily weather files are included -under this directory: 

- -

-        -SIT: contains EPIC site files.

- -

-        -dailyWETH: contains daily weather and N files for EPIC -modeling.

- -

·         -scripts – stores script and log files created to run the -tools within the FEST-C interface.  All tools are executed through the Linux -queue system.  Users should always check the log file to make sure that the -queue job completed correctly.  Unwanted files under this directory should be -cleaned out periodically. 

- -

·         -work_dir – contains some intermediate or temporary files -created by the FEST-C tools.  Not many files are created under this directory.  -

- -

·         -21 crop dirs ( "HAY", "ALFALFA", -"OTHER_GRASS", "BARLEY", "EBEANS", -"CORNG", "CORNS", "COTTON", "OATS", -"PEANUTS", "POTATOES", "RICE", "RYE", -"SORGHUMG", "SORGHUMS", "SOYBEANS", -"SWHEAT", "WWHEAT", "OTHER_CROP", -"CANOLA", "BEANS") – the 21 crop directories are -created by the EPIC Site File Generation tool.  Under each crop -directory there are many files that are created for generating EPIC input -files.  The spinup and app subdirectories described below are -also created from management file generation and EPIC runs for spin-up and -application:

- -

-        -spinup: contains files created from the EPIC management -file generation and EPIC runs for spin-up tools.  It contains the following -three subdirectories:

- -

·         -manage – contains EPIC run files, EPIC site management -files created by the Management File Generation for Spinup tool, and -tile drain soil list file. The management files and tile drain soil list file are -contained under the following subdirectories:

- -

-        -OPC: contains the management schedule for each domain grid -cell containing rain-fed and irrigated crop.  Variables (schedule) can be -interpreted using the documentation for the EPIC modeling system for CMAQ.

- -

-        -tileDrain: contains the SOILLIST.DAT which has soil tile -drain information for EPIC spinup runs.  In general, if a soil is classified as -hydric, then it is assumed to drain.

- -

·         -rainf – contains files for each domain grid cell that are created -by the EPIC Runs for Spinup tool from rain-fed crops.  It contains the -following output directories (see the EPIC documentation from the Texas A&M -AgriLife Research):

- -

-        -DFA: daily fertilizer and other output.

- -

-        -NCM: monthly fertilizer and other output.

- -

-        -NCS: monthly soil output.

- -

-        -OUT: standard EPIC output file that contains various -budget tables and summaries of the simulation which are useful for debugging.

- -

-        -SOL: soil output files that are used as initial values for -the application.

- -

-        -TNA: annual fertilizer and other outputs.

- -

-        -TNS: annual soil output.

- -

·         -irr – contains files for each domain grid cell containing the -particular crop that were created by the EPIC Runs for Spinup tool from -irrigated crops.  It contains the following output directories:

- -

-        -DFA: daily fertilizer and other output.

- -

-        -NCM: monthly fertilizer and other output.

- -

-        -NCS: monthly soil output.

- -

-        -OUT: standard EPIC output file that contains various -budget tables and summaries of the simulation that are useful for debugging.

- -

-        -SOL: soil output files.

- -

-        -TNA: annual fertilizer and other outputs that are useful -for debugging.

- -

-        -TNS: annual soil output.

- -

-        -app: contains files created from the management file -generation and EPIC runs for application tools.  It contains the following -three subdirectories:

- -

·         -manage – contains EPIC run files, EPIC site management -files created by the Management File Generation for Application tool, -and tile drain soil list file.  Management files and the tile drain soil list -file are contained under the following subdirectories:

- -

-        -OPC: contains the management schedule for each domain grid -cell containing rain-fed and irrigated crop.  Variables (schedule) can be -interpreted using the documentation for the EPIC modeling system for CMAQ.

- -

-        -tileDrain: contains the SOILLIST.DAT which has soil tile -drain information for EPIC application runs.

- -

·         -rainf – contains files created by the EPIC Runs for -Application tool from rain-fed crops.  It contains the following output -directories (see the EPIC documentation from the Texas A&M AgriLife -Research):

- -

-        -DFA: daily fertilizer and other output.

- -

-        -NCM: monthly fertilizer and other output.

- -

-        -NCS: monthly soil output.

- -

-        -OUT: standard EPIC output file that contains various -budget tables and summaries of the simulation (useful for debugging).

- -

-        -SOL: soil output files.

- -

-        -TNA: annual fertilizer and other outputs.

- -

-        -TNS: annual soil output.

- -

·         -irr – contains files created by the EPIC Runs for -Application tool from rain-fed crops.  It contains the following output -directories:

- -

-        -DFA: daily fertilizer and other output.

- -

-        -NCM: monthly fertilizer and other output.

- -

-        -NCS: monthly soil output.

- -

-        -OUT: standard EPIC output file that contains various -budget tables and summaries of the simulation (useful for debugging).

- -

-        -SOL: soil output files.

- -

-        -TNA: annual fertilizer and other output.

- -

-        -TNS: annual soil output.

- -

·         -output4CMAQ – stores EPIC output files and extracted NetCDF -files for quality assurance (QA) and CMAQ bidirectional NH3 -modeling.  This directory contains the two following subdirectories:

- -

-        -spinup: contains all files created from EPIC spin-up -simulations for CMAQ.  It contains the following three subdirectories:

- -

·         -5years – contains extracted average EPIC output for each -crop from the last five years of the spin-up simulation.  Files are named as -“BELD4 Crop Number”.dat (see Table 1 in Section 4.1 for crop numbers). 

- -

·         -daily – stores daily EPIC output files for the EPIC spin-up -simulation of each crop.  “BELD4 Crop Number”.NCS is for soil output and “BELD4 -Crop Number”.NCD is for fertilizer and other daily output. 

- -

·         -toCMAQ – contains created NetCDF and IO/API files with -EPIC spin-up output for selected modeling grid cells with crop data.  The NetCDF -output files are created using the FEST-C tools by extracting data files stored -under the 5years or daily directories listed above.

- -

-        -app: stores files created from EPIC application simulations -for CMAQ.  It contains the following three subdirectories:

- -

·         -year – contains extracted average EPIC output for the EPIC -application year.  Files are named as “BELD4 Crop Number”.dat. 

- -

·         -daily – stores daily EPIC output files for the EPIC application -simulation of each crop.  “BELD4 Crop Number”.NCS is for soil output and “BELD4 -Crop Number”.NCD is for fertilizer and other daily output. 

- -

·         -toCMAQ – contains created NetCDF and CMAQ-ready IO/API -files with the BELD4 data and EPIC application simulation results for the -modeling domain.  The NetCDF output files are created using the FEST-C tools by -extracting data files stored under the year or daily directories -listed above.

- -

·         -output4SWAT – stores daily EPIC, N deposition, and -meteorology files summarized by regions and SWAT-ready input files for SWAT -simulation.  This directory contains four subdirectories:

- -

-        -dailyEPIC – contains runoff data extracted from EPIC daily -output files.  The extracted data are summarized by the domain, county, state, HUC2, -HUC6, and HUC8. 

- -

-        -dailyWETH – contains extracted weather data.

- -

-        -NDEP – contains extracted nitrogen deposition data.

- -

-        -swat_inputs – contains SWAT-ready EPIC, weather, and N -deposition input files in subdirectories named as dailydep, dailyweath, -and EPICinputPoint

- -

3. Scenario Management Selections under the File Menu

- -

 

- -

There are five scenario management -selections (as well as Exit) under the File menu at the upper left of the -FEST-C tool bar: Open Scenario, New Scenario, Copy Scenario, -Save Scenario, and Delete Scenario. Each of these is described -below.

- -

·         -Open Scenario – to open an already-created scenario. Users -always need to either open or create (see next bullet) a scenario to work on.  -Users can select any one of the scenarios under the scenarios/scenariosInfo -directory.  After users open a scenario, information for the scenario, such as -the domain description, will be automatically filled in by the FEST-C tool -interface.  Within the FEST-C system, users have to work within a scenario to -execute any of the tools except the Visualization tool.  Figure 4 shows -the interface used to open the test case created in the FEST-C system (The test_case -scenario is described at the beginning of Section 4).

- -

- -

Figure 4. Open Scenario selection -window used to open the test_case scenario.

- -

 

- -

·         -New Scenario – to create a new scenario (versus opening -one that’s already been created). In creating a new scenario, the user has to -provide the following information for a CMAQ modeling domain and EPIC -simulation year (see Figure 5):

- -

-        -Rows, Columns: the number of rows and columns for the -domain.

- -

-        -XCellSize, YCellSize: x and y resolution for -the grid cell.

- -

-        -XMin, YMin: x and y coordinates of the lower -left corner of the lower left grid cell.  Users can often find this information -in the GRIDDESC file in the Meteorology-Chemistry Interface Processor (MCIP) -output.

- -

- -

Figure -5. New Scenario selection window with input to create the test_case -scenario within FEST-C.

- -

 

- -

-        -Proj4Projection: domain projection defined in Proj4 format -(see details at http://geotiff.maptools.org/proj_list/).  -The interface sets the Lambert Conformal Conic projection, which is used by the -CMAQ U.S. 12-km domain as the default.  Users can change it to any projection -supported for CMAQ modeling.

- -

-        -Grid Name: user-supplied name for the domain, using no -more than 16 alphanumeric characters and no spaces. 

- -

-        -Simulation Year: year (YYYY) for the EPIC simulation.  -FEST-C is designed to simulate yearly fertilizer application information for -CMAQ bidirectional NH3 modeling.

- -

-        -NLCD/MODIS Data Year: year (YYYY) for the NLCD/MODIS land -cover data used for the EPIC simulation.  NLCD/MODIS land cover data are required -in the EPIC simulation within FEST-C for CMAQ bidirectional NH3 -modeling.  Currently, users can select 2001, 2006, or 2011 NLCD/MODIS data -year.  2016 NLCD/MODIS data selection will be added to the system in the -future.

- -

-        -Scenario Name: name for the scenario, using alphanumeric -characters and no spaces.

- -

When a new scenario is -created, the following files and directories are created:

- -

-        -scenarios/scenariosInfo/“scenario name”: XML file to store the scenario information.

- -

-        -scenarios/“scenario name”: directory -to store all generated information for this scenario.  Some subdirectories are -also generated under this scenario directory (see Section 2 for file -structures).

- -

-        -scenarios/“scenario name”/share_data/EPICCONT.DAT: contains -EPIC constant parameters.  The simulation period is a two-year period starting with -the year before the simulation year.

- -

·         -Copy Scenario – to copy an existing scenario under the scenarios/scenariosInfo -directory to a new scenario with a defined simulation year, which can be the same -as or different from the existing scenario year (see Figure 6).  Note that if -the existing scenario contains many crop simulations, this action can take a -long time to complete in a background queue job. 

- -

 

- -

- -

Figure 6. Copy Scenario selection window.

- -

 

- -

·         -Save Scenario – to save a scenario after a user has worked -on it.  Only the input information for the scenario tool interfaces is saved.  -When the user performs the FEST-C tool actions, generated files are always -saved under different directories, described in Section 2. 

- -

·         -Delete Scenario – to -delete a scenario.  This is also run as a background submission and can -take some time. All directories and subdirectories for that scenario are -deleted completely.

- -

·         -Exit – to exit the FEST-C interface.  You will be asked if -you want to save the scenario you were working on before exiting the tool.

- -

The action performed by making a selection -under the File menu (e.g., copy, create, delete) is executed by a script file -through the queue job. The script and log files are stored under the scenarios/scenariosInfo/logs -directory.  Users should check the log files under the directory to -make sure that the selected action completely correctly.

- -

4. The Pre-EPIC File Generation Tools

- -

 

- -

Before describing the various -FEST-C tools in Sections 4 through 7, we must first discuss the test_case -scenario in the FEST-C system, because we use this scenario to demonstrate the -input and output components on the tool interface.  The test_case -scenario is a small 12-km domain with 25 rows and 25 columns in the CMAQ -standard projection.  The domain is located in the northwest corner of Iowa and -crosses into Minnesota, South Dakota, and Nebraska.  Figure 7 illustrates the -domain grid cells with the identification numbers (GRIDID) used in the FEST-C -system; colors are used to indicate the crop percentage for each grid cell as generated -from 2006 NLCD data.  All 625 (25´25) -12-km grid cells in this test domain have crop coverage, and most of them have -more than 75% crop coverage.  The GRIDID for a grid cell with row and column -starting from 1 is defined as:

- -

                                                          -(1)

- -

where columns is the number -of columns for the domain.  Row and column start from 1 at the lower left -corner cell in the domain.  Users can compute the row and column for a grid -cell with GRIDID as:

- -

       -                                            (2) -

- -

                                     (3)

- -

where floor is for rounding -down the value and remainder is for taking the remainder from the -division.     

- -

- -

Figure 7. -FEST-C test_case scenario 12-km domain in the U.S. northern Central Plains. -Associated with each grid cell is an identification number (GRIDID) and a color -that indicates crop coverage percentage.  The domain’s cells are numbered from -1 for the lower left corner cell to 625 for the upper right corner cell.

- -

 

- -

In Section 4, -we discuss the first three tools in the FEST-C interface: the BELD4 Data -Generation tool, the Crop Site Info Generation tool, and the WRF/CMAQ-to-EPIC -tool. These are used to prepare site crop and spatial data for EPIC input file -generation and to generate required daily weather data and optional nitrogen -deposition data for the EPIC simulation year.  All three tools were developed -in the SA Raster Tools system.

- -

4.1 BELD4 Data Generation

- -

EPIC modeling for a CMAQ domain requires BELD4 data, which are used for -selecting grid cells with crop coverage.  The BELD4 Data Generation tool -allows users to compute the BELD4 dataset for a selected scenario.  For detailed -information, users can consult the SA Raster Tools documentation: https://www.cmascenter.org/sa-tools/.  -Figure 8 shows the interface used to compute the BELD4 dataset for the test_case -scenario.

- -

- -

Figure 8. The BELD4 Data Generation tool -interface for the test_case scenario.

- -

Before running this tool, users -need only to make sure that the following two entries are correct for their -scenarios:

- -

·         -NLCD/MODIS Data Year – the year defined when creating the -scenario; it can be either 2001, 2006, or 2011.  Processed 2001, 2006, and 2011 -crop tables from the U.S. and Canada are stored under the ${SA_HOME}/data -directory for this tool.  The 42 rain-fed and irrigated crops generated from -the BELD4 tool and modeled in the FEST-C system are displayed in Table 1.  In -addition to crop numbers used in BELD4 (new version of BELD), the table also -lists BELD3 (older version) numbers, because we started building the FEST-C -system using the BELD3 data.  Crop numbers used in EPIC modeling often follow -the BELD3 crop numbers (from 22 to 63), but the output files from EPIC modeling -for use in CMAQ use the BELD4 crop numbers (from 1 to 42).  If a new crop is to -be modeled in the FEST-C system, new crop tables under the SA data -directory must be generated and the BELD4 tool has to be modified as well.  -Table 2 provides additional information on how crops are mapped to each EPIC crop -type.

- -

Table 1. The 42 rain-fed and -irrigated crops modeled in the FEST-C system.

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

BELD4

-
-

BELD3

-
-

Crop Name

-
-

BELD4

-
-

BELD3

-
-

Crop Name

-
-

BELD4

-
-

BELD3

-
-

Crop Name

-
-

1

-
-

22

-
-

Hay

-
-

15

-
-

36

-
-

Cotton

-
-

29

-
-

50

-
-

SorghumSilage

-
-

2

-
-

23

-
-

Hay_ir

-
-

16

-
-

37

-
-

Cotton_ir

-
-

30

-
-

51

-
-

SorghumSilage_ir

-
-

3

-
-

24

-
-

Alfalfa

-
-

17

-
-

38

-
-

Oats

-
-

31

-
-

52

-
-

Soybeans

-
-

4

-
-

25

-
-

Alfalfa_ir

-
-

18

-
-

39

-
-

Oats_ir

-
-

32

-
-

53

-
-

Soybeans_ir

-
-

5

-
-

26

-
-

Other_Grass

-
-

19

-
-

40

-
-

Peanuts

-
-

33

-
-

54

-
-

Wheat_Spring

-
-

6

-
-

27

-
-

Other_Grass_ir

-
-

20

-
-

41

-
-

Peanuts_ir

-
-

34

-
-

55

-
-

Wheat_Spring_ir

-
-

7

-
-

28

-
-

Barley

-
-

21

-
-

42

-
-

Potatoes

-
-

35

-
-

56

-
-

Wheat_Winter

-
-

8

-
-

29

-
-

Barley_ir

-
-

22

-
-

43

-
-

Potatoes_ir

-
-

36

-
-

57

-
-

Wheat_Winter_ir

-
-

9

-
-

30

-
-

BeansEdible

-
-

23

-
-

44

-
-

Rice

-
-

37

-
-

58

-
-

Other_Crop

-
-

10

-
-

31

-
-

BeansEdible_ir

-
-

24

-
-

45

-
-

Rice_ir

-
-

38

-
-

59

-
-

Other_Crop_ir

-
-

11

-
-

32

-
-

CornGrain

-
-

25

-
-

46

-
-

Rye

-
-

39

-
-

60

-
-

Canola

-
-

12

-
-

33

-
-

CornGrain_ir

-
-

26

-
-

47

-
-

Rye_ir

-
-

40

-
-

61

-
-

Canola_ir

-
-

13

-
-

34

-
-

CornSilage

-
-

27

-
-

48

-
-

SorghumGrain

-
-

41

-
-

62

-
-

Beans

-
-

14

-
-

35

-
-

CornSilage_ir

-
-

28

-
-

49

-
-

SorghumGrain_ir

-
-

42

-
-

63

-
-

Beans_ir

-
- -
- -

Table 2. Mapping of the 42 rain-fed and -irrigated crops for U.S. and Canada (Mexico will be available in a future -release).

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

BELD4

-
-

Crop Name

-
-

USA

-
-

Canada

-
-

1

-
-

Hay

-
-

HAY- (HAY, ALFALFA)-(HAY, - WILD) + HAYLAGE, (EXCL ALFALFA)

-
-

All other tame hay and - fodder crops

-
-

2

-
-

Hay_ir

-
-

Same items, irrigated

-
-

N/A

-
-

3

-
-

Alfalfa

-
-

ALFALFA HAY + ALFALFA - HAYLAGE

-
-

Alfalfa and alfalfa - mixtures

-
-

4

-
-

Alfalfa_ir

-
-

 Same items, irrigated

-
-

N/A

-
-

5

-
-

Other_Grass

-
-

(AG LAND, CROPLAND, - PASTURED ONLY )-(Hay+Alfalfa)

-
-

N/A

-
-

6

-
-

Other_Grass_ir

-
-

N/A

-
-

N/A

-
-

7

-
-

Barley

-
-

BARLEY

-
-

Barley

-
-

8

-
-

Barley_ir

-
-

 BARLEY, irrigated

-
-

N/A

-
-

9

-
-

BeansEdible

-
-

BEANS, DRY EDIBLE, LIMA; - BEANS, DRY EDIBLE, (EXCL LIMA)

-
-

Dry white beans; Other dry - beans

-
-

10

-
-

BeansEdible_ir

-
-

Same items, irrigated

-
-

N/A

-
-

11

-
-

CornGrain

-
-

CORN, GRAIN

-
-

Corn for grain

-
-

12

-
-

CornGrain_ir

-
-

CORN, GRAIN, IRRIGATED

-
-

N/A

-
-

13

-
-

CornSilage

-
-

CORN, SILAGE

-
-

Corn for silage

-
-

14

-
-

CornSilage_ir

-
-

CORN, SILAGE, IRRIGATED

-
-

N/A

-
-

15

-
-

Cotton

-
-

COTTON

-
-

N/A

-
-

16

-
-

Cotton_ir

-
-

COTTON, IRRIGATED

-
-

N/A

-
-

17

-
-

Oats

-
-

OATS

-
-

Oats

-
-

18

-
-

Oats_ir

-
-

OATS, IRRIGATED

-
-

N/A

-
-

19

-
-

Peanuts

-
-

PEANUTS

-
-

N/A

-
-

20

-
-

Peanuts_ir

-
-

PEANUTS, IRRIGATED

-
-

N/A

-
-

21

-
-

Potatoes

-
-

POTATOES+SWEET POTATOES

-
-

Potatoes

-
-

22

-
-

Potatoes_ir

-
-

Same fractional breakdown - of rainfed vs irrigated potatoes from 2006 data

-
-

N/A

-
-

23

-
-

Rice

-
-

N/A

-
-

N/A

-
-

24

-
-

Rice_ir

-
-

RICE, IRRIGATED

-
-

N/A

-
-

25

-
-

Rye

-
-

RYE

-
-

Fall rye

-
-

26

-
-

Rye_ir

-
-

RYE, IRRIGATED

-
-

N/A

-
-

27

-
-

SorghumGrain

-
-

SORGHUM, GRAIN

-
-

N/A

-
-

28

-
-

SorghumGrain_ir

-
-

SORGHUM, GRAIN, IRRIGATED

-
-

N/A

-
-

29

-
-

SorghumSilage

-
-

SORGHUM, SILAGE

-
-

N/A

-
-

30

-
-

SorghumSilage_ir

-
-

SORGHUM, SILAGE, IRRIGATED

-
-

N/A

-
-

31

-
-

Soybeans

-
-

SOYBEANS

-
-

Soybeans

-
-

32

-
-

Soybeans_ir

-
-

SOYBEANS, IRRIGATED

-
-

N/A

-
-

33

-
-

Wheat_Spring

-
-

WHEAT, SPRING, DURUM; - WHEAT, SPRING, (EXCL DURUM)

-
-

Spring wheat (excluding - durum); Durum wheat

-
-

34

-
-

Wheat_Spring_ir

-
-

WHEAT, SPRING, DURUM, - IRRIGATED; WHEAT, SPRING, (EXCL DURUM), IRRIGATED

-
-

N/A

-
-

35

-
-

Wheat_Winter

-
-

WHEAT, WINTER

-
-

Winter wheat

-
-

36

-
-

Wheat_Winter_ir

-
-

WHEAT, WINTER, IRRIGATED

-
-

N/A

-
-

37

-
-

Other_Crop

-
-

(AG LAND, CROPLAND) - (AG - LAND, CROPLAND, PASTURED ONLY) -sum of rainfed crops

-

 

-

If “AG LAND, CROPLAND” is - larger

-
-

Mixed grains; Spring rye; - Flaxseed; Forage seed for seed; Mustard seed; Sunflowers; Canary seed; - Ginseng; Buckwheat; Sugar beets; Caraway seed; Triticale; Other field crops

-
-

38

-
-

Other_Crop_ir

-
-

Irrland= (AG LAND, (EXCL - HARVESTED CROPLAND), IRRIGATED – ACRES) + (AG LAND, CROPLAND, HARVESTED, - IRRIGATED – ACRES)

-

=Irrland – sum of irr crops - (if irrland is larger)

-
-

N/A

-
-

39

-
-

Canola

-
-

CANOLA

-
-

Canola (rapeseed)

-
-

40

-
-

Canola_ir

-
-

CANOLA, IRRIGATED

-
-

N/A

-
-

41

-
-

Beans

-
-

PEAS, DRY EDIBLE

-
-

Dry field peas; Lentils; - Chick peas

-
-

42

-
-

Beans_ir

-
-

PEAS, DRY EDIBLE, IRRIGATED

-
-

N/A

-
- -
- -

 

- -

·         -NLCD/MODIS List File – set to the fixed-format text file that -contains downloaded NLCD land use, imperviousness, and canopy data files and -downloaded tiled MODIS land cover (MCD12Q1) data sets.  The interface sets the -file ${SA_HOME}/data/ nlcd_modis_files_{NLCD/MODIS Data Year}.txt as the default -file.  Users need to download NLCD and MODIS land cover data sets and modify -the text file accordingly using the paths and names for the downloaded data -sets.  The text file must have the same fixed titles and format as in the -default file.  ${SA_HOME}/data/sat/README contains instructions on downloading -the data sets.  If users want to generate a 2001 BELD4 data set, 2001 NLCD and -MODIS land cover data sets have to be downloaded from the NLCD web site (https://www.mrlc.gov/finddata.php) -and MODIS land products web site (https://lpdaac.usgs.gov/products/modis_products_ -table/mcd12q1 ), and the nlcd_modis_files_2001.txt list file has to -be modified following the format in this sample file.

- -

 

- -

When the Run button on the BELD4 -Data Generation tool interface is clicked, a c-shell (csh) script file is -generated under the scenarios/”scenario name”/scripts directory.  This -file is submitted to the system as a queue job after the user clicks OK, and a -log file for the job execution will be generated after the queue job is finished.  -Users should always check for error messages in the log file, based on the -information provided in the Message Box (shown in Figure 8). 

- -

 

- -

The outputs produced by the tool -are the following files, which are stored under the ”scenario -name”/share_data and ”scenario name”/output4CMAQ/app/ toCMAQ directories:

- -

·         -beld4_{Gird Name}_{NLCD/MODIS Data Year}.nc (beld4_TESTGRIDS_2006.nc -for the test_case scenario) – both  NetCDF and I/O API formatted files -containing gridded percentage data for imperviousness, canopy, 194 tree species, -40 NLCD/MODIS land cover classes, and 42 BELD4 crops are created.  The NetCDF domain- -and resolution-specific data file is a required input to the Crop Site Info -Generation tool discussed in the next section.  CMAQ bi-directional NH3 -modeling requires the I/O API formatted BELD4 output file under the ”scenario name”/output4CMAQ/app/toCMAQ directory.

- -

·         -beld4_{Grid Name}_{ NLCD/MODIS Data Year}.txt -(beld4_TESTGRIDS_2006.txt for the test_case scenario) – a text table -containing gridded percentage data for impervious­ness, canopy, and 40 NLCD/MODIS -land cover classes for a specific domain and grid resolution.  

- -

4.2 Crop Site Info Generation

- -

The Crop Site Info Generation tool is used to -compute EPIC site (grid cells) and crop informa­tion for EPIC modeling.  The -tool processes spatial boundary shapefiles and elevation and slope image data -to generate site infor­mation data needed in EPIC modeling.  Figure 9 displays -the tool interface used to compute the crop site information for the test_case -scenario.  The tool uses the spatial data sets stored under ${FESTC_HOME}/epic/common_data/gisFiles -and input files from the ${SA_HOME}/data directory.  Before running this -tool, users need only to choose the following two entries for this tool:

- -

·         -BELD4 NetCDF File – this is the BELD4 NetCDF file generated -using the BELD4 tool described above.  The file name should be of the form beld4_{Gird -Name}_{NLCD/MODIS Data Year}.nc (e.g. beld4_TESTGRIDS_2006.nc for the test_case -scenario).  If this file does not exist, the interface will indicate this after -Run is clicked.  If this is the case, users need to either run the BELD4 tool to -generate this data set or input anywhere within the computer system a BELD4 NetCDF -file that is based on the same domain as the domain of the scenarios with which -the users are working.

- -

·         -Minimum Crop Acres – this is the minimum crop area for at -least one of the 42 possible crops in a grid cell, if the grid cell is to be -selected for EPIC simulation.  For instance, users can set it to be 40 acres for -representing the smallest commercially viable farm size.  For finer grid -resolutions or for domains in which smaller commercial enterprises make up a -significant fraction of farms (e.g., orchards, some vegetable and specialty -crops), users may need to reduce this minimum to adequately characterize the -distribution of agricultural lands.  For including all cropland in simulations, -users should set it to be 0.0.  Doing so may increase the number of simulated -grid cells (sites), which can also increase run time. 

- -

- -

Figure 9. The Crop Site Info Generation tool -interface used for the test_case scenario.

- -

After Run has -been clicked and the queue job has completed, users should check the log file -under their scenario’s scripts directory to see whether any errors occurred -during execution.  The tool generates the following three text output files -stored under scenarios/”scenario name”/share_data:

- -

·         -EPICSites_Info.csv – contains the GRIDID, XLONG, YLAT, ELEVATION, SLOPE_P, -HUC8, REG10, STFIPS, CNTYFIPS, GRASS, CROPS, CROP_P, COUNTRY, and -COUNTRY-PROVINCE items used for creating EPIC site files.

- -

·         -EPICSites_Crop.csv – contains the GRIDID, acreages of 42 possible -crops within each grid cell, COUNTRY, and HUC8 items used in EPIC site and soil -file generation. 

- -

·         -allSites_Info.csv – contains the GRIDID, XLONG, YLAT, ELEVATION, -SLOPE_P, HUC8, REG10, STFIPS, CNTYFIPS, GRASS, CROPS, CROP_P, COUNTRY, and -COUNTRY-PROVINCE items for all grid cells to be used in the SWAT watershed -extraction.

- -

4.3 WRF/CMAQ to EPIC

- -

The WRF/CMAQ-to-EPIC -tool is used to generate EPIC daily weather data and, if the option is -selected, N deposition inputs to be used in EPIC application simulations.  The -tool reads EPIC grid cell information stored in the allSites_Info.csv file -generated using the Crop Site Info Generation tool (the previous tool).  -It extracts daily weather input data from WRF simulation output (METCOR2D data -arrays) into a NetCDF file and EPIC-ready text files.  Users need to make sure -that the right version of the WRF/CMAQ-to-EPIC tools are compiled under -the Spatial Allocator. There are two versions of this tool: one for CMAQ before -version 5.2 and one for CMAQ v5.2 or above version. 

- -

There are up to -four options currently available for the inclusion of daily atmospheric deposition -data in EPIC simulations: (1) no N deposition, (2) the original EPIC -default (assumes a constant N concentration of 0.8 ppm in precipitation and no -dry deposition), and (3) CMAQ hourly output files (DRYDEP, WETDEP1) from a -previous CMAQ run (unidirectional or bidirectional), and (4) a pre-processed -set of 5-yr average CMAQ deposition estimates for the period 2002-2006 (labeled -as 2004) and 2006-2010 (labeled as 2008).  In the vicinity of areas receiving -significant atmospheric dry deposition, such as areas immediately surrounding -large animal feeding operations, this information can impact EPIC -biogeochemistry and subsequent estimates of plant N application needs.  If -speciated N deposition is available, oxidized wet and dry deposition are -assumed to enter the EPIC soil nitrate pool, and reduced wet and dry deposition -is assumed to enter the EPIC soil ammonium pool.  If CMAQ hourly output files -are selected for this tool, the MCIP and CMAQ domains must be the same as the -domain defined in the EPIC scenario.  Figure 10 shows this tool interface as used -for the test_case scenario. 

- -

- -

Figure 10. The WRF/CMAQ-to-EPIC tool interface -used for the test_case scenario.

- -

Before running this tool, users must -provide input for the following three items in the interface:

- -

·         -MCIP Data Directory – this directory contains processed -WRF files output by MCIP for the EPIC simulation year.  This tool requires only -MCIP METCRO2D output files.  METCRO2D output files must have names of the -format METCRO2D*{DATE} in which * can be any non-digit characters and {DATE} -can be in one of four date formats: YYYYMMDD, YYMMDD, YYYYDDD, or YYDDD (e.g., METCRO2D_051226)

- -

·         -Deposition Selection – used to select one of the following -three options:

- -

-        -CMAQ deposition directory: select this option to use CMAQ -deposition output files.  If this is selected, users must set the CMAQ -deposition file directory in the next field on the interface.

- -

-        -Default: this option assumes that the N mixing ratio is 0.8 ppm -for wet oxidized N deposition.  The tool computes wet oxidized N deposition based -only on WRF rainfall, and other N deposition variables are assumed to be zero.

- -

-        -Zero: this option assumes that there is no atmospheric N.

- -

·         -CMAQ Deposition Directory – used to set the directory -containing the CMAQ dry and wet deposition output files for the simulation year -if “CMAQ deposition directory” was chosen in the previous field.  The dry and -wet deposition file names must contain the string “DRYDEP” or “WETDEP”.  In -addition, the deposition file names must end with “*{DATE}” in the format that -is described for the MCIP files above (e.g., an MCIP file can be named as METCRO2D_20030416 -and the deposition files can be named CCTM_M2f_v14soa_v3.4beta3_2003.DRYDEP.20030416 -and CCTM_M2f_v14soa_v3.4beta3_2003.WETDEP1.20030416).  

- -

After Run has -been clicked and the queue job has finished, users should check the log file -under their scenario’s scripts directory to see whether any errors -occurred during execution.  The tool generates the following three output files -stored under scenarios/”scenario name”/share_data:

- -

·         -dailyWETH/“GRIDID”.dly – daily weather and N -files for each selected grid cell for EPIC modeling.  “GRIDID” is the -identification number for a selected grid cell (see Figure 7).  Each daily file -contains 14 formatted data items (listed in Table 3) to be used in the EPIC -runs for the simulation year (same as the weather year).  This daily weather -file is duplicated for the year before the simulation year because we run the -EPIC model for a two-year period using daily time steps. 

- -

·         -EPICW2YR.2YR – daily weather file list to be used in EPIC -application modeling.  It is defined in ${FESTC_HOME}/epic/common_data/EPIC_model/app/EPICFILE.DAT.

- -

·         -site_weather_dep_${YEAR}0101_to_${YEAR}1231.nc – a single NetCDF -file with daily time steps for the simulation year.  It contains extracted -daily weather and N deposition data for the all grid cells from the allSites_Info.csv -file.  Users can use the Visualization tool (discussed in Section 7) to -display the values of a selected variable spatially. 

- -

 

- -

Table 3. EPIC daily weather and nitrogen deposition -variables.

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Index

-
-

Variable

-
-

Index

-
-

Variable

-
-

1

-
-

Year

-
-

8

-
-

Daily Average Relative Humidity

-
-

2

-
-

Month

-
-

9

-
-

Daily Average 10-m Wind Speed (m s-1)

-
-

3

-
-

Day

-
-

10

-
-

Daily Total Wet Oxidized N (g/ha)

-
-

4

-
-

Daily Total Radiation (MJ m2)

-
-

11

-
-

Daily Total Wet Reduced N (g/ha)

-
-

5

-
-

Daily Maximum 2-m Temperature (C)

-
-

12

-
-

Daily Total Dry Oxidized N (g/ha)

-
-

6

-
-

Daily minimum 2-m temperature (C)

-
-

13

-
-

Daily Total Dry Reduced N (g/ha)

-
-

7

-
-

Daily Total Precipitation (mm)

-
-

14

-
-

Daily Total Wet Organic N (g/ha)

-
- -
- -

5. EPIC Spin-up Run Tools

- -

 

- -

Users must run EPIC spin-up -simulations to generate initial soil files and annual plant N demand data, -which are used in EPIC application-year simulations.  Described in this section -are the five EPIC spin-up run tools: EPIC Site File Generation, Soil -Match for EPIC Spinup, Management File Generation for Spinup, View/Edit -EPIC Inputs, and EPIC Runs for Spinup. Users can use these tools -sequentially to generate files needed for the spin-up and launch the EPIC -spinup run.  Users can obtain detailed information on the EPIC databases from -the documentation for the EPIC modeling system for CMAQ, and on the file -formats and parameter descriptions from the EPIC model documentation at the Texas -A&M AgriLife Research (http://epicapex.tamu.edu/files/ -2013/02/epic0509usermanualupdated.pdf).

- -

5.1 -EPIC Site File Generation

- -

The EPIC Site -File Generation tool uses the FORTRAN programs stored under ${FESTC_HOME}/epic/util/siteCreate.  -This tool generates EPIC site files for the selected grid cells with the -minimum crop acreage limit criterion.  It also creates 21 crop directories with -a crop site list file that is to be used in the other tools.  As simulations -are performed, irrigated and rainfed results are maintained as separate -subdirectories under the overall crop directory.  Figure 11 displays the tool -interface for the test_case scenario with the Minimum Crop Acres set -to 40.  Users should use the same Minimum Crop Acres set in the Crop -Site Info Generation tool.    

- -

- -

Figure -11. The EPIC Site File Generation interface for the test_case -scenario.

- -

After the queue job run has finished, -users should check the log file under their scenario’s scripts directory -to see whether any errors occurred during execution.  The tool generates the -following files and directories:

- -

·         -“scenario name”/share_data/SIT/“GRIDID”0.SIT – EPIC site -files to be used for all EPIC crop modeling.  A description of the file format -can be obtained from the EPIC model documentation.

- -

·         -“scenario name”/share_data/SITELIST.DAT – EPIC site list -file for all crops to be used in EPIC modeling.

- -

·         -“scenario name”/“crop name”/“crop name”-LIST.DAT – EPIC -site list for the particular crop, to be used in the Soil Match for EPIC -Spinup tool discussed in the following section.  If there are no grid cells -that contain that crop, this file will be empty.

- -

5.2 -Soil Match for EPIC Spinup

- -

The Soil Match -for EPIC Spinup tool selects a soil for each crop within a grid cell and -creates the EPIC soil input file.  The EPIC soil datasets are built to -represent the sample point soils selected for USDA NRI data points at the HUC-8 -spatial scale. This tool links built EPIC soil datasets contained in the BaumerSoils -subdirectory to the soil series from the USDA NRI for the crop and grid cell.  It -uses the FORTRAN programs stored under ${FESTC_HOME}/epic/util /soilMatch -with the common data files stored under ${FESTC_HOME}/epic/common_data/ util/soilMatch -and the generated soil list data under each crop directory.  Figure 12 shows -the tool interface used to match soils for all crops (as explained at the -beginning of Section 5) for the current version of FEST-C.  After selecting the -crops, users click the Run button to run the tool in the queue.  After the job -has finished, users should check the queue job and log file in the “scenario -name”/scripts directory, based on the information provided in the Message -Box (shown in Figure 12). 

- -

 

- -

The tool generates many output -files under each crop directory, but most of them are inter­mediate files.  The -final data file created for the EPIC spin-up simulation is “scenario name”/ -“crop name”/SOILLIST.DAT, which contains the matched BaumerSoils -soil file with other parameters for each grid cell under each crop directory.  -This step can take substantial time to complete.

- -

- -

Figure -12. The Soil Match for EPIC Spinup tool interface used for the test_case -scenario.
-Users can select single or multiple crops for the current FEST-C version.

- -

5.3 -Management File Generation for Spinup

- -

The Management -File Generation for Spinup tool interface is used to create the EPIC manage­ment -for each crop within a grid cell. The EPICRUN file that has the linkages for -the grid cell, statistical weather and wind files, soil files, and management -files is also created for the rain-fed and irrigated forms of the crop.  This -tool uses the FORTRAN programs ManGenSU.exe and soildrain.exe stored under ${FESTC_HOME}/epic/util/manageCreate -with the common data files stored under ${FESTC_HOME}/epic/common_data/util/manageCreate -and many other data files generated under each crop directory.  Figure 13 shows -the tool interface used to generate management files for the test_case -scenario. 

- -

- -

Figure -13. The Management File Generation for Spinup tool used for the test_case -scenario.

- -

Users need to make sure that the -following two fields are selected correctly:

- -

·         -Fertilizer Year – select either 2001 or 2006 for choosing the -correct common data sets stored under ${FESTC_HOME}/epic/common_data/util/manageCreate.  - 2011 fertilizer year will be available in future releases.  NLCD/MODIS -2011 is available in this release and can be used (e.g. changes in crop -fraction) with the 2006 fertilizer year but changes to fertilizer types for -2011 will not be realized in these simulations.       

- -

·         -Selected Crops – select one crop or multiple crops.

- -

After the user clicks the Run -button and then “OK”, a queue job to generate management files for each -selected crop is submitted.  After the job has finished, users should check the -queue job and log file in the “scenario name”/scripts directory, based -on the information provided in the Message Box (shown in Figure 13). 

- -

 

- -

There are many output files -generated under each crop, but many of these are used just for verification. -The tool generates the following files to be used for the EPIC spin-up -simulations under the directory “scenario name”/“crop name”/spinup/manage for -each crop:

- -

·         -EPICRUNFILERAIN.DAT – EPIC run file for rain-fed spin-up -simulation of this crop.

- -

·         -EPICRUNFILEIRR.DAT – EPIC run file for irrigated spin-up -simulation of this crop.

- -

·         -GRIDS_OPC.DAT – the list of management file names to be used in -EPIC modeling.

- -

·         -OPC/“GRIDID”0“BELD3 Crop Number”.OPC – grid cell EPIC -management files under the OPC directory.  Table 1 in Section 4.1 lists -the crop numbers in the BELD data and how they are mapped, Table 2.    

- -

·         -tileDrain/SOILLIST.DAT – soil list file which contains -tile drain information for EPIC simulations and is used when “tileDrain” is -selected when running EPIC spinup simulations.

- -

5.4 -View/Edit EPIC Inputs

- -

The View/Edit -EPIC Inputs interface allows users to view or edit five main EPIC -simulation files (listed in Figure 14).  Users generally do not need to edit these -files, but viewing them can be helpful for debugging. The user has to select a -crop first and then select the EPIC simulation type.  The simulation type can -be SPINUP if the Management File Generation for Spinup tool (previous -section) has been executed for the selected crop; or the user can select the -simulation type APP after the Management File Generation for Application -tool (discussed in Section 6.1) has been executed for the crop. Figure 14 shows -the View/Edit EPIC Inputs tool interface for the test_case -scenario. 

- -

- -

Figure -14. The View/Edit EPIC Inputs tool for the test_case -scenario.

- -

5.5 -EPIC Runs for Spinup

- -

The EPIC Runs -for Spinup tool interface is used to run the EPIC model for spin-up (EPICsu.exe -program), which is stored under the directory ${FESTC_HOME}/epic/model/current. -The tool uses input files stored primarily in the following directories:

- -

·         -${FESTC_HOME}/epic/common_data/EPIC_model/spinup – contains -the common model input files.

- -

·         -scenarios/“scenario name”/share_data – contains site files -and list file.

- -

·         -${FESTC_HOME}/epic/common_data/statWeath – contains -observed climate station statistical data (see http://epicapex.tamu.edu/epic/)

- -

·         -scenarios/“scenario name”/“crop name”/spinup/manage – contains -the run files, management files, and management list file.

- -

·         -scenarios/“scenario name”/ “crop name” – contains the soil -list file.

- -

Spin-up -simulations generate EPIC soil files reflecting the user-defined management to be -used as initial conditions in the application run for the simulation year.  Soil -erosion (wind and water) is “turned off” during the spin-up period to avoid -loss of productive soil layers.  These losses are “turned on” during -application year simulation.  As discussed in Section 2, the spin-up simulation -is run for 25 years starting from 1978 for all crops except potatoes; for potatoes -it is run for 100 years starting from 1903.  These dates are strictly used for -“bookkeeping” and are not used in subsequent steps.  Statistically generated -weather conditions for Cooperative Observer Weather Stations during the period -1980-2010 drive these simulations.  Future releases are expected to support -input of alternative sources of long-term weather information (i.e., 25 years -or more).  Figure 15 displays the tool interface used for the test_case -scenario.  Users can select one or more crops for the simulation.  After -clicking the Run button, a script file is generated to run the rain-fed and -irrigated EPIC spin-up simula­tions for each crop.  The user submits the script -file to the queue by clicking OK.  After the job has finished, users should -check the queue job and log file in the “scenario name”/scripts directory, -based on the information provided in the Message Box (shown in Figure 15). 

- -

- -

Figure 15. The EPIC -Runs for Spinup tool used for the test_case scenario.

- -

Users need to make sure that the -following three fields are selected correctly:

- -

·         -CO2 Level (ppm) - input the correct CO2 -level for the simulation (e.g. 380).  The input level overwrites the CO2 -level defined in EPICCONT.DAT and site file.

- -

·         -Daily Average N Deposition – select N input to be used in -the simulation.  Users can select using 1) the values defined in EPIC input files, -2) daily average N input from 5-year CMAQ simulations from 2002 to 2006, or 3) daily -average N input from 5-year CMAQ simulations from 2006 to 2010.  The 5-year -CMAQ N daily input files are stored under ${FESTC_HOME}/epic/common_data/EPIC_model.  -Future releases will include daily average N input from 5-year CMAQ simulations -from 2011 to 2015.

- -

·         -Run TileDrain – select whether tile drain is applied for -saturated soils.  If YES is selected, SOILLIST file under scenarios/“scenario -name”/“crop name”/spinup/manage/tileDrain will be used.  The tile drain -process is applied for all crops except hay (1, 2), alfalfa (3, 4), Other_Grass -(5, 6) and rice (23, 24).   

- -

The tool generates many directories -and files for each crop.  The original EPIC output files are stored under the -two following subdirectories in the “scenario name”/“crop name”/spinup directory:

- -

·         -rainf – contains output from EPIC rain-fed spin-up -simulations for this crop.

- -

·         -irr – contains output from EPIC irrigated spin-up -simulations for this crop. 

- -

In both cases, -soil files to be used in the EPIC application simulation are:

- -

-        -SOL/“GRIDID”0“BELD3 Crop Number”.SOL 

- -

The output data created for CMAQ -modeling are used primarily for QA purposes, and are stored under the following -two directories in the “scenario name”/output4CMAQ/spinup directory:

- -

·         -5years – contains average EPIC output data from the last -five years of the spin-up simulations for the crops. 

- -

·         -daily – stores daily EPIC output data from EPIC spin-up -runs for the crops simulated. 

- -

6. EPIC Application Run Tools

- -

After users -complete the EPIC simulations for spin-up, they can proceed to the EPIC -application run tools for the simulation (or application) year.  The spin-up -simulations need to be run only once for a given domain and grid resolution—in other -words, the initial conditions can be re-used for multiple application years. -The first step in running an EPIC application is to generate management files -for the application year (as described in Section 6.1).  The application -management program needs to be run only once for a given domain and grid -resolution; it is not year-specific.  The user can then run the EPIC model for -the application year (as described in Section 6.2) if the daily weather and N -deposition files for the scenario have already been generated using the tool described -in Section 4.3. 

- -

6.1 -Management File Generation for Application

- -

The Management -File Generation for Application tool interface is used to create (1) the -EPIC management files for each crop to be used in the EPIC application-year -modeling; and (2) the EPICRUN file for the rain-fed and irrigated simulations, -which contains the linkages for the statistical weather and wind files, the -soil files, and the management files for EPIC grid cells.  The tool uses the -FORTRAN programs ManGenFERT.exe and soildrain.exe stored under the ${FESTC_HOME}/ -epic/util/manageCreate directory with the common data files stored under ${FESTC_HOME} -/epic/common_data/util/manageCreate and many other data files generated -under each crop directory.  Figure 16 shows the tool interface used to generate -management files for the test_case scenario.  Users must make sure that -the following two entries are selected correctly:

- -

·         -Fertilizer Year – select 2001 or 2006.  The common -management and fertilizer data sets created under the ${FESTC_HOME}/epic/common_data/util/manageCreate -will be used accordingly.  This management tool uses the created -fertilizer data types for the 10 crop production regions.  Fertilizer for 2011 -will be available in a future release. 

- -

·         -Selected Crops – select one or more crops.

- -

 

- -

- -

Figure 16. The Management -File Generation for Application tool interface used
-for the test_case scenario.

- -

After clicking the Run button, a -script file is generated to compute the management files for the selected -crops.  The user submits the script file to the queue by clicking OK.  After -the job has finished, users should check the queue job and log file in the “scenario -name”/scripts directory, based on the information provided in the Message -Box (shown in Figure 16). 

- -

 

- -

The tool will generate many output -files under each crop (many of these are used just for verification). The tool -generates the following files under the “scenario name”/“crop name”/app/manage -directory:

- -

·         -EPICRUNFILERAINDW.DAT – EPIC run file for rain-fed application -simulation.

- -

·         -EPICRUNFILEIRRDW.DAT – EPIC run file for irrigated application -simulation.

- -

·         -GRIDS_OPC.DAT – the list of management file names to be used in -EPIC modeling.

- -

·         -OPC/“GRIDID”0“BELD3 Crop Number”.OPC – grid cell EPIC -management files under the OPC directory.  Table 1 in Section 4.1 lists -the crop numbers in the BELD data.

- -

·         -tileDrain/SOILLIST.DAT – soil list file which contains -tile drain information for EPIC simulations and is used when “tileDrain” is -selected when running EPIC application simulations. 

- -

6.2 -EPIC Runs for Application

- -

The EPIC Runs -for Application tool interface is used to run the EPIC model for the -simulation year (EPICapp.exe program), which is stored under the directory ${FESTC_HOME}/epic/ -model/current.  Users must already have generated the site daily weather -and N deposition files using the WRF/CMAQ-to-EPIC tool interface (see -Section 4.3).  N deposition input can be selected from the four available -options – CMAQ, EPIC parameter input file, 2002-2006 5-year CMAQ average, -and 2006-2010 5-year CMAQ average. The tool uses input files stored primarily -in the following directories:

- -

·         -${FESTC_HOME}/epic/common_data/EPIC_model/app – contains -the common model input files.

- -

·         -scenarios/“scenario name”/share_data – contains the EPICCONT.DAT -file, site files, site list file, daily weather and N deposition files, and -weather list file. 

- -

·         - ${FESTC_HOME}/epic/common_data/statWeath – contains observed -climate station statistical data.

- -

·         -scenarios/“scenario name”/ “crop name” /app/manage – contains -the run files, management files, and management list file.

- -

·         -scenarios/“scenario name”/ “crop name”/spinup/rainf/SOL – contains -the soil files to be used in the rain-fed simulations.

- -

·         -scenarios/“scenario name”/ “crop name”/spinup/irr/SOL – contains -the soil files to be used in the irrigated simulations.

- -

Figure 17 shows -the tool interface used for the test_case scenario.  The Simulation Year -is defined when the user creates the scenario.  Users can select one or -multiple crops for the simulation.  After clicking the Run button, a script -file is generated to run the rain-fed and irrigated EPIC application -simulations for each crop.  The EPIC application simulations will run for a two-year -period (the previous year and the simulation year) using the same daily weather -and N deposition files for the simulation year; the two-year period is needed to -simulate a full growing season for fall-sown crops. The user submits the script -file to the queue by clicking OK.  After the job has finished, users should -check the queue job and log file in the “scenario name”/scripts directory, -based on the information provided in the Message Box (shown in Figure 17). 

- -

Users need to -make sure that the following three fields are selected correctly:

- -

·         -CO2 Level (ppm) - input the correct CO2 -level for the simulation (e.g. 380).  The input level overwrites the CO2 -level defined in EPICCONT.DAT and site file.

- -

·         -Daily Average N Deposition – select N input to be used in -the simulation.  Users can select using 1) the CMAQ N values in daily weather -files, 2) values defined in EPIC input files, 3) daily average N input from the -5-year CMAQ simulations from 2002 to 2006, or 4) daily average N input from the -5-year CMAQ simulations from 2006 to 2010.  The 5-year CMAQ N daily input files -are stored under ${FESTC_HOME}/epic/common_data/EPIC_model.  Future -releases will include daily average N input from 5-year CMAQ simulations from -2011 to 2015.

- -

·         -Run TileDrain – select whether tile drain is applied for -saturated soils.  If YES is selected, SOILLIST file under scenarios/“scenario -name”/“crop name”/app/manage/tileDrain will be used.  The tile drain -process is applied for all crops except hay (1, 2), alfalfa (3, 4), Other_Grass -(5, 6) and rice (23, 24).   

- -

 

- -

- -

Figure 17. The EPIC -Runs for Application tool interface used for the test_case scenario.

- -

The tool generates many directories -and files for each crop.  The original EPIC output files are stored under the -following two subdirectories in the “scenario name”/“crop name”/app directory:

- -

·         -rainf – contains output from EPIC rain-fed application -simulations for this crop. 

- -

·         -irr – contains output from EPIC irrigated application -simulations for this crop. 

- -

The output data created for CMAQ -modeling are stored under the following two subdirectories in the “scenario -name”/output4CMAQ/app directory:

- -

·         -year – contains average EPIC output data for the -simulation year (one year) run for the crops simulated.  These data are used -primarily for QA purposes.

- -

·         -daily – stores daily EPIC output data from EPIC -application runs for the crops simulated.  These data are used to extract the -input for CMAQ bidirectional NH3 modeling and SWAT simulations.

- -

7. Output Processing and Visualizing Tools

- -

EPIC is a field-based -model that generates output in formatted text files.  In the domain-based EPIC -modeling within FEST-C, the crops in each grid cell are modeled individually.  -Thus, there are many text output files generated for each crop in each grid -cell selected for EPIC modeling.  In this section we first describe the EPIC -Yearly Extraction tool and the EPIC-to-CMAQ tool. Developed in the -SA Raster Tools system, these two tools extract yearly or daily EPIC output -variables into NetCDF-format files for QA purposes and for CMAQ modeling.  We -then discuss the EPIC to SWAT tool which prepares SWAT input files from -EPIC output and WRF/CMAQ weather and N deposition NetCDF file using many R -codes.  The Visualization tool interface, which allows users to prepare -spatial views of the EPIC output variables in the created NetCDF files over -their modeling scenario domain, is presented last in this section. 

- -

7.1 -EPIC Yearly Extraction

- -

The EPIC -Yearly Extraction tool is used to extract 48 crop-specific variables and 39 -crop-area-weighted variables into two NetCDF files from the yearly average EPIC -output files for all simulated crops within the grid cells that were selected.  -The output from this tool is used primarily for QA purposes, to make sure that the -EPIC simulation results appear to be spatially reasonable over the domain -area.  Figure 18 shows the tool interface used for the test_case -scenario.  The only item users need to select is an “Output Type”:

- -

·         -EPIC SPINUP – select this to extract yearly average -variables from the EPIC spin-up simulations. Yearly average variables from the -last five years of the simulations are from the output stored under the “scenario -name”/output4CMAQ/spinup/5years directory. 

- -

·         -EPIC APP – select this to extract yearly average variables -from the EPIC simulations for the application year.  The yearly average -variables are from the output stored under the “scenario -name”/output4CMAQ/app/year directory.   

- -

 

- -

- -

Figure 18.  The EPIC -Yearly Extraction tool interface used for the test_case scenario.

- -

Table 4 lists all variables that -are in the two EPIC output files created by the tool:  epic2cmaq_year.nc -(crop-specific output) and epic2cmaq_year_total.nc (crop-weighted output). -These files are stored in one of the following two directories:

- -

·         -scenarios/“scenario name”/output4CMAQ/spinup/toCMAQ – if -the EPIC SPINUP output type is selected.

- -

·         -scenarios/“scenario name”/output4CMAQ/app/toCMAQ – if the -EPIC APP output type is selected.

- -

 

- -

Users should check the log file -under their scenario’s scripts directory to see whether any errors -occurred when the tool was run.  If the user is visualizing the data using the -VERDI tool for visualization, there is no time dimension.  Data layers are assigned -to individual crops (see Table 1 in Section 4.1 for the BELD crop numbers). 

- -

Table 4. EPIC yearly extraction output variables.

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

epic2cmaq_year.nc - crop specific output

-
-

 

-
-

 

-
-

 

-
-

Index

-
-

Name

-
-

Variable

-
-

Index

-
-

Name

-
-

Variable

-
-

1

-
-

GMN

-
-

N Mineralized (kg/ha)

-
-

25

-
-

FTP

-
-

P Applied (kg/ha)

-
-

2

-
-

NMN

-
-

Humus Mineralization (kg/ha)

-
-

26

-
-

IRGA*

-
-

Irrigation Volume Applied (mm)

-
-

3

-
-

NFIX

-
-

N Fixation (kg/ha)

-
-

27

-
-

WS

-
-

Water Stress Days (days)

-
-

4

-
-

NITR

-
-

N - Nitrified NH3 (kg/ha)

-
-

28

-
-

NS

-
-

N Stress Days (days)

-
-

5

-
-

AVOL

-
-

N - Volatilization (kg/ha)

-
-

29

-
-

IPLD

-
-

Planting Date (Julian Date)

-
-

6

-
-

DN

-
-

N-NO3 Denitrification (kg/ha)

-
-

30

-
-

IGMD

-
-

Germination Date (Julian Date)

-
-

7

-
-

YON

-
-

N Loss with Sediment (kg/ha)

-
-

31

-
-

IHVD

-
-

Harvest Date (Julian Date)

-
-

8

-
-

QNO3

-
-

N Loss in Surface Runoff - (kg/ha)

-
-

32

-
-

YP

-
-

P Loss with Sediment (kg/ha)

-
-

9

-
-

SSFN

-
-

N in Subsurface Flow (kg/ha)

-
-

33

-
-

QAP

-
-

Labile P Loss in Runoff (kg/ha)

-
-

10

-
-

PRKN

-
-

N Loss in Percolate (kg/ha)

-
-

34

-
-

YW

-
-

Wind Erosion (ton/ha)

-
-

11

-
-

FNO

-
-

N - Organic Fertilizer (kg/ha)

-
-

35

-
-

Q*

-
-

Runoff (mm)

-
-

12

-
-

FNO3

-
-

N - Nitrate Fertilize (kg/ha)

-
-

36

-
-

SSF

-
-

Subsurface flow (mm)

-
-

13

-
-

FNH3

-
-

N - Ammonia Fertilize (kg/ha)

-
-

37

-
-

PRK

-
-

Percolation (mm)

-
-

14

-
-

OCPD

-
-

Organic Carbon in Plow Layer - (mt/ha)

-
-

38

-
-

PRCP

-
-

Rainfall (mm)

-
-

15

-
-

TOC

-
-

Organic Carbon in Soil Profile - (mt/ha)

-
-

39

-
-

PET

-
-

Potential Evapotranspiration - (mm)

-
-

16

-
-

TNO3

-
-

Total NO3 in Soil Profile - (kg/ha)

-
-

40

-
-

ET

-
-

Evapotranspiration (mm)

-
-

      17

-
-

DN2

-
-

N-N2O from NO3 Denitrification - (kg/ha)

-
-

41

-
-

QDRN

-
-

Drain Tile Flow (mm)

-
-

18

-
-

YLDG

-
-

Grain Yield (t/ha)

-
-

42

-
-

MUSL

-
-

Water erosion (ton/ha)

-
-

19

-
-

T_YLDG

-
-

T - Grain Yield (1000ton)

-
-

43

-
-

DRNN

-
-

Nitrogen in drain tile flow (kg/ha)

-
-

20

-
-

YLDF

-
-

Forage Yield (t/ha)

-
-

44

-
-

DRNP

-
-

P in Drain Tile Flow (kg/ha)

-
-

21

-
-

T_YLDF

-
-

T - Forage Yield (1000ton)

-
-

45

-
-

PRKP

-
-

P in Percolation (kg/ha)

-
-

22

-
-

YLN

-
-

N Used by Crop (kg/ha)

-
-

46

-
-

FPO

-
-

Organic P Fertilizer (kg/ha)

-
-

23

-
-

YLP

-
-

P Used by Crop (kg/ha)

-
-

47

-
-

FPL

-
-

Labile P Fertilizer (kg/ha)

-
-

24

-
-

FTN

-
-

N Applied (kg/ha)

-
-

48

-
-

MNP

-
-

P Mineralized (kg/ha)

-
-

 

-
-

 

-
-

 

-
-

 

-
-

 

-
-

 

-
-

epic2cmaq_year_total.nc - crop weighted - output

-
-

 

-
-

 

-
-

 

-
-

Index

-
-

Name

-
-

Variable

-
-

Index

-
-

Name

-
-

Variable

-
-

1

-
-

T_GMN

-
-

N Mineralized (mt - metric ton)

-
-

21

-
-

T_FTP

-
-

P Applied (mt)

-
-

2

-
-

T_NMN

-
-

Humus Mineralization (mt)

-
-

22

-
-

T_IRGA*

-
-

Irrigation Volume Applied (mm)

-
-

3

-
-

T_NFIX

-
-

N Fixation (mt)

-
-

23

-
-

T_YP

-
-

T - P Loss with Sediment (mt)

-
-

4

-
-

T_NITR

-
-

N - Nitrified NH3 (mt)

-
-

24

-
-

T_QAP

-
-

T - Labile P Loss in Runoff - (mt)

-
-

5

-
-

T_AVOL

-
-

N - Volatilization (mt)

-
-

25

-
-

T_YW

-
-

T - Wind Erosion (1000ton)

-
-

6

-
-

T_DN

-
-

N-NO3 Denitrification (mt)

-
-

26

-
-

T_Q*

-
-

T - Runoff (mm)

-
-

7

-
-

T_YON

-
-

N Loss with Sediment (mt)

-
-

27

-
-

T_SSF

-
-

T - Subsurface flow (mm)

-
-

8

-
-

T_QNO3

-
-

N Loss in Surface Runoff (mt)

-
-

28

-
-

T_PRK

-
-

T - Percolation (mm)

-
-

9

-
-

T_SSFN

-
-

N in Subsurface Flow (mt)

-
-

29

-
-

T_PRCP

-
-

T - Rainfall (mm)

-
-

10

-
-

T_PRKN

-
-

N Loss in Percolate (mt)

-
-

30

-
-

T_PET

-
-

T - Potential - Evapotranspiration (mm)

-
-

11

-
-

T_FNO

-
-

N - Organic Fertilizer (mt)

-
-

31

-
-

T_ET

-
-

T - Evapotranspiration (mm)

-
-

12

-
-

T_FNO3

-
-

N - Nitrate Fertilizer (mt)

-
-

32

-
-

T_QDRN

-
-

T - Drain Tile Flow (mm)

-
-

13

-
-

T_FNH3

-
-

N - Ammonia Fertilizer (mt)

-
-

33

-
-

T_MUSL

-
-

T - Water erosion (ton/ha)

-
-

14

-
-

T_OCPD

-
-

Organic Carbon in Plow Layer - (1000mt)

-
-

34

-
-

T_DRNN

-
-

T – N in drain tile flow - (kg/ha)

-
-

15

-
-

T_TOC

-
-

Organic Carbon in Soil Profile - (1000mt)

-
-

35

-
-

T_DRNP

-
-

T - P in Drain Tile Flow - (kg/ha)

-
-

16

-
-

T_TNO3

-
-

Total NO3 in Soil Profile (mt)

-
-

36

-
-

T_PRKP

-
-

T - P in Percolation (kg/ha)

-
-

17

-
-

T_DN2

-
-

N-N2O from NO3 Denitrification - (mt)

-
-

37

-
-

T_FPO

-
-

T - Organic P Fertilizer - (kg/ha)

-
-

18

-
-

T_YLN

-
-

N Used by Crop (mt)

-
-

38

-
-

T_FPL

-
-

T - Labile P Fertilizer (kg/ha)

-
-

19

-
-

T_YLP

-
-

P Used by Crop (mt)

-
-

39

-
-

T_MNP

-
-

T - P Mineralized (kg/ha)

-
-

20

-
-

T_FTN

-
-

N Applied (mt)

-
-

 

-
-

 

-
-

 

-
- -
- -

*Water -on agricultural lands.

- -

7.2 -EPIC to CMAQ

- -

The EPIC to CMAQ -tool is used to extract 13 variables from EPIC soil output files and 41 -variables from EPIC daily output files into NetCDF files for all simulated -crops within the grid cells that were selected.  The output from this tool is -used as input to CMAQ bidirectional NH3 modeling over the domain -area.  Figure 19 shows the tool interface used for the test_case -scenario. 

- -

The user needs to -input the following two items:

- -

·         -Output File Prefix – this is used as the file prefix for -all of the NetCDF output file names

- -

·         -Output Type – select “EPIC SPINUP” to extract -yearly average variables from the EPIC spin-up simulations under the “scenario -name”/output4CMAQ/spinup/5years directory and “EPIC APP” to extract -yearly average variables from the EPIC simulations for the application year -under the “scenario name”/output4CMAQ/app/year directory.   

- -

The following output files produced -by the tool are stored under the scenarios/“scenario -name”/output4CMAQ/app/toCMAQ directory:

- -

·         -Output File Prefix”_soil.nc – soil output file that -contains 13 soil variables extracted from the EPIC soil output files (“scenario -name”/output4CMAQ /app/daily/“BELD4 Crop Number”.NCS); these variables are -listed in Table 5.  L1 and L2 are for the soil depth from 0 to 1 cm and from 1 cm -to 10 cm, respectively. 

- -

·         -Output File Prefix”_timeYYYYMMDD.nc – daily NetCDF files -for the simulation year.  A daily NetCDF file contains 41 variables extracted -from the EPIC daily output files (e.g. “scenario name”/output4CMAQ -/app/daily/“BELD4 Crop Number”.NCD”); these variables are listed in Table 6.  -L1, L2, and T1 are for the soil depth from 0 to 1 cm, from 1 cm to 10 cm, -and from 0 cm to the full Baumer soil profile depth, which can be more than -1 m.   

- -

 

- -

- -

Figure -19. The EPIC to CMAQ tool interface used for the test_case -scenario.

- -

 

- -

Table 5. EPIC to CMAQ soil output variables

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Index

-
-

Name

-
-

Soil - Variable

-
-

Index

-
-

Name

-
-

Soil - Variable

-
-

1

-
-

L1_SoilNum

-
-

Soil Number (none)

-
-

8

-
-

L2_Bulk_D

-
-

Layer2 Bulk Density (t/m**3)

-
-

2

-
-

L1_Bulk_D

-
-

Layer1 Bulk Density (t/m**3)

-
-

9

-
-

L2_Wilt_P

-
-

Layer2 Wilting Point (m/m)

-
-

3

-
-

L1_Wilt_P

-
-

Layer1 Wilting Point(m/m)

-
-

10

-
-

 L2_Field_C

-
-

Layer2 Field Capacity (m/m)

-
-

4

-
-

L1_Field_C

-
-

Layer1 Field Capacity (m/m)

-
-

11

-
-

L2_Porosity

-
-

Layer2 Porosity (%)

-
-

5

-
-

L1_Porosity

-
-

Layer1 Porosity (%)

-
-

12

-
-

L2_PH

-
-

Layer2 PH (none)

-
-

6

-
-

L1_PH

-
-

Layer1 PH (none)

-
-

13

-
-

L2_Cation

-
-

Layer2 Cation Ex (cmol/kg)

-
-

7

-
-

L1_Cation

-
-

Layer1 Cation Ex (cmol/kg)

-
-

 

-
-

 

-
-

 

-
- -
- -

 

- -

 

- -

Table 6. EPIC to CMAQ daily output variables

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Index

-
-

Name

-
-

Variable

-
-

Index

-
-

Name

-
-

Variable

-
-

1

-
-

DN

-
-

N-NO3 Denitrification (kg/ha)

-
-

22

-
-

L2_NH3

-
-

Layer2 N - Ammonia (kg/ha)

-
-

2

-
-

DN2

-
-

N-N2O from NO3 Denitrification - (kg/ha)

-
-

23

-
-

L2_ON

-
-

Layer2 Organic N (kg/ha)

-
-

3

-
-

HMN

-
-

OC Change by Soil Respiration - (kg/ha)

-
-

24

-
-

L2_C

-
-

Layer2 Carbon (kg/ha)

-
-

4

-
-

NFIX

-
-

N Fixation (kg/ha)

-
-

25

-
-

L2_NITR

-
-

Layer2 N - Nitrified NH3 - (kg/ha)

-
-

5

-
-

GMN

-
-

N Mineralized (kg/ha)

-
-

26

-
-

T1_DEP

-
-

Layert Depth (m)

-
-

6

-
-

YW

-
-

Wind Erosion (ton/ha)

-
-

27

-
-

T1_BD

-
-

Layert Bulk Density (t/m**3)

-
-

7

-
-

FPO

-
-

Organic P Fertilizer (kg/ha)

-
-

28

-
-

T1_NO3

-
-

Layert N - Nitrate (kg/ha)

-
-

8

-
-

FPL

-
-

Labile P Fertilizer (kg/ha)

-
-

29

-
-

T1_NH3

-
-

Layert N - Ammonia (kg/ha)

-
-

9

-
-

MNP

-
-

P Mineralized (kg/ha)

-
-

30

-
-

T1_ON

-
-

Layert Organic N (kg/ha)

-
-

10

-
-

L1_DEP

-
-

Layer1 Depth (m)

-
-

31

-
-

T1_C

-
-

Layert Carbon (kg/ha)

-
-

11

-
-

L1_BD

-
-

Layer1 Bulk Density (t/m**3)

-
-

32

-
-

T1_NITR

-
-

Layert N - Nitrified NH3 - (kg/ha)

-
-

12

-
-

L1_SW

-
-

Layer 1 Soil Moisture (mm)

-
-

33

-
-

L1_ANO3

-
-

Layer1 N-NO3 AppRate (kg/ha)

-
-

13

-
-

L1_NO3

-
-

Layer1 N - Nitrate (kg/ha)

-
-

34

-
-

L1_ANH3

-
-

Layer1 N-NH3 AppRate (kg/ha)

-
-

14

-
-

L1_NH3

-
-

Layer1 N - Ammonia (kg/ha)

-
-

35

-
-

L1_AON

-
-

Layer1 ON AppRate (kg/ha)

-
-

15

-
-

 L1_ON

-
-

Layer1 Organic N (kg/ha)

-
-

36

-
-

L2_ANO3

-
-

Layer2 N-NO3 AppRate (kg/ha)

-
-

16

-
-

L1_C

-
-

Layer1 Carbon (kg/ha)

-
-

37

-
-

L2_ANH3

-
-

Layer2 N-NH3 AppRate (kg/ha)

-
-

17

-
-

L1_NITR

-
-

Layer1 N - Nitrified NH3 - (kg/ha)

-
-

38

-
-

L2_AON

-
-

Layer2 ON AppRate (kg/ha)

-
-

18

-
-

L2_DEP

-
-

Layer2 Depth (m)

-
-

39

-
-

LAI

-
-

Leaf Area Index (none)

-
-

19

-
-

L2_BD

-
-

Layer2 Bulk Density (t/m**3)

-
-

40

-
-

CPHT

-
-

Crop Height (m)

-
-

20

-
-

L2_SW

-
-

Layer 2 Soil Moisture (mm)

-
-

41

-
-

FBARE

-
-

Bare Land Fraction for Wind - Erosion (Fraction)

-
-

21

-
-

L2_NO3

-
-

Layer2 N - Nitrate (kg/ha)

-
-

 

-
-

 

-
-

 

-
-

Note: - EPIC is a daily time step model while the CMAQ bidirectional NH3 - flux model is at a time scale which could be less than 10 minutes. 

-
- -
- -

 

- -

When the user clicks the Run -button, a script file is generated under the scenario’s scripts directory.  -The script file is submitted to the queue for execution after the user clicks -OK.  A CMAQ-ready file is generated for each day and is viewable in VERDI.  After -the queue job has completed, users should check the log file under the scripts -directory to see whether any errors occurred during execution.

- -

7.3 -EPIC to SWAT

- -

 

- -

The EPIC to SWAT tool is used -to extract EPIC output and WRF/CMAQ weather and N deposition data for SWAT -simulations in 8-digit HUC watersheds defined by users.  “EPIC”, “NDEP”, and “DailyWETH” -are tools which users can click in any order to aggregate EPIC daily output and -N deposition and weather data in CMAQ grid format into the different areas listed.  -After aggregated EPIC, N deposition, and weather files are created, users can -click “SWAT INPUTS” to generate SWAT-ready input files.  The output from -“SWAT INPUTS” can be used by SWAT modelers to replace default or “traditional” -SWAT weather, atmospheric deposition and agricultural land nutrient and runoff input.  - Figure 20 shows the tool interface which is used for the test_case -scenario.  Users need to make sure that the following fields are filled and selected -correctly:

- -

·         -HUC8 Delivery Ratio File – EPIC to SWAT integration file.  -This text file contains SWAT 8-digit HUC watershed information with average -delivery ratios from EPIC edge-of-field output to SWAT watershed output.  Users -can view the delivery ratio file – “test_case/share_data/subbasins-mapping_test_case.csv” -included for the test_case scenario for items and format required.

- -

·         -Daily Average N Deposition – select the source of N -deposition for SWAT extraction.  Users can select CMAQ application year N -deposition or one of the 5-year average CMAQ N deposition. 

- -

·         -Area Selection – select area for generating SWAT-ready -input files by the “SWAT INPUTS” button.  The current system only works for -8-digit HUC SWAT input file generation regardless of which area is selected.  -The “EPIC”, “NDEP”, and DailyWETH” extraction buttons will generate aggregated -data for all areas listed.

- -

 

- -

- -

Figure 20. The -EPIC to SWAT interface.

- -

The button tools with descriptions -in this subinterface are:

- -

·         -EPIC – aggregate the daily variables -required by SWAT (Table 7) from EPIC application run output to all areas listed -on the interface (Domain, State, County, HUC8, HUC6, and HUC2).  This tool uses -the R program epic2swat_extract_dailyEPIC.R stored under ${FESTC_HOME}/epic/util/swat. - After clicking the EPIC button, a script file is generated to run the program -using all information defined by environment variables.  The user submits the -script file to the queue by clicking OK.  After the job is finished, users -should check the queue job and log file in the “scenario name”/scripts -directory, based on the information provided in the Message Box (shown in -Figure 20).  The output files from the tool are stored under the sub-directories -with corresponding area names in the “scenario name”/output4SWAT/dailyEPIC directory.   -  

- -
-
- -

 

- -

Table 7. Conversion of EPIC -daily output to SWAT point source input

- -

 

- -

- -

Notes: Area is for the crop area in a specific -grid.  is the summation for all grids -in a region (e.g. HUC8).

- -

 

- -

 

- -

·         -NDEP - aggregate daily N deposition variables required by -SWAT (Table 8) from daily deposition NetCDF file generated from CMAQ to all -areas listed on the interface (Domain, State, County, HUC8, HUC6, and HUC2).  This -tool uses the R program epic2swat_extract_daily_ndepCMAQ.R stored under ${FESTC_HOME}/epic/util/swat.  -After clicking the NDEP button, a script file is generated to run the program -using all information defined by environment variables.  The user submits the -script file to the queue by clicking OK.  After the job is finished, users -should check the queue job and log file in the “scenario name”/scripts -directory, based on the information provided in the Message Box (shown in -Figure 20).  The output files from the tool are stored under the sub-directories -with corresponding area names in the “scenario name”/output4SWAT/NDEP directory.   -  

- -

 

- -
-
- -

 

- -

Table 8. CMAQ N Deposition -to SWAT

- -

 

- -

- -

Note: N is the total -number of grid cells in a specific region (e.g. HUC8).

- -

 

- -

·         -DailyWETH - aggregate -daily weather variables required by SWAT (Table 9) from daily weather NetCDF -file generated from WRF to all areas listed on the interface (Domain, State, -County, HUC8, HUC6, and HUC2).  This tool uses the R program epic2swat_extract_daily_metCMAQ.R -stored under ${FESTC_HOME}/epic/util/swat.  After clicking the DailyWETH -button, a script file is generated to run the program using all information -defined by environment variables.  The user submits the script file to the -queue by clicking OK.  After the job is finished, users should check the queue -job and log file in the “scenario name”/scripts directory, based on the -information provided in the Message Box (shown in Figure 20).  The output files -from the tool are stored under the sub-directories with corresponding area -names in the “scenario name”/output4SWAT/dailyWETH directory.     

- -

 

- -
-
- -

 

- -

Table 9. WRF daily weather to -SWAT  

- -

 

- -

- -

Note: N is the total -number of grid cells in a specific region (e.g. HUC8).

- -

 

- -

 

- -

·         -SWAT INPUTS – generate SWAT-ready input files from aggregated -daily EPIC, weather, and N deposition files by the previous three button tools -for the watersheds specified in the “HUC8 Delivery Ratio File” field.  This -tool calls the R program extract_swatInputs.R stored under ${FESTC_HOME}/epic/util/swat.  -After clicking the “SWAT INPUTS” button, a script file is generated to run the program -using all information defined by environment variables.  The user submits the -script file to the queue by clicking OK.  After the job is finished, users -should check the queue job and log file in the “scenario name”/scripts -directory, based on the information provided in the Message Box (shown in -Figure 20).  The output files from the tool are stored under the -sub-directories for EPIC, weather, and N deposition individually in the “scenario -name”/output4SWAT/swat_inputs directory.

- -

7.4 Visualization

- -

The Visualization -tool interface is used to invoke the VERDI interface to view a selected NetCDF -data set.  Figure 21 shows the appearance of the tool interface before an input -file has been selected.  Users can select the data type on the left side of the -interface window and then by browse through the file systems to select a NetCDF -file created or used within the FEST-C system (e.g., an EPIC output NetCDF file -created by the previous two tools, a BELD4 data set, MCIP and CMAQ data sets, a -daily weather and N deposition NetCDF output file).  Clicking the Display button -invokes the VERDI interface to visualize the selected NetCDF file.  Note: -For this to work properly, the user has to have set the VERDI system in the -FEST-C configuration file config.properties (see Section 1.3).  -Information on how to use the VERDI system can be obtained from the CMAS VERDI -site: http://www.cmascenter.org/verdi/.  -

- -

- -

Figure 21. The -Visualization tool interface.

- -

8. Future Work

- -

In this release, -2011 NLCD/MODIS data is available to produce crop fractions for Canada and the -US.  To accompany this data, a future release will include an updated -fertilizer type scenario for 2011.  In addition, we will continue to improve -the crop fraction coverage with the upcoming NLCD 2016 release using the USDA -2017 census data and corresponding crop census data for Canada and Mexico.  We -are continuing our efforts to improve the C-N-P budgets within this systems for -different crops.  We are also exploring the possibility of moving to computing -crop land use data directly from USDA National Agricultural Statistics Service (NASS) -Cropland Data Layer (CDL) data.  This would provide higher-resolution crop -spatial information, however, CDL data do not include some information that is -critical for FEST-C EPIC (such as differentiation between irrigated and -rain-fed crops).  Thus, further exploration on using this data set in -combination with other irrigation data is needed.

- -

 

- -
- - - - + + + + + +NOTE: Review and QA of all work products is included with the hours for +those work products + + + + + + +
+ +

  +

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

+ + + + + + + + + +
+ + 

+ +

 

+ +
+ +

User’s Guide for the Fertilizer +Emission Scenario Tool for CMAQ (FEST-C) Version 1.4

+ +

 

+ +

 

+ +

 

+ +

 

+ +

Limei Ran1, Ellen Cooter1, +Dongmei Yang2, Verel Benson3, Yongping Yuan4, Adel +Hanna2, Val Garcia1

+ +

 

+ +

 

+ +

1Atmospheric Model Application and +Analysis Branch, Computational Exposure Division, USEPA/ORD/NERL, Research +Triangle Park, NC 27711

+ +

 

+ +

2Institute for the Environment, University +of North Carolina at Chapel Hill, 100 Europa Dr., Chapel Hill, NC 27517

+ +

 

+ +

3Benson Consulting, Columbia, Missouri, +USA

+ +

 

+ +

4Integrated Environmental Modeling Branch, +Systems Exposure Division, USEPA/ORD/NERL, Research Triangle Park, NC 27711

+ +

 

+ +

 

+ +

                                                                       

+ +

 

+ +

Date:                     September +20, 2018

+ +
+
+ +

 

+ +

Disclaimer

+ +

 

+ +

The information in this operational guidance document has +been funded wholly or in part by the United States Environmental Protection +Agency. The draft version of this document has not been subjected to the +Agency’s peer and administrative review, nor has it been approved for +publication as an EPA document. The draft document has been subjected to review +by the Community Modeling and Analysis System Center only; this content has not +yet been approved by the EPA. Mention of trade names or commercial products +does not constitute endorsement or recommendation for use.

+ +

 

+ +

Acknowledgments

+ +

 

+ +

The development of the FEST-C +system is currently being supported by the U.S. EPA’s Computational Exposure +Division (CED) under U.S. EPA contract EP-W-16-014, “Operation of the Center +for Community Air Quality Modeling and Analysis (CMAS)” in support of Office of +Research and Development Air Climate and Energy, Safe and Sustainable Waters +and Safe and Healthy Communities Research Programs.  This work was also +supported under prior U.S. EPA contracts: EP W 09 023, “Operation of the Center +for Community Air Quality Modeling and Analysis (CMAS),” and EP D-12-044, +“Emissions, Air Quality, and Meteorological Modeling Support (EMAQ).”  We +greatly appreciate the continuing and generous intellectual support we have +received from Dr. Jimmy R. Williams at Texas A&M AgriLife Research, +Blackland Research & Extension Center (Temple, TX).  We thank Joe Slater, +Manager of Fertilizer/AG Lime Control Services, University of Missouri +Agricultural Experiment Station at Columbia, MO, for his invaluable insights +regarding fertilizer sales and use.  Finally, we thank Dr. Qun He for his +design and support on the FEST-C interface.

+ +
+
+ +

 

+ +

 

+ +

 

+ +

Contents

+ +

1. The +FEST-C System.. 1

+ +

1.1 +Introduction. 1

+ +

1.2 +Components. 3

+ +

1.3 +Installation and Requirements. 4

+ +

1.4 +Interface Launch. 5

+ +

2. File Structures +for EPIC Modeling. 7

+ +

3. Scenario +Management Selections under the File Menu. 17

+ +

4. The +Pre-EPIC File Generation Tools. 21

+ +

4.1 BELD4 +Data Generation. 23

+ +

4.2 Crop +Site Info Generation. 27

+ +

4.3 WRF/CMAQ +to EPIC.. 29

+ +

5. EPIC +Spin-up Run Tools. 32

+ +

5.1 EPIC +Site File Generation. 32

+ +

5.2 Soil +Match for EPIC Spinup. 34

+ +

5.3 +Management File Generation for Spinup. 35

+ +

5.4 +View/Edit EPIC Inputs. 37

+ +

5.5 EPIC +Runs for Spinup. 38

+ +

6. EPIC +Application Run Tools. 41

+ +

6.1 +Management File Generation for Application. 41

+ +

6.2 EPIC +Runs for Application. 43

+ +

7. Output +Processing and Visualizing Tools. 46

+ +

7.1 EPIC +Yearly Extraction. 46

+ +

7.2 EPIC to +CMAQ.. 49

+ +

7.3 EPIC to +SWAT. 52

+ +

7.4 +Visualization. 56

+ +

8. Future Work. 57

+ +

 

+ +

 

+ +
+ +
+
+ +
+ +

1. The FEST-C System

+ +

1.1 Introduction

+ +

The Fertilizer +Emission Scenario Tool for CMAQ (FEST-C) (http://www.cmascenter.org/fest-c/) +is a Java-based interface system that facilitates the integration of +agriculture, atmosphere, and hydrology simulations at large scales.  With an +adapted Environmental Policy Integrated Climate (EPIC) model (http://epicapex.tamu.edu/ +epic/) for grassland and crop production, the system is primarily +used to simulate daily soil carbon (C), nitrogen (N), and phosphorus (P) cycles +on agricultural lands with atmospheric conditions and management practices +including fertilization and irrigation.  The FEST-C interface +with simple tool buttons guides users through EPIC simulations and output +extractions to generate the required input for bidirectional NH3 +modeling performed using the Community +Multiscale Air Quality (CMAQ) modeling system (http://www.cmascenter.org/cmaq/).  In addition to its application for air quality +modeling, the system has been enhanced to integrate with the Soil and Water +Assessment Tool (SWAT, https://swat.tamu.edu/) +for watershed hydrological simulations.   FEST-C enables the extraction of +SWAT-ready input files with nutrients and water runoffs from agricultural lands +and weather and N deposition from atmospheric models for simulating nitrogen +fate and transport in watersheds.  The FEST-C system is developed by EPA +scientists, Institute for the Environment at the University of North Carolina +at Chapel Hill (UNC), and Benson Consulting with the help from the Texas A&M AgriLife Research.  UNC and Benson +Consulting were supported under contract to the U.S. EPA Office of Research and +Development.

+ +

The EPA EPIC +implementation requires no previous estimates of fertilizer application; it estimates +daily soil N conditions with fertilizer applications based entirely on +simulated plant demand in response to local soil and weather conditions.  The +FEST-C interface associates EPIC simulations spatially to the CMAQ domain covering +the conterminous United States (CONUS) and resolution through the current +release of the Spatial Allocator (SA) Raster Tools system (http://www.cmascenter.org/sa-tools/) +that has been developed under the Community Modeling and Analysis System (CMAS) +Center.  Figure 1 displays the process diagram of FEST-C linkage with the Weather +Research and Forecasting (WRF, http://www2.mmm.ucar.edu/wrf/users/), +CMAQ, and SWAT modeling systems.  The Biogenic Emissions Landcover Database +version 4 (BELD4), which is generated using the BELD4 tool in the SA Raster +Tools system, is consistently used in the FEST-C system as well as the WRF/CMAQ +modeling system.  Previous WRF/CMAQ system results provide daily weather inputs +and N deposition (optional), to the FEST-C system.  In return, FEST-C generates +soil properties (e.g. texture, moisture, and pH) and daily ammonium and nitrate +N pool status for specific crops assigned to agricultural land areas in each of +the CMAQ bidirectional NH3 modeling grids.  With the integrated +land-air-water models, FEST-C can be used in assessing not only the impacts of +agricultural fertilization and management practices on water quantity and +quality, air quality (NH3), and climate (N2O), but also +the impacts of meteorology/climate and air quality (N deposition) on crop +yield, soil erosion, watershed hydrology and quality, and overall C-N-P +biogeochemical status of the agricultural ecosystem. 

+ +

+ +

Figure 1. The FEST-C process diagram.  The system +works for any domains covering the CONUS and for any of the four WRF +projections (longitude/latitude, Lambert Conformal Conic, Universal Polar Stereographic, +and Mercator).

+ +

FEST-C is designed to be used +for CMAQ domains in North America, particularly for domains covering CONUS.  +The current version of the EPIC system for CMAQ has complete modeling +capabilities for grids located within the U.S. To apply this system to other +regions, users must modify the databases (particularly for soil) that were +created within the FEST-C system and to change the agricultural management file +generation, as different regions will likely have different agricultural +management practices in addition to different soil properties.  For areas +outside the U.S., the bidirectional CMAQ internally estimates these inputs for +regions in Canada and Mexico.  The system works for domains at different +resolutions and in any of the four WRF projection coordinate systems: +longitude/latitude, Lambert Conformal Conic, Universal Polar Stereographic, and +Mercator.     

+ +

1.2 Components

+ +

The version 1.4 release +of the FEST-C system (FEST-C v1.4), which includes Java interface programs, +EPIC FORTRAN codes, and associated data sets, was developed for Linux-based +operating systems.  The FEST-C Java interface is licensed under the Gnu Public +License (GPL) version 3.  The downloaded FEST-C system contains the following +two directories:

+ +

·         +festc – contains the Java-based interface.

+ +

·         +epic – stores EPIC model version 0509, which has been modified to +meet CMAQ input requirements; and related utilities and data for FEST-C v1.4.  +The original EPIC model description can be obtained from the Texas A&M +AgriLife Research web site (http://epicapex.tamu.edu/files/2013/02/epic0509usermanualupdated.pdf +).  The documentation of the modified EPIC modeling system for CMAQ is included +in the release of the FEST-C system.  It provides detailed information on how +this particular application of EPIC was developed. 

+ +

The FEST-C system +requires that the SA Raster Tools system be installed on the same computer system +where FEST-C resides.  For visualization, users can configure FEST-C to view NetCDF +files using the Visualization Environment for Rich Data Interpretation (VERDI) +or NCVIEW.  Both the SA Raster Tools and the VERDI system and their +documentation can be obtained from the CMAS web site (https://www.cmascenter.org/). 

+ +

1.3 Installation and Requirements

+ +

Users need to +untar the obtained FEST-C and SA packages in their system from the CMAS Center +Software Clearinghouse, https://www.cmascenter.org.  The +programs under FEST-C do not need any compiling, as the system comes with +static compiled tools.  The Raster Tools under SA, which are required by +FEST-C, are not statically pre-compiled with the package.  Depending on the +system configuration, users may need to recompile the SA Raster tools if there +is a library call error when running the tools using FEST-C.  Assuming the +downloaded FEST-C system is installed under the ${FESTC_HOME} directory +and the Spatial Allocator is installed under the ${SA_HOME} directory, +users should perform the following steps:

+ +

1.      +Modify ${FESTC_HOME}/festc/config.properties to set:

+ +

·         +work.dir – working directory for scenarios.

+ +

·         +epic.home – epic home directory, which should be ${FESTC_HOME}/epic; + includes common data and executables for both EPIC and utilities.

+ +

·         +sa.home – installed Spatial Allocator directory, which should be ${SA_HOME}.

+ +

·         +visual.program.home – directory containing VERDI program.

+ +

·         +queue.cmd – queue job submission command such as qsub or bsub.  +Queue configuration (includes queue.name and queue.bigmem as well) for job +submission has to be modified based on the user’s Linux system.  Comment out +(place # sign in the front) the three queue configurations if user’s systems do +not have batch job queuing systems.

+ +

·         +queue.name – queue name.

+ +

·         +queue.bigmem – big memory setup to be used by the EPIC-to-CMAQ +tool.

+ +

·         +debug – set to “true” to print out debug message.  It is +recommended that users not change this setting.

+ +

·         +allow.diff.check – set to “true” for checking consistent input in +"Minimum Crop Acres" and "Fertilizer Year" fields +from different subinterfaces.  It is recommended that users not change this +setting.   

+ +

2.      +Make a directory called “festc” under the user’s home directory, +which is assumed to be ${USER_HOME}, then copy ${FESTC_HOME}/config.properties +to the ${USER_HOME}/festc directory.  Change the work.dir setting if +needed. 

+ +

3.      +Modify ${FESTC_HOME}/festc/festc.sh file to set:

+ +

·         +FESTC_HOME to ${FESTC_HOME}/festc.

+ +

·         +-Xmx1024M to -Xmx2048M (optional) if users want to use 2 GB of +RAM to run the interface.

+ +

·         +JAVA path (optional) if users do not want to use the Standard +Edition Runtime Environment (JRE) version 8 for Linux 32-bit and 64-bit systems +that is included in the FEST-C release.

+ +

4.      +Modify ${FESTC_HOME}/festc/festc_setup.csh to:

+ +

·         +Set the ${FESTC_HOME} and ${SA_HOME} directories.

+ +

·         +Source the file in the user’s .cshrc file.

+ +

5.      +Launch FEST-C 1.4 interface by typing:

+ +

·         +Type festc in any directory with the x-window capability.

+ +

Troubleshooting +for the SA Raster Tools:

+ +

The SA Raster +Tools have compiled tools which are stored under ${SA_HOME}/bin/64bits.  +The executable tools may not work depending on the system configuration.  If +there is a library error in running the SA Raster Tools within FEST-C, users +should:

+ +

·         +Recompile all libraries under ${SA_HOME}/src/libs +following instructions in the ${SA_HOME}/src/libs/README file.

+ +

·         +Modiy ${SA_HOME}/src/raster/Makefile for correct paths.

+ +

·         +Type “make clean” to clean previous compiled programs.

+ +

·         +Type “make” to compile the tools.

+ +

·         +Type “make -B install” or “make install” to install compiled +tools.

+ +

1.4 Interface Launch

+ +

The FEST-C +interface facilitates the creation of the spatial associations, input files, +soil initial­ization, and application processes required by EPIC.  After +preliminary site information and soils are assigned to each grid cell, a +25-year “spin-up” simulation is required to generate initial soil and annual +nitrogen demand conditions that represent the management system the user has +defined.  These initial conditions are provided to the year-specific +application and management scheme.  To launch the FEST-C interface +system, type:

+ +

·         +festc or ${FESTC_HOME}/festc/festc.sh

+ +

 

+ +

The FEST-C interface allows the +user to create, select, and manage different scenario manage­ment schemes under +the File menu for EPIC modeling and sub-interface tools (see Figure 2). 

+ +

+ +

Figure 2. The +FEST-C interface system.

+ +

The system is described in detail +in the remaining sections of this document:

+ + + +

1.      +BELD4 Data Generation

+ +

2.      +Crop Site Info Generation

+ +

3.      +WRF/CMAQ to EPIC

+ + + +

1.      EPIC +Site File Generation

+ +

2.      Soil +Match for EPIC Spin-up

+ +

3.      +Management File Generation for Spin-up

+ +

4.      +View/Edit EPIC Inputs

+ +

5.      +EPIC Runs for Spin-up

+ + + +

1.      +Management File Generation for Application

+ +

2.      +EPIC Runs for Application

+ + + +

1.      +EPIC Yearly Extraction

+ +

2.      +EPIC to CMAQ

+ +

3.      +EPIC to SWAT

+ +

4.      +Visualization

+ +

·         +Section 8: Future Work

+ +

2. File Structures for EPIC Modeling

+ +

The EPIC model +and related utilities and data are stored under the ${FESTC_HOME}/epic directory.  +The working directory, which is named “scenarios”, is defined by work.dir +in the user’s config.properties file.  In the released tar, “scenarios” +with a sample “test_case” scenario is provided for users to test the +system under the epic directory.  After the installation, users can move +the “scenarios” directory to their working space and modify the work.dir +entry for the new location.  The file structure for EPIC modeling within the +FEST-C system is displayed in Figure 3. 

+ +

+ +

Figure 3. File +structure for EPIC modeling (directory names in black and files in blue)

+ +

The epic +directory contains four subdirectories: model, util, common_data, and doc; +scenarios is under work.dir, which is specified in config file under home +directory. These are described below.

+ +

·         +model – used to store the EPIC0509 model for FESTCv1.4.  It +includes one subdirectory:

+ +

-        +current: contains two EPIC models for spin-up and +application simulations modified from EPIC0509 for CMAQ modeling.  The EPIC0509 +with many updates were obtained from the Texas A&M AgriLife Research.

+ +

·         +doc – contains the documentation on the development of the +EPIC modeling system for CMAQ (EPA_EPIC_application_v1_10252013.pdf).

+ +

·         +util – contains utility programs developed by Benson +Consulting to generate site, soil, and management input files required by EPIC. +It has four subdirectories:

+ +

-        +siteCreate: contains two programs used by the EPIC Site +File Generation tool.  The programs will not only generate EPIC site files but +also link EPIC sites (grid cell centroids) to the BELD4 crop grid assignments +and the 8-digit hydrologic cataloging units (HUCs) that contain the grid cells +to be used in the soil matching program.  Based on BELD4, this program assigns +only those crops to a grid cell that BELD4 indicates are present at that +location.  This minimizes the number of crop-specific simulations performed +across large domains.  Users need to input the minimum crop acres, usually 0 or +40 acres, but can be any value, to be included in EPIC simulations.  The larger +the cropland area minimum, the fewer crops that will be identified within a +grid for EPIC, the fewer the grid-level simulations and the faster the overall +system execution time.

+ +

-        +soilMatch: contains six soil matching programs used by the +Soil Match for EPIC Spinup tool.  Soils are selected based on the U.S. +Department of Agriculture (USDA) 1997 Natural Resource Inventory (NRI) +assignment of each crop in each 8-digit HUC to its most common HUC-8 soil type. +

+ +

-        +manageCreate: contains programs to create EPIC management +files for spin-up and application simulations by the Management File +Generation for Spinup and Management File Generation for Application +tools.

+ +

-        +swat: contains R codes and associated sample c-shell +scripts to extract daily EPIC outputs, nitrogen deposition, and daily weather +and to transfer them to SWAT input by clicking “EPIC”, “NDEP”, “DailyWETH”, and +“SWAT INPUTS” sequentially.  “SWAT INPUTS” is the last button users should click +for aggregating all input data generated from the first three buttons into SWAT +input format.  The tool associated with “SWAT INPUTS” button requires a text +file including delivery ratios for EPIC to SWAT integration.  The sample text +file is provided in the “share_data” directory under the test_case +scenario as “subbasins-mapping_test_case.csv”.  Users need to create this file +for their corresponding watershed SWAT simulations. 

+ +

-        +misc: contains utility programs for converting the +generated BELD4 land use file in NetCDF format to be in IO/API format for the +CMAQ bi-directional modeling (used by the BELD4 tool script), aggregating EPIC +variables from yearly average extraction output by regions (e.g. 8-digit +hydrologic units, states, counties, and the whole domain) and by crops (e.g. 42 +crops), summarizing N fertilizer application from extracted daily files for +CMAQ, and generating files with selected EPIC daily output variables for the +8-digit HUC areas.  Users can access the README file in the directory and modify +the C shell scripts in the subdirectories to use the tools. Users must have the +required R libraries installed to run the R tool utilities.      

+ +

·         +common_data – contains data sets needed for EPIC and +utility programs.  Also provided under this subdirectory is the file EPIC_42crop_names.txt, +which contains the crop names and numbers, used in the FEST-C system.  This +directory has the following subdirectories:

+ +

-        +BaumerSoils: contains the soil data sets (22,838 soils) built +with soil parameters from the Baumer database developed by Dr. Otto Baumer of National +Soil Survey Laboratory (NSSL) at USDA.  Dr. Baumer used the SOILS5 database and +soil pedon data to develop the representative EPIC data sets.  Benson +Consulting utilized this information to create a subset of soil parameters in +22,838 soil files to be used with EPIC.  Detailed information on the data set +creation can be obtained from the documentation of the EPIC modeling system for +CMAQ.   The raw soil profiles have been QA’d and missing descriptors have been +filled so that they may be similar, but are not identical to the profiles available +through the USGS STATSGO and SURRGO databases.

+ +

-        +EPIC_model: contains two 5-year average CMAQ N deposition +daily and NetCDF files and the following two directories, which have common +data files required by EPIC spin-up and application runs.  The two 5-year +average N deposition daily files under dailyNDep_2004 and dailyNDep_2008 +directories provide 5-year average CMAQ-simulated N deposition estimates for +each calendar day over the periods 2002-2006 (referred to as “2002-2006 5-year +CMAQ average” and 2006-2010 (referred to as “2006-2010 5-year CMAQ average”.  These +periods are provided to reflect the documented non-stationarity of N deposition +trends.  The average N deposition data are from the U.S. CMAQ domain which has +the following properties:

+ +

GRID_PROJ    +"+proj=lcc +a=6370000.0 +b=6370000.0 +lat_1=33 +lat_2=45 +lat_0=40 ++lon_0=-97"

+ +

GRID_ROWS     +299

+ +

GRID_COLUMNS  +459

+ +

GRID_XMIN    +-2556000.0

+ +

GRID_YMIN    +-1728000.0

+ +

GRID_XCELLSIZE +12000.0

+ +

GRID_YCELLSIZE +12000.0

+ +

The +N deposition data from the nearest grid point in the average daily sets is selected +in EPIC simulations.

+ +

·         +spinup – has common files used for EPIC spin-up +simulations. For all crops except potatoes, the spin-up is set to run for 25 +years using the EPIC statistical weather generator (see the weather generator discussion +in the EPIC documenta­tion from the Texas A&M AgriLife Research).  We have +arbitrarily set the starting year as 1978 in EPICCONT.DAT.  The termination +date is not used by any subsequent codes and, since the driving data are +statistically generated, do not exactly correspond to any observation year.  For +potatoes, the spin-up is set to run for 100 years from 1903 in EPICCONT_POTATOES.DAT. + 

+ +

·         +app – contains common files used for EPIC application +simulations.  In the FEST-C system, users input the target year (1 year only) +for the EPIC application simulation.  When a new scenario is created, +EPICCONT.DAT from this directory is copied to the scenarios/“scenario +name”/share_data directory and the simulation period is changed to 2 years +starting from the year previous to the simulation year.  Two years’ worth of +weather data are needed to support production of fall-sown crops.  At present, +the same weather is used for both years.  In the future, an option may be added +to support input of two unique weather time series. 

+ +

-        +gisFiles: includes U.S. counties, U.S. states plus some +boundary areas in Canada and Mexico, U.S. 8-digit HUC shapefiles, and elevation +and slope raster files.  The readme file in the directory describes each file +and associated attributes in detail. 

+ +

-        +statWeath: contains weather station climate statistics +files distributed with the standard EPIC package.

+ +

-        +util: includes common files used by the utility programs.  +This directory has two subdirectories:

+ +

·         +soilMatch – has input files used by the soil matching +program to create EPIC soil files for the EPIC Runs for Spinup tool.

+ +

·         +manageCreate – contain files to be used in generating EPIC +spin-up and application management files.  We developed management data with +fertilizer types applied in 2001 and 2006 for each of 10 production regions +(Northeast, Appalachia, Southeast, Lake States, Corn Belt, Delta States, +Northern Plains, Southern Plains, Mountain, and Pacific) (see the region map in +Cooter et al. [2012], which is listed in the “Online Resources” section of the +FEST-C web site (http://www.cmascenter.org/fest-c/).  +Fertilizer types (but not amounts) applied are based on fertilizer sales of 62 +major fertilizer types by state.  Users can obtain detailed information from +the docu­mentation for the EPIC modeling system for CMAQ.  It is recommended +that 2001 be used for applications prior to 2006, and that 2006 be used for +applications from 2006 through 2010.  We anticipate that a 2011 fertilizer type +file will be included in the next interim release.  Fertilizer types applied +are used by the EPIC management file generation for application, and they are +stored under the following two subdirectories: 

+ +

-        +2001: for 2001 fertilizer year management file +generation. 

+ +

-        +2006: for 2006 fertilizer year management file +generation. 

+ +

In +both cases, regional fertilizer data information is stored under the directory:

+ +

-        +regionFert 

+ +

·         +scenarios – contains EPIC application scenarios and it is +the working directory for a user.  The directory is described separately below +this bulleted list.

+ +

 

+ +

In general, users should not change +the data files described in the above directories.  All files generated by +users’ applications are stored under the scenarios directory.  When the +user creates a scenario by selecting “New Scenario” under the File menu, +the following items are created:

+ +

·         +scenariosInfo – a metadata file that stores information for +the created scenario, which is assumed to be named by the user as “scenario +name”.  This directory contains:

+ +

-        +“scenario name”: an XML file that stores the scenario information.  +

+ +

-        +logs: directory containing the script file used to create (or +copy or delete as well) the scenario and execution log file.

+ +

·         +“scenario name” – scenario directory that will contain all +generated files for this scenario.

+ +

Under each scenario directory, the +following directories are created for EPIC modeling:

+ +

·         +share_data – contains all data sets generated for EPIC +modeling and to be used by all crops modeled.  The following two data subdirectories +which store generated EPIC site files and daily weather files are included +under this directory: 

+ +

-        +SIT: contains EPIC site files.

+ +

-        +dailyWETH: contains daily weather and N files for EPIC +modeling.

+ +

·         +scripts – stores script and log files created to run the +tools within the FEST-C interface.  All tools are executed through the Linux +queue system.  Users should always check the log file to make sure that the +queue job completed correctly.  Unwanted files under this directory should be +cleaned out periodically. 

+ +

·         +work_dir – contains some intermediate or temporary files +created by the FEST-C tools.  Not many files are created under this directory.  +

+ +

·         +21 crop dirs ( "HAY", "ALFALFA", +"OTHER_GRASS", "BARLEY", "EBEANS", +"CORNG", "CORNS", "COTTON", "OATS", +"PEANUTS", "POTATOES", "RICE", "RYE", +"SORGHUMG", "SORGHUMS", "SOYBEANS", +"SWHEAT", "WWHEAT", "OTHER_CROP", +"CANOLA", "BEANS") – the 21 crop directories are +created by the EPIC Site File Generation tool.  Under each crop +directory there are many files that are created for generating EPIC input +files.  The spinup and app subdirectories described below are +also created from management file generation and EPIC runs for spin-up and +application:

+ +

-        +spinup: contains files created from the EPIC management +file generation and EPIC runs for spin-up tools.  It contains the following +three subdirectories:

+ +

·         +manage – contains EPIC run files, EPIC site management +files created by the Management File Generation for Spinup tool, and +tile drain soil list file. The management files and tile drain soil list file are +contained under the following subdirectories:

+ +

-        +OPC: contains the management schedule for each domain grid +cell containing rain-fed and irrigated crop.  Variables (schedule) can be +interpreted using the documentation for the EPIC modeling system for CMAQ.

+ +

-        +tileDrain: contains the SOILLIST.DAT which has soil tile +drain information for EPIC spinup runs.  In general, if a soil is classified as +hydric, then it is assumed to drain.

+ +

·         +rainf – contains files for each domain grid cell that are created +by the EPIC Runs for Spinup tool from rain-fed crops.  It contains the +following output directories (see the EPIC documentation from the Texas A&M +AgriLife Research):

+ +

-        +DFA: daily fertilizer and other output.

+ +

-        +NCM: monthly fertilizer and other output.

+ +

-        +NCS: monthly soil output.

+ +

-        +OUT: standard EPIC output file that contains various +budget tables and summaries of the simulation which are useful for debugging.

+ +

-        +SOL: soil output files that are used as initial values for +the application.

+ +

-        +TNA: annual fertilizer and other outputs.

+ +

-        +TNS: annual soil output.

+ +

·         +irr – contains files for each domain grid cell containing the +particular crop that were created by the EPIC Runs for Spinup tool from +irrigated crops.  It contains the following output directories:

+ +

-        +DFA: daily fertilizer and other output.

+ +

-        +NCM: monthly fertilizer and other output.

+ +

-        +NCS: monthly soil output.

+ +

-        +OUT: standard EPIC output file that contains various +budget tables and summaries of the simulation that are useful for debugging.

+ +

-        +SOL: soil output files.

+ +

-        +TNA: annual fertilizer and other outputs that are useful +for debugging.

+ +

-        +TNS: annual soil output.

+ +

-        +app: contains files created from the management file +generation and EPIC runs for application tools.  It contains the following +three subdirectories:

+ +

·         +manage – contains EPIC run files, EPIC site management +files created by the Management File Generation for Application tool, +and tile drain soil list file.  Management files and the tile drain soil list +file are contained under the following subdirectories:

+ +

-        +OPC: contains the management schedule for each domain grid +cell containing rain-fed and irrigated crop.  Variables (schedule) can be +interpreted using the documentation for the EPIC modeling system for CMAQ.

+ +

-        +tileDrain: contains the SOILLIST.DAT which has soil tile +drain information for EPIC application runs.

+ +

·         +rainf – contains files created by the EPIC Runs for +Application tool from rain-fed crops.  It contains the following output +directories (see the EPIC documentation from the Texas A&M AgriLife +Research):

+ +

-        +DFA: daily fertilizer and other output.

+ +

-        +NCM: monthly fertilizer and other output.

+ +

-        +NCS: monthly soil output.

+ +

-        +OUT: standard EPIC output file that contains various +budget tables and summaries of the simulation (useful for debugging).

+ +

-        +SOL: soil output files.

+ +

-        +TNA: annual fertilizer and other outputs.

+ +

-        +TNS: annual soil output.

+ +

·         +irr – contains files created by the EPIC Runs for +Application tool from rain-fed crops.  It contains the following output +directories:

+ +

-        +DFA: daily fertilizer and other output.

+ +

-        +NCM: monthly fertilizer and other output.

+ +

-        +NCS: monthly soil output.

+ +

-        +OUT: standard EPIC output file that contains various +budget tables and summaries of the simulation (useful for debugging).

+ +

-        +SOL: soil output files.

+ +

-        +TNA: annual fertilizer and other output.

+ +

-        +TNS: annual soil output.

+ +

·         +output4CMAQ – stores EPIC output files and extracted NetCDF +files for quality assurance (QA) and CMAQ bidirectional NH3 +modeling.  This directory contains the two following subdirectories:

+ +

-        +spinup: contains all files created from EPIC spin-up +simulations for CMAQ.  It contains the following three subdirectories:

+ +

·         +5years – contains extracted average EPIC output for each +crop from the last five years of the spin-up simulation.  Files are named as +“BELD4 Crop Number”.dat (see Table 1 in Section 4.1 for crop numbers). 

+ +

·         +daily – stores daily EPIC output files for the EPIC spin-up +simulation of each crop.  “BELD4 Crop Number”.NCS is for soil output and “BELD4 +Crop Number”.NCD is for fertilizer and other daily output. 

+ +

·         +toCMAQ – contains created NetCDF and IO/API files with +EPIC spin-up output for selected modeling grid cells with crop data.  The NetCDF +output files are created using the FEST-C tools by extracting data files stored +under the 5years or daily directories listed above.

+ +

-        +app: stores files created from EPIC application simulations +for CMAQ.  It contains the following three subdirectories:

+ +

·         +year – contains extracted average EPIC output for the EPIC +application year.  Files are named as “BELD4 Crop Number”.dat. 

+ +

·         +daily – stores daily EPIC output files for the EPIC application +simulation of each crop.  “BELD4 Crop Number”.NCS is for soil output and “BELD4 +Crop Number”.NCD is for fertilizer and other daily output. 

+ +

·         +toCMAQ – contains created NetCDF and CMAQ-ready IO/API +files with the BELD4 data and EPIC application simulation results for the +modeling domain.  The NetCDF output files are created using the FEST-C tools by +extracting data files stored under the year or daily directories +listed above.

+ +

·         +output4SWAT – stores daily EPIC, N deposition, and +meteorology files summarized by regions and SWAT-ready input files for SWAT +simulation.  This directory contains four subdirectories:

+ +

-        +dailyEPIC – contains runoff data extracted from EPIC daily +output files.  The extracted data are summarized by the domain, county, state, HUC2, +HUC6, and HUC8. 

+ +

-        +dailyWETH – contains extracted weather data.

+ +

-        +NDEP – contains extracted nitrogen deposition data.

+ +

-        +swat_inputs – contains SWAT-ready EPIC, weather, and N +deposition input files in subdirectories named as dailydep, dailyweath, +and EPICinputPoint

+ +

3. Scenario Management Selections under the File Menu

+ +

 

+ +

There are five scenario management +selections (as well as Exit) under the File menu at the upper left of the +FEST-C tool bar: Open Scenario, New Scenario, Copy Scenario, +Save Scenario, and Delete Scenario. Each of these is described +below.

+ +

·         +Open Scenario – to open an already-created scenario. Users +always need to either open or create (see next bullet) a scenario to work on.  +Users can select any one of the scenarios under the scenarios/scenariosInfo +directory.  After users open a scenario, information for the scenario, such as +the domain description, will be automatically filled in by the FEST-C tool +interface.  Within the FEST-C system, users have to work within a scenario to +execute any of the tools except the Visualization tool.  Figure 4 shows +the interface used to open the test case created in the FEST-C system (The test_case +scenario is described at the beginning of Section 4).

+ +

+ +

Figure 4. Open Scenario selection +window used to open the test_case scenario.

+ +

 

+ +

·         +New Scenario – to create a new scenario (versus opening +one that’s already been created). In creating a new scenario, the user has to +provide the following information for a CMAQ modeling domain and EPIC +simulation year (see Figure 5):

+ +

-        +Rows, Columns: the number of rows and columns for the +domain.

+ +

-        +XCellSize, YCellSize: x and y resolution for +the grid cell.

+ +

-        +XMin, YMin: x and y coordinates of the lower +left corner of the lower left grid cell.  Users can often find this information +in the GRIDDESC file in the Meteorology-Chemistry Interface Processor (MCIP) +output.

+ +

+ +

Figure +5. New Scenario selection window with input to create the test_case +scenario within FEST-C.

+ +

 

+ +

-        +Proj4Projection: domain projection defined in Proj4 format +(see details at http://geotiff.maptools.org/proj_list/).  +The interface sets the Lambert Conformal Conic projection, which is used by the +CMAQ U.S. 12-km domain as the default.  Users can change it to any projection +supported for CMAQ modeling.

+ +

-        +Grid Name: user-supplied name for the domain, using no +more than 16 alphanumeric characters and no spaces. 

+ +

-        +Simulation Year: year (YYYY) for the EPIC simulation.  +FEST-C is designed to simulate yearly fertilizer application information for +CMAQ bidirectional NH3 modeling.

+ +

-        +NLCD/MODIS Data Year: year (YYYY) for the NLCD/MODIS land +cover data used for the EPIC simulation.  NLCD/MODIS land cover data are required +in the EPIC simulation within FEST-C for CMAQ bidirectional NH3 +modeling.  Currently, users can select 2001, 2006, or 2011 NLCD/MODIS data +year.  2016 NLCD/MODIS data selection will be added to the system in the +future.

+ +

-        +Scenario Name: name for the scenario, using alphanumeric +characters and no spaces.

+ +

When a new scenario is +created, the following files and directories are created:

+ +

-        +scenarios/scenariosInfo/“scenario name”: XML file to store the scenario information.

+ +

-        +scenarios/“scenario name”: directory +to store all generated information for this scenario.  Some subdirectories are +also generated under this scenario directory (see Section 2 for file +structures).

+ +

-        +scenarios/“scenario name”/share_data/EPICCONT.DAT: contains +EPIC constant parameters.  The simulation period is a two-year period starting with +the year before the simulation year.

+ +

·         +Copy Scenario – to copy an existing scenario under the scenarios/scenariosInfo +directory to a new scenario with a defined simulation year, which can be the same +as or different from the existing scenario year (see Figure 6).  Note that if +the existing scenario contains many crop simulations, this action can take a +long time to complete in a background queue job. 

+ +

 

+ +

+ +

Figure 6. Copy Scenario selection window.

+ +

 

+ +

·         +Save Scenario – to save a scenario after a user has worked +on it.  Only the input information for the scenario tool interfaces is saved.  +When the user performs the FEST-C tool actions, generated files are always +saved under different directories, described in Section 2. 

+ +

·         +Delete Scenario – to +delete a scenario.  This is also run as a background submission and can +take some time. All directories and subdirectories for that scenario are +deleted completely.

+ +

·         +Exit – to exit the FEST-C interface.  You will be asked if +you want to save the scenario you were working on before exiting the tool.

+ +

The action performed by making a selection +under the File menu (e.g., copy, create, delete) is executed by a script file +through the queue job. The script and log files are stored under the scenarios/scenariosInfo/logs +directory.  Users should check the log files under the directory to +make sure that the selected action completely correctly.

+ +

4. The Pre-EPIC File Generation Tools

+ +

 

+ +

Before describing the various +FEST-C tools in Sections 4 through 7, we must first discuss the test_case +scenario in the FEST-C system, because we use this scenario to demonstrate the +input and output components on the tool interface.  The test_case +scenario is a small 12-km domain with 25 rows and 25 columns in the CMAQ +standard projection.  The domain is located in the northwest corner of Iowa and +crosses into Minnesota, South Dakota, and Nebraska.  Figure 7 illustrates the +domain grid cells with the identification numbers (GRIDID) used in the FEST-C +system; colors are used to indicate the crop percentage for each grid cell as generated +from 2006 NLCD data.  All 625 (25´25) +12-km grid cells in this test domain have crop coverage, and most of them have +more than 75% crop coverage.  The GRIDID for a grid cell with row and column +starting from 1 is defined as:

+ +

                                                          +(1)

+ +

where columns is the number +of columns for the domain.  Row and column start from 1 at the lower left +corner cell in the domain.  Users can compute the row and column for a grid +cell with GRIDID as:

+ +

       +                                            (2) +

+ +

                                     (3)

+ +

where floor is for rounding +down the value and remainder is for taking the remainder from the +division.     

+ +

+ +

Figure 7. +FEST-C test_case scenario 12-km domain in the U.S. northern Central Plains. +Associated with each grid cell is an identification number (GRIDID) and a color +that indicates crop coverage percentage.  The domain’s cells are numbered from +1 for the lower left corner cell to 625 for the upper right corner cell.

+ +

 

+ +

In Section 4, +we discuss the first three tools in the FEST-C interface: the BELD4 Data +Generation tool, the Crop Site Info Generation tool, and the WRF/CMAQ-to-EPIC +tool. These are used to prepare site crop and spatial data for EPIC input file +generation and to generate required daily weather data and optional nitrogen +deposition data for the EPIC simulation year.  All three tools were developed +in the SA Raster Tools system.

+ +

4.1 BELD4 Data Generation

+ +

EPIC modeling for a CMAQ domain requires BELD4 data, which are used for +selecting grid cells with crop coverage.  The BELD4 Data Generation tool +allows users to compute the BELD4 dataset for a selected scenario.  For detailed +information, users can consult the SA Raster Tools documentation: https://www.cmascenter.org/sa-tools/.  +Figure 8 shows the interface used to compute the BELD4 dataset for the test_case +scenario.

+ +

+ +

Figure 8. The BELD4 Data Generation tool +interface for the test_case scenario.

+ +

Before running this tool, users +need only to make sure that the following two entries are correct for their +scenarios:

+ +

·         +NLCD/MODIS Data Year – the year defined when creating the +scenario; it can be either 2001, 2006, or 2011.  Processed 2001, 2006, and 2011 +crop tables from the U.S. and Canada are stored under the ${SA_HOME}/data +directory for this tool.  The 42 rain-fed and irrigated crops generated from +the BELD4 tool and modeled in the FEST-C system are displayed in Table 1.  In +addition to crop numbers used in BELD4 (new version of BELD), the table also +lists BELD3 (older version) numbers, because we started building the FEST-C +system using the BELD3 data.  Crop numbers used in EPIC modeling often follow +the BELD3 crop numbers (from 22 to 63), but the output files from EPIC modeling +for use in CMAQ use the BELD4 crop numbers (from 1 to 42).  If a new crop is to +be modeled in the FEST-C system, new crop tables under the SA data +directory must be generated and the BELD4 tool has to be modified as well.  +Table 2 provides additional information on how crops are mapped to each EPIC crop +type.

+ +

Table 1. The 42 rain-fed and +irrigated crops modeled in the FEST-C system.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

BELD4

+
+

BELD3

+
+

Crop Name

+
+

BELD4

+
+

BELD3

+
+

Crop Name

+
+

BELD4

+
+

BELD3

+
+

Crop Name

+
+

1

+
+

22

+
+

Hay

+
+

15

+
+

36

+
+

Cotton

+
+

29

+
+

50

+
+

SorghumSilage

+
+

2

+
+

23

+
+

Hay_ir

+
+

16

+
+

37

+
+

Cotton_ir

+
+

30

+
+

51

+
+

SorghumSilage_ir

+
+

3

+
+

24

+
+

Alfalfa

+
+

17

+
+

38

+
+

Oats

+
+

31

+
+

52

+
+

Soybeans

+
+

4

+
+

25

+
+

Alfalfa_ir

+
+

18

+
+

39

+
+

Oats_ir

+
+

32

+
+

53

+
+

Soybeans_ir

+
+

5

+
+

26

+
+

Other_Grass

+
+

19

+
+

40

+
+

Peanuts

+
+

33

+
+

54

+
+

Wheat_Spring

+
+

6

+
+

27

+
+

Other_Grass_ir

+
+

20

+
+

41

+
+

Peanuts_ir

+
+

34

+
+

55

+
+

Wheat_Spring_ir

+
+

7

+
+

28

+
+

Barley

+
+

21

+
+

42

+
+

Potatoes

+
+

35

+
+

56

+
+

Wheat_Winter

+
+

8

+
+

29

+
+

Barley_ir

+
+

22

+
+

43

+
+

Potatoes_ir

+
+

36

+
+

57

+
+

Wheat_Winter_ir

+
+

9

+
+

30

+
+

BeansEdible

+
+

23

+
+

44

+
+

Rice

+
+

37

+
+

58

+
+

Other_Crop

+
+

10

+
+

31

+
+

BeansEdible_ir

+
+

24

+
+

45

+
+

Rice_ir

+
+

38

+
+

59

+
+

Other_Crop_ir

+
+

11

+
+

32

+
+

CornGrain

+
+

25

+
+

46

+
+

Rye

+
+

39

+
+

60

+
+

Canola

+
+

12

+
+

33

+
+

CornGrain_ir

+
+

26

+
+

47

+
+

Rye_ir

+
+

40

+
+

61

+
+

Canola_ir

+
+

13

+
+

34

+
+

CornSilage

+
+

27

+
+

48

+
+

SorghumGrain

+
+

41

+
+

62

+
+

Beans

+
+

14

+
+

35

+
+

CornSilage_ir

+
+

28

+
+

49

+
+

SorghumGrain_ir

+
+

42

+
+

63

+
+

Beans_ir

+
+ +
+ +

Table 2. Mapping of the 42 rain-fed and +irrigated crops for U.S. and Canada (Mexico will be available in a future +release).

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

BELD4

+
+

Crop Name

+
+

USA

+
+

Canada

+
+

1

+
+

Hay

+
+

HAY- (HAY, ALFALFA)-(HAY, + WILD) + HAYLAGE, (EXCL ALFALFA)

+
+

All other tame hay and + fodder crops

+
+

2

+
+

Hay_ir

+
+

Same items, irrigated

+
+

N/A

+
+

3

+
+

Alfalfa

+
+

ALFALFA HAY + ALFALFA + HAYLAGE

+
+

Alfalfa and alfalfa + mixtures

+
+

4

+
+

Alfalfa_ir

+
+

 Same items, irrigated

+
+

N/A

+
+

5

+
+

Other_Grass

+
+

(AG LAND, CROPLAND, + PASTURED ONLY )-(Hay+Alfalfa)

+
+

N/A

+
+

6

+
+

Other_Grass_ir

+
+

N/A

+
+

N/A

+
+

7

+
+

Barley

+
+

BARLEY

+
+

Barley

+
+

8

+
+

Barley_ir

+
+

 BARLEY, irrigated

+
+

N/A

+
+

9

+
+

BeansEdible

+
+

BEANS, DRY EDIBLE, LIMA; + BEANS, DRY EDIBLE, (EXCL LIMA)

+
+

Dry white beans; Other dry + beans

+
+

10

+
+

BeansEdible_ir

+
+

Same items, irrigated

+
+

N/A

+
+

11

+
+

CornGrain

+
+

CORN, GRAIN

+
+

Corn for grain

+
+

12

+
+

CornGrain_ir

+
+

CORN, GRAIN, IRRIGATED

+
+

N/A

+
+

13

+
+

CornSilage

+
+

CORN, SILAGE

+
+

Corn for silage

+
+

14

+
+

CornSilage_ir

+
+

CORN, SILAGE, IRRIGATED

+
+

N/A

+
+

15

+
+

Cotton

+
+

COTTON

+
+

N/A

+
+

16

+
+

Cotton_ir

+
+

COTTON, IRRIGATED

+
+

N/A

+
+

17

+
+

Oats

+
+

OATS

+
+

Oats

+
+

18

+
+

Oats_ir

+
+

OATS, IRRIGATED

+
+

N/A

+
+

19

+
+

Peanuts

+
+

PEANUTS

+
+

N/A

+
+

20

+
+

Peanuts_ir

+
+

PEANUTS, IRRIGATED

+
+

N/A

+
+

21

+
+

Potatoes

+
+

POTATOES+SWEET POTATOES

+
+

Potatoes

+
+

22

+
+

Potatoes_ir

+
+

Same fractional breakdown + of rainfed vs irrigated potatoes from 2006 data

+
+

N/A

+
+

23

+
+

Rice

+
+

N/A

+
+

N/A

+
+

24

+
+

Rice_ir

+
+

RICE, IRRIGATED

+
+

N/A

+
+

25

+
+

Rye

+
+

RYE

+
+

Fall rye

+
+

26

+
+

Rye_ir

+
+

RYE, IRRIGATED

+
+

N/A

+
+

27

+
+

SorghumGrain

+
+

SORGHUM, GRAIN

+
+

N/A

+
+

28

+
+

SorghumGrain_ir

+
+

SORGHUM, GRAIN, IRRIGATED

+
+

N/A

+
+

29

+
+

SorghumSilage

+
+

SORGHUM, SILAGE

+
+

N/A

+
+

30

+
+

SorghumSilage_ir

+
+

SORGHUM, SILAGE, IRRIGATED

+
+

N/A

+
+

31

+
+

Soybeans

+
+

SOYBEANS

+
+

Soybeans

+
+

32

+
+

Soybeans_ir

+
+

SOYBEANS, IRRIGATED

+
+

N/A

+
+

33

+
+

Wheat_Spring

+
+

WHEAT, SPRING, DURUM; + WHEAT, SPRING, (EXCL DURUM)

+
+

Spring wheat (excluding + durum); Durum wheat

+
+

34

+
+

Wheat_Spring_ir

+
+

WHEAT, SPRING, DURUM, + IRRIGATED; WHEAT, SPRING, (EXCL DURUM), IRRIGATED

+
+

N/A

+
+

35

+
+

Wheat_Winter

+
+

WHEAT, WINTER

+
+

Winter wheat

+
+

36

+
+

Wheat_Winter_ir

+
+

WHEAT, WINTER, IRRIGATED

+
+

N/A

+
+

37

+
+

Other_Crop

+
+

(AG LAND, CROPLAND) - (AG + LAND, CROPLAND, PASTURED ONLY) -sum of rainfed crops

+

 

+

If “AG LAND, CROPLAND” is + larger

+
+

Mixed grains; Spring rye; + Flaxseed; Forage seed for seed; Mustard seed; Sunflowers; Canary seed; + Ginseng; Buckwheat; Sugar beets; Caraway seed; Triticale; Other field crops

+
+

38

+
+

Other_Crop_ir

+
+

Irrland= (AG LAND, (EXCL + HARVESTED CROPLAND), IRRIGATED – ACRES) + (AG LAND, CROPLAND, HARVESTED, + IRRIGATED – ACRES)

+

=Irrland – sum of irr crops + (if irrland is larger)

+
+

N/A

+
+

39

+
+

Canola

+
+

CANOLA

+
+

Canola (rapeseed)

+
+

40

+
+

Canola_ir

+
+

CANOLA, IRRIGATED

+
+

N/A

+
+

41

+
+

Beans

+
+

PEAS, DRY EDIBLE

+
+

Dry field peas; Lentils; + Chick peas

+
+

42

+
+

Beans_ir

+
+

PEAS, DRY EDIBLE, IRRIGATED

+
+

N/A

+
+ +
+ +

 

+ +

·         +NLCD/MODIS List File – set to the fixed-format text file that +contains downloaded NLCD land use, imperviousness, and canopy data files and +downloaded tiled MODIS land cover (MCD12Q1) data sets.  The interface sets the +file ${SA_HOME}/data/ nlcd_modis_files_{NLCD/MODIS Data Year}.txt as the default +file.  Users need to download NLCD and MODIS land cover data sets and modify +the text file accordingly using the paths and names for the downloaded data +sets.  The text file must have the same fixed titles and format as in the +default file.  ${SA_HOME}/data/sat/README contains instructions on downloading +the data sets.  If users want to generate a 2001 BELD4 data set, 2001 NLCD and +MODIS land cover data sets have to be downloaded from the NLCD web site (https://www.mrlc.gov/finddata.php) +and MODIS land products web site (https://lpdaac.usgs.gov/products/modis_products_ +table/mcd12q1 ), and the nlcd_modis_files_2001.txt list file has to +be modified following the format in this sample file.

+ +

 

+ +

When the Run button on the BELD4 +Data Generation tool interface is clicked, a c-shell (csh) script file is +generated under the scenarios/”scenario name”/scripts directory.  This +file is submitted to the system as a queue job after the user clicks OK, and a +log file for the job execution will be generated after the queue job is finished.  +Users should always check for error messages in the log file, based on the +information provided in the Message Box (shown in Figure 8). 

+ +

 

+ +

The outputs produced by the tool +are the following files, which are stored under the ”scenario +name”/share_data and ”scenario name”/output4CMAQ/app/ toCMAQ directories:

+ +

·         +beld4_{Gird Name}_{NLCD/MODIS Data Year}.nc (beld4_TESTGRIDS_2006.nc +for the test_case scenario) – both  NetCDF and I/O API formatted files +containing gridded percentage data for imperviousness, canopy, 194 tree species, +40 NLCD/MODIS land cover classes, and 42 BELD4 crops are created.  The NetCDF domain- +and resolution-specific data file is a required input to the Crop Site Info +Generation tool discussed in the next section.  CMAQ bi-directional NH3 +modeling requires the I/O API formatted BELD4 output file under the ”scenario name”/output4CMAQ/app/toCMAQ directory.

+ +

·         +beld4_{Grid Name}_{ NLCD/MODIS Data Year}.txt +(beld4_TESTGRIDS_2006.txt for the test_case scenario) – a text table +containing gridded percentage data for impervious­ness, canopy, and 40 NLCD/MODIS +land cover classes for a specific domain and grid resolution.  

+ +

4.2 Crop Site Info Generation

+ +

The Crop Site Info Generation tool is used to +compute EPIC site (grid cells) and crop informa­tion for EPIC modeling.  The +tool processes spatial boundary shapefiles and elevation and slope image data +to generate site infor­mation data needed in EPIC modeling.  Figure 9 displays +the tool interface used to compute the crop site information for the test_case +scenario.  The tool uses the spatial data sets stored under ${FESTC_HOME}/epic/common_data/gisFiles +and input files from the ${SA_HOME}/data directory.  Before running this +tool, users need only to choose the following two entries for this tool:

+ +

·         +BELD4 NetCDF File – this is the BELD4 NetCDF file generated +using the BELD4 tool described above.  The file name should be of the form beld4_{Gird +Name}_{NLCD/MODIS Data Year}.nc (e.g. beld4_TESTGRIDS_2006.nc for the test_case +scenario).  If this file does not exist, the interface will indicate this after +Run is clicked.  If this is the case, users need to either run the BELD4 tool to +generate this data set or input anywhere within the computer system a BELD4 NetCDF +file that is based on the same domain as the domain of the scenarios with which +the users are working.

+ +

·         +Minimum Crop Acres – this is the minimum crop area for at +least one of the 42 possible crops in a grid cell, if the grid cell is to be +selected for EPIC simulation.  For instance, users can set it to be 40 acres for +representing the smallest commercially viable farm size.  For finer grid +resolutions or for domains in which smaller commercial enterprises make up a +significant fraction of farms (e.g., orchards, some vegetable and specialty +crops), users may need to reduce this minimum to adequately characterize the +distribution of agricultural lands.  For including all cropland in simulations, +users should set it to be 0.0.  Doing so may increase the number of simulated +grid cells (sites), which can also increase run time. 

+ +

+ +

Figure 9. The Crop Site Info Generation tool +interface used for the test_case scenario.

+ +

After Run has +been clicked and the queue job has completed, users should check the log file +under their scenario’s scripts directory to see whether any errors occurred +during execution.  The tool generates the following three text output files +stored under scenarios/”scenario name”/share_data:

+ +

·         +EPICSites_Info.csv – contains the GRIDID, XLONG, YLAT, ELEVATION, SLOPE_P, +HUC8, REG10, STFIPS, CNTYFIPS, GRASS, CROPS, CROP_P, COUNTRY, and +COUNTRY-PROVINCE items used for creating EPIC site files.

+ +

·         +EPICSites_Crop.csv – contains the GRIDID, acreages of 42 possible +crops within each grid cell, COUNTRY, and HUC8 items used in EPIC site and soil +file generation. 

+ +

·         +allSites_Info.csv – contains the GRIDID, XLONG, YLAT, ELEVATION, +SLOPE_P, HUC8, REG10, STFIPS, CNTYFIPS, GRASS, CROPS, CROP_P, COUNTRY, and +COUNTRY-PROVINCE items for all grid cells to be used in the SWAT watershed +extraction.

+ +

4.3 WRF/CMAQ to EPIC

+ +

The WRF/CMAQ-to-EPIC +tool is used to generate EPIC daily weather data and, if the option is +selected, N deposition inputs to be used in EPIC application simulations.  The +tool reads EPIC grid cell information stored in the allSites_Info.csv file +generated using the Crop Site Info Generation tool (the previous tool).  +It extracts daily weather input data from WRF simulation output (METCOR2D data +arrays) into a NetCDF file and EPIC-ready text files.  Users need to make sure +that the right version of the WRF/CMAQ-to-EPIC tools are compiled under +the Spatial Allocator. There are two versions of this tool: one for CMAQ before +version 5.2 and one for CMAQ v5.2 or above version. 

+ +

There are up to +four options currently available for the inclusion of daily atmospheric deposition +data in EPIC simulations: (1) no N deposition, (2) the original EPIC +default (assumes a constant N concentration of 0.8 ppm in precipitation and no +dry deposition), and (3) CMAQ hourly output files (DRYDEP, WETDEP1) from a +previous CMAQ run (unidirectional or bidirectional), and (4) a pre-processed +set of 5-yr average CMAQ deposition estimates for the period 2002-2006 (labeled +as 2004) and 2006-2010 (labeled as 2008).  In the vicinity of areas receiving +significant atmospheric dry deposition, such as areas immediately surrounding +large animal feeding operations, this information can impact EPIC +biogeochemistry and subsequent estimates of plant N application needs.  If +speciated N deposition is available, oxidized wet and dry deposition are +assumed to enter the EPIC soil nitrate pool, and reduced wet and dry deposition +is assumed to enter the EPIC soil ammonium pool.  If CMAQ hourly output files +are selected for this tool, the MCIP and CMAQ domains must be the same as the +domain defined in the EPIC scenario.  Figure 10 shows this tool interface as used +for the test_case scenario. 

+ +

+ +

Figure 10. The WRF/CMAQ-to-EPIC tool interface +used for the test_case scenario.

+ +

Before running this tool, users must +provide input for the following three items in the interface:

+ +

·         +MCIP Data Directory – this directory contains processed +WRF files output by MCIP for the EPIC simulation year.  This tool requires only +MCIP METCRO2D output files.  METCRO2D output files must have names of the +format METCRO2D*{DATE} in which * can be any non-digit characters and {DATE} +can be in one of four date formats: YYYYMMDD, YYMMDD, YYYYDDD, or YYDDD (e.g., METCRO2D_051226)

+ +

·         +Deposition Selection – used to select one of the following +three options:

+ +

-        +CMAQ deposition directory: select this option to use CMAQ +deposition output files.  If this is selected, users must set the CMAQ +deposition file directory in the next field on the interface.

+ +

-        +Default: this option assumes that the N mixing ratio is 0.8 ppm +for wet oxidized N deposition.  The tool computes wet oxidized N deposition based +only on WRF rainfall, and other N deposition variables are assumed to be zero.

+ +

-        +Zero: this option assumes that there is no atmospheric N.

+ +

·         +CMAQ Deposition Directory – used to set the directory +containing the CMAQ dry and wet deposition output files for the simulation year +if “CMAQ deposition directory” was chosen in the previous field.  The dry and +wet deposition file names must contain the string “DRYDEP” or “WETDEP”.  In +addition, the deposition file names must end with “*{DATE}” in the format that +is described for the MCIP files above (e.g., an MCIP file can be named as METCRO2D_20030416 +and the deposition files can be named CCTM_M2f_v14soa_v3.4beta3_2003.DRYDEP.20030416 +and CCTM_M2f_v14soa_v3.4beta3_2003.WETDEP1.20030416).  

+ +

After Run has +been clicked and the queue job has finished, users should check the log file +under their scenario’s scripts directory to see whether any errors +occurred during execution.  The tool generates the following three output files +stored under scenarios/”scenario name”/share_data:

+ +

·         +dailyWETH/“GRIDID”.dly – daily weather and N +files for each selected grid cell for EPIC modeling.  “GRIDID” is the +identification number for a selected grid cell (see Figure 7).  Each daily file +contains 14 formatted data items (listed in Table 3) to be used in the EPIC +runs for the simulation year (same as the weather year).  This daily weather +file is duplicated for the year before the simulation year because we run the +EPIC model for a two-year period using daily time steps. 

+ +

·         +EPICW2YR.2YR – daily weather file list to be used in EPIC +application modeling.  It is defined in ${FESTC_HOME}/epic/common_data/EPIC_model/app/EPICFILE.DAT.

+ +

·         +site_weather_dep_${YEAR}0101_to_${YEAR}1231.nc – a single NetCDF +file with daily time steps for the simulation year.  It contains extracted +daily weather and N deposition data for the all grid cells from the allSites_Info.csv +file.  Users can use the Visualization tool (discussed in Section 7) to +display the values of a selected variable spatially. 

+ +

 

+ +

Table 3. EPIC daily weather and nitrogen deposition +variables.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Index

+
+

Variable

+
+

Index

+
+

Variable

+
+

1

+
+

Year

+
+

8

+
+

Daily Average Relative Humidity

+
+

2

+
+

Month

+
+

9

+
+

Daily Average 10-m Wind Speed (m s-1)

+
+

3

+
+

Day

+
+

10

+
+

Daily Total Wet Oxidized N (g/ha)

+
+

4

+
+

Daily Total Radiation (MJ m2)

+
+

11

+
+

Daily Total Wet Reduced N (g/ha)

+
+

5

+
+

Daily Maximum 2-m Temperature (C)

+
+

12

+
+

Daily Total Dry Oxidized N (g/ha)

+
+

6

+
+

Daily minimum 2-m temperature (C)

+
+

13

+
+

Daily Total Dry Reduced N (g/ha)

+
+

7

+
+

Daily Total Precipitation (mm)

+
+

14

+
+

Daily Total Wet Organic N (g/ha)

+
+ +
+ +

5. EPIC Spin-up Run Tools

+ +

 

+ +

Users must run EPIC spin-up +simulations to generate initial soil files and annual plant N demand data, +which are used in EPIC application-year simulations.  Described in this section +are the five EPIC spin-up run tools: EPIC Site File Generation, Soil +Match for EPIC Spinup, Management File Generation for Spinup, View/Edit +EPIC Inputs, and EPIC Runs for Spinup. Users can use these tools +sequentially to generate files needed for the spin-up and launch the EPIC +spinup run.  Users can obtain detailed information on the EPIC databases from +the documentation for the EPIC modeling system for CMAQ, and on the file +formats and parameter descriptions from the EPIC model documentation at the Texas +A&M AgriLife Research (http://epicapex.tamu.edu/files/ +2013/02/epic0509usermanualupdated.pdf).

+ +

5.1 +EPIC Site File Generation

+ +

The EPIC Site +File Generation tool uses the FORTRAN programs stored under ${FESTC_HOME}/epic/util/siteCreate.  +This tool generates EPIC site files for the selected grid cells with the +minimum crop acreage limit criterion.  It also creates 21 crop directories with +a crop site list file that is to be used in the other tools.  As simulations +are performed, irrigated and rainfed results are maintained as separate +subdirectories under the overall crop directory.  Figure 11 displays the tool +interface for the test_case scenario with the Minimum Crop Acres set +to 40.  Users should use the same Minimum Crop Acres set in the Crop +Site Info Generation tool.    

+ +

+ +

Figure +11. The EPIC Site File Generation interface for the test_case +scenario.

+ +

After the queue job run has finished, +users should check the log file under their scenario’s scripts directory +to see whether any errors occurred during execution.  The tool generates the +following files and directories:

+ +

·         +“scenario name”/share_data/SIT/“GRIDID”0.SIT – EPIC site +files to be used for all EPIC crop modeling.  A description of the file format +can be obtained from the EPIC model documentation.

+ +

·         +“scenario name”/share_data/SITELIST.DAT – EPIC site list +file for all crops to be used in EPIC modeling.

+ +

·         +“scenario name”/“crop name”/“crop name”-LIST.DAT – EPIC +site list for the particular crop, to be used in the Soil Match for EPIC +Spinup tool discussed in the following section.  If there are no grid cells +that contain that crop, this file will be empty.

+ +

5.2 +Soil Match for EPIC Spinup

+ +

The Soil Match +for EPIC Spinup tool selects a soil for each crop within a grid cell and +creates the EPIC soil input file.  The EPIC soil datasets are built to +represent the sample point soils selected for USDA NRI data points at the HUC-8 +spatial scale. This tool links built EPIC soil datasets contained in the BaumerSoils +subdirectory to the soil series from the USDA NRI for the crop and grid cell.  It +uses the FORTRAN programs stored under ${FESTC_HOME}/epic/util /soilMatch +with the common data files stored under ${FESTC_HOME}/epic/common_data/ util/soilMatch +and the generated soil list data under each crop directory.  Figure 12 shows +the tool interface used to match soils for all crops (as explained at the +beginning of Section 5) for the current version of FEST-C.  After selecting the +crops, users click the Run button to run the tool in the queue.  After the job +has finished, users should check the queue job and log file in the “scenario +name”/scripts directory, based on the information provided in the Message +Box (shown in Figure 12). 

+ +

 

+ +

The tool generates many output +files under each crop directory, but most of them are inter­mediate files.  The +final data file created for the EPIC spin-up simulation is “scenario name”/ +“crop name”/SOILLIST.DAT, which contains the matched BaumerSoils +soil file with other parameters for each grid cell under each crop directory.  +This step can take substantial time to complete.

+ +

+ +

Figure +12. The Soil Match for EPIC Spinup tool interface used for the test_case +scenario.
+Users can select single or multiple crops for the current FEST-C version.

+ +

5.3 +Management File Generation for Spinup

+ +

The Management +File Generation for Spinup tool interface is used to create the EPIC manage­ment +for each crop within a grid cell. The EPICRUN file that has the linkages for +the grid cell, statistical weather and wind files, soil files, and management +files is also created for the rain-fed and irrigated forms of the crop.  This +tool uses the FORTRAN programs ManGenSU.exe and soildrain.exe stored under ${FESTC_HOME}/epic/util/manageCreate +with the common data files stored under ${FESTC_HOME}/epic/common_data/util/manageCreate +and many other data files generated under each crop directory.  Figure 13 shows +the tool interface used to generate management files for the test_case +scenario. 

+ +

+ +

Figure +13. The Management File Generation for Spinup tool used for the test_case +scenario.

+ +

Users need to make sure that the +following two fields are selected correctly:

+ +

·         +Fertilizer Year – select either 2001 or 2006 for choosing the +correct common data sets stored under ${FESTC_HOME}/epic/common_data/util/manageCreate.  + 2011 fertilizer year will be available in future releases.  NLCD/MODIS +2011 is available in this release and can be used (e.g. changes in crop +fraction) with the 2006 fertilizer year but changes to fertilizer types for +2011 will not be realized in these simulations.       

+ +

·         +Selected Crops – select one crop or multiple crops.

+ +

After the user clicks the Run +button and then “OK”, a queue job to generate management files for each +selected crop is submitted.  After the job has finished, users should check the +queue job and log file in the “scenario name”/scripts directory, based +on the information provided in the Message Box (shown in Figure 13). 

+ +

 

+ +

There are many output files +generated under each crop, but many of these are used just for verification. +The tool generates the following files to be used for the EPIC spin-up +simulations under the directory “scenario name”/“crop name”/spinup/manage for +each crop:

+ +

·         +EPICRUNFILERAIN.DAT – EPIC run file for rain-fed spin-up +simulation of this crop.

+ +

·         +EPICRUNFILEIRR.DAT – EPIC run file for irrigated spin-up +simulation of this crop.

+ +

·         +GRIDS_OPC.DAT – the list of management file names to be used in +EPIC modeling.

+ +

·         +OPC/“GRIDID”0“BELD3 Crop Number”.OPC – grid cell EPIC +management files under the OPC directory.  Table 1 in Section 4.1 lists +the crop numbers in the BELD data and how they are mapped, Table 2.    

+ +

·         +tileDrain/SOILLIST.DAT – soil list file which contains +tile drain information for EPIC simulations and is used when “tileDrain” is +selected when running EPIC spinup simulations.

+ +

5.4 +View/Edit EPIC Inputs

+ +

The View/Edit +EPIC Inputs interface allows users to view or edit five main EPIC +simulation files (listed in Figure 14).  Users generally do not need to edit these +files, but viewing them can be helpful for debugging. The user has to select a +crop first and then select the EPIC simulation type.  The simulation type can +be SPINUP if the Management File Generation for Spinup tool (previous +section) has been executed for the selected crop; or the user can select the +simulation type APP after the Management File Generation for Application +tool (discussed in Section 6.1) has been executed for the crop. Figure 14 shows +the View/Edit EPIC Inputs tool interface for the test_case +scenario. 

+ +

+ +

Figure +14. The View/Edit EPIC Inputs tool for the test_case +scenario.

+ +

5.5 +EPIC Runs for Spinup

+ +

The EPIC Runs +for Spinup tool interface is used to run the EPIC model for spin-up (EPICsu.exe +program), which is stored under the directory ${FESTC_HOME}/epic/model/current. +The tool uses input files stored primarily in the following directories:

+ +

·         +${FESTC_HOME}/epic/common_data/EPIC_model/spinup – contains +the common model input files.

+ +

·         +scenarios/“scenario name”/share_data – contains site files +and list file.

+ +

·         +${FESTC_HOME}/epic/common_data/statWeath – contains +observed climate station statistical data (see http://epicapex.tamu.edu/epic/)

+ +

·         +scenarios/“scenario name”/“crop name”/spinup/manage – contains +the run files, management files, and management list file.

+ +

·         +scenarios/“scenario name”/ “crop name” – contains the soil +list file.

+ +

Spin-up +simulations generate EPIC soil files reflecting the user-defined management to be +used as initial conditions in the application run for the simulation year.  Soil +erosion (wind and water) is “turned off” during the spin-up period to avoid +loss of productive soil layers.  These losses are “turned on” during +application year simulation.  As discussed in Section 2, the spin-up simulation +is run for 25 years starting from 1978 for all crops except potatoes; for potatoes +it is run for 100 years starting from 1903.  These dates are strictly used for +“bookkeeping” and are not used in subsequent steps.  Statistically generated +weather conditions for Cooperative Observer Weather Stations during the period +1980-2010 drive these simulations.  Future releases are expected to support +input of alternative sources of long-term weather information (i.e., 25 years +or more).  Figure 15 displays the tool interface used for the test_case +scenario.  Users can select one or more crops for the simulation.  After +clicking the Run button, a script file is generated to run the rain-fed and +irrigated EPIC spin-up simula­tions for each crop.  The user submits the script +file to the queue by clicking OK.  After the job has finished, users should +check the queue job and log file in the “scenario name”/scripts directory, +based on the information provided in the Message Box (shown in Figure 15). 

+ +

+ +

Figure 15. The EPIC +Runs for Spinup tool used for the test_case scenario.

+ +

Users need to make sure that the +following three fields are selected correctly:

+ +

·         +CO2 Level (ppm) - input the correct CO2 +level for the simulation (e.g. 380).  The input level overwrites the CO2 +level defined in EPICCONT.DAT and site file.

+ +

·         +Daily Average N Deposition – select N input to be used in +the simulation.  Users can select using 1) the values defined in EPIC input files, +2) daily average N input from 5-year CMAQ simulations from 2002 to 2006, or 3) daily +average N input from 5-year CMAQ simulations from 2006 to 2010.  The 5-year +CMAQ N daily input files are stored under ${FESTC_HOME}/epic/common_data/EPIC_model.  +Future releases will include daily average N input from 5-year CMAQ simulations +from 2011 to 2015.

+ +

·         +Run TileDrain – select whether tile drain is applied for +saturated soils.  If YES is selected, SOILLIST file under scenarios/“scenario +name”/“crop name”/spinup/manage/tileDrain will be used.  The tile drain +process is applied for all crops except hay (1, 2), alfalfa (3, 4), Other_Grass +(5, 6) and rice (23, 24).   

+ +

The tool generates many directories +and files for each crop.  The original EPIC output files are stored under the +two following subdirectories in the “scenario name”/“crop name”/spinup directory:

+ +

·         +rainf – contains output from EPIC rain-fed spin-up +simulations for this crop.

+ +

·         +irr – contains output from EPIC irrigated spin-up +simulations for this crop. 

+ +

In both cases, +soil files to be used in the EPIC application simulation are:

+ +

-        +SOL/“GRIDID”0“BELD3 Crop Number”.SOL 

+ +

The output data created for CMAQ +modeling are used primarily for QA purposes, and are stored under the following +two directories in the “scenario name”/output4CMAQ/spinup directory:

+ +

·         +5years – contains average EPIC output data from the last +five years of the spin-up simulations for the crops. 

+ +

·         +daily – stores daily EPIC output data from EPIC spin-up +runs for the crops simulated. 

+ +

6. EPIC Application Run Tools

+ +

After users +complete the EPIC simulations for spin-up, they can proceed to the EPIC +application run tools for the simulation (or application) year.  The spin-up +simulations need to be run only once for a given domain and grid resolution—in other +words, the initial conditions can be re-used for multiple application years. +The first step in running an EPIC application is to generate management files +for the application year (as described in Section 6.1).  The application +management program needs to be run only once for a given domain and grid +resolution; it is not year-specific.  The user can then run the EPIC model for +the application year (as described in Section 6.2) if the daily weather and N +deposition files for the scenario have already been generated using the tool described +in Section 4.3. 

+ +

6.1 +Management File Generation for Application

+ +

The Management +File Generation for Application tool interface is used to create (1) the +EPIC management files for each crop to be used in the EPIC application-year +modeling; and (2) the EPICRUN file for the rain-fed and irrigated simulations, +which contains the linkages for the statistical weather and wind files, the +soil files, and the management files for EPIC grid cells.  The tool uses the +FORTRAN programs ManGenFERT.exe and soildrain.exe stored under the ${FESTC_HOME}/ +epic/util/manageCreate directory with the common data files stored under ${FESTC_HOME} +/epic/common_data/util/manageCreate and many other data files generated +under each crop directory.  Figure 16 shows the tool interface used to generate +management files for the test_case scenario.  Users must make sure that +the following two entries are selected correctly:

+ +

·         +Fertilizer Year – select 2001 or 2006.  The common +management and fertilizer data sets created under the ${FESTC_HOME}/epic/common_data/util/manageCreate +will be used accordingly.  This management tool uses the created +fertilizer data types for the 10 crop production regions.  Fertilizer for 2011 +will be available in a future release. 

+ +

·         +Selected Crops – select one or more crops.

+ +

 

+ +

+ +

Figure 16. The Management +File Generation for Application tool interface used
+for the test_case scenario.

+ +

After clicking the Run button, a +script file is generated to compute the management files for the selected +crops.  The user submits the script file to the queue by clicking OK.  After +the job has finished, users should check the queue job and log file in the “scenario +name”/scripts directory, based on the information provided in the Message +Box (shown in Figure 16). 

+ +

 

+ +

The tool will generate many output +files under each crop (many of these are used just for verification). The tool +generates the following files under the “scenario name”/“crop name”/app/manage +directory:

+ +

·         +EPICRUNFILERAINDW.DAT – EPIC run file for rain-fed application +simulation.

+ +

·         +EPICRUNFILEIRRDW.DAT – EPIC run file for irrigated application +simulation.

+ +

·         +GRIDS_OPC.DAT – the list of management file names to be used in +EPIC modeling.

+ +

·         +OPC/“GRIDID”0“BELD3 Crop Number”.OPC – grid cell EPIC +management files under the OPC directory.  Table 1 in Section 4.1 lists +the crop numbers in the BELD data.

+ +

·         +tileDrain/SOILLIST.DAT – soil list file which contains +tile drain information for EPIC simulations and is used when “tileDrain” is +selected when running EPIC application simulations. 

+ +

6.2 +EPIC Runs for Application

+ +

The EPIC Runs +for Application tool interface is used to run the EPIC model for the +simulation year (EPICapp.exe program), which is stored under the directory ${FESTC_HOME}/epic/ +model/current.  Users must already have generated the site daily weather +and N deposition files using the WRF/CMAQ-to-EPIC tool interface (see +Section 4.3).  N deposition input can be selected from the four available +options – CMAQ, EPIC parameter input file, 2002-2006 5-year CMAQ average, +and 2006-2010 5-year CMAQ average. The tool uses input files stored primarily +in the following directories:

+ +

·         +${FESTC_HOME}/epic/common_data/EPIC_model/app – contains +the common model input files.

+ +

·         +scenarios/“scenario name”/share_data – contains the EPICCONT.DAT +file, site files, site list file, daily weather and N deposition files, and +weather list file. 

+ +

·         + ${FESTC_HOME}/epic/common_data/statWeath – contains observed +climate station statistical data.

+ +

·         +scenarios/“scenario name”/ “crop name” /app/manage – contains +the run files, management files, and management list file.

+ +

·         +scenarios/“scenario name”/ “crop name”/spinup/rainf/SOL – contains +the soil files to be used in the rain-fed simulations.

+ +

·         +scenarios/“scenario name”/ “crop name”/spinup/irr/SOL – contains +the soil files to be used in the irrigated simulations.

+ +

Figure 17 shows +the tool interface used for the test_case scenario.  The Simulation Year +is defined when the user creates the scenario.  Users can select one or +multiple crops for the simulation.  After clicking the Run button, a script +file is generated to run the rain-fed and irrigated EPIC application +simulations for each crop.  The EPIC application simulations will run for a two-year +period (the previous year and the simulation year) using the same daily weather +and N deposition files for the simulation year; the two-year period is needed to +simulate a full growing season for fall-sown crops. The user submits the script +file to the queue by clicking OK.  After the job has finished, users should +check the queue job and log file in the “scenario name”/scripts directory, +based on the information provided in the Message Box (shown in Figure 17). 

+ +

Users need to +make sure that the following three fields are selected correctly:

+ +

·         +CO2 Level (ppm) - input the correct CO2 +level for the simulation (e.g. 380).  The input level overwrites the CO2 +level defined in EPICCONT.DAT and site file.

+ +

·         +Daily Average N Deposition – select N input to be used in +the simulation.  Users can select using 1) the CMAQ N values in daily weather +files, 2) values defined in EPIC input files, 3) daily average N input from the +5-year CMAQ simulations from 2002 to 2006, or 4) daily average N input from the +5-year CMAQ simulations from 2006 to 2010.  The 5-year CMAQ N daily input files +are stored under ${FESTC_HOME}/epic/common_data/EPIC_model.  Future +releases will include daily average N input from 5-year CMAQ simulations from +2011 to 2015.

+ +

·         +Run TileDrain – select whether tile drain is applied for +saturated soils.  If YES is selected, SOILLIST file under scenarios/“scenario +name”/“crop name”/app/manage/tileDrain will be used.  The tile drain +process is applied for all crops except hay (1, 2), alfalfa (3, 4), Other_Grass +(5, 6) and rice (23, 24).   

+ +

 

+ +

+ +

Figure 17. The EPIC +Runs for Application tool interface used for the test_case scenario.

+ +

The tool generates many directories +and files for each crop.  The original EPIC output files are stored under the +following two subdirectories in the “scenario name”/“crop name”/app directory:

+ +

·         +rainf – contains output from EPIC rain-fed application +simulations for this crop. 

+ +

·         +irr – contains output from EPIC irrigated application +simulations for this crop. 

+ +

The output data created for CMAQ +modeling are stored under the following two subdirectories in the “scenario +name”/output4CMAQ/app directory:

+ +

·         +year – contains average EPIC output data for the +simulation year (one year) run for the crops simulated.  These data are used +primarily for QA purposes.

+ +

·         +daily – stores daily EPIC output data from EPIC +application runs for the crops simulated.  These data are used to extract the +input for CMAQ bidirectional NH3 modeling and SWAT simulations.

+ +

7. Output Processing and Visualizing Tools

+ +

EPIC is a field-based +model that generates output in formatted text files.  In the domain-based EPIC +modeling within FEST-C, the crops in each grid cell are modeled individually.  +Thus, there are many text output files generated for each crop in each grid +cell selected for EPIC modeling.  In this section we first describe the EPIC +Yearly Extraction tool and the EPIC-to-CMAQ tool. Developed in the +SA Raster Tools system, these two tools extract yearly or daily EPIC output +variables into NetCDF-format files for QA purposes and for CMAQ modeling.  We +then discuss the EPIC to SWAT tool which prepares SWAT input files from +EPIC output and WRF/CMAQ weather and N deposition NetCDF file using many R +codes.  The Visualization tool interface, which allows users to prepare +spatial views of the EPIC output variables in the created NetCDF files over +their modeling scenario domain, is presented last in this section. 

+ +

7.1 +EPIC Yearly Extraction

+ +

The EPIC +Yearly Extraction tool is used to extract 48 crop-specific variables and 39 +crop-area-weighted variables into two NetCDF files from the yearly average EPIC +output files for all simulated crops within the grid cells that were selected.  +The output from this tool is used primarily for QA purposes, to make sure that the +EPIC simulation results appear to be spatially reasonable over the domain +area.  Figure 18 shows the tool interface used for the test_case +scenario.  The only item users need to select is an “Output Type”:

+ +

·         +EPIC SPINUP – select this to extract yearly average +variables from the EPIC spin-up simulations. Yearly average variables from the +last five years of the simulations are from the output stored under the “scenario +name”/output4CMAQ/spinup/5years directory. 

+ +

·         +EPIC APP – select this to extract yearly average variables +from the EPIC simulations for the application year.  The yearly average +variables are from the output stored under the “scenario +name”/output4CMAQ/app/year directory.   

+ +

 

+ +

+ +

Figure 18.  The EPIC +Yearly Extraction tool interface used for the test_case scenario.

+ +

Table 4 lists all variables that +are in the two EPIC output files created by the tool:  epic2cmaq_year.nc +(crop-specific output) and epic2cmaq_year_total.nc (crop-weighted output). +These files are stored in one of the following two directories:

+ +

·         +scenarios/“scenario name”/output4CMAQ/spinup/toCMAQ – if +the EPIC SPINUP output type is selected.

+ +

·         +scenarios/“scenario name”/output4CMAQ/app/toCMAQ – if the +EPIC APP output type is selected.

+ +

 

+ +

Users should check the log file +under their scenario’s scripts directory to see whether any errors +occurred when the tool was run.  If the user is visualizing the data using the +VERDI tool for visualization, there is no time dimension.  Data layers are assigned +to individual crops (see Table 1 in Section 4.1 for the BELD crop numbers). 

+ +

Table 4. EPIC yearly extraction output variables.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

epic2cmaq_year.nc - crop specific output

+
+

 

+
+

 

+
+

 

+
+

Index

+
+

Name

+
+

Variable

+
+

Index

+
+

Name

+
+

Variable

+
+

1

+
+

GMN

+
+

N Mineralized (kg/ha)

+
+

25

+
+

FTP

+
+

P Applied (kg/ha)

+
+

2

+
+

NMN

+
+

Humus Mineralization (kg/ha)

+
+

26

+
+

IRGA*

+
+

Irrigation Volume Applied (mm)

+
+

3

+
+

NFIX

+
+

N Fixation (kg/ha)

+
+

27

+
+

WS

+
+

Water Stress Days (days)

+
+

4

+
+

NITR

+
+

N - Nitrified NH3 (kg/ha)

+
+

28

+
+

NS

+
+

N Stress Days (days)

+
+

5

+
+

AVOL

+
+

N - Volatilization (kg/ha)

+
+

29

+
+

IPLD

+
+

Planting Date (Julian Date)

+
+

6

+
+

DN

+
+

N-NO3 Denitrification (kg/ha)

+
+

30

+
+

IGMD

+
+

Germination Date (Julian Date)

+
+

7

+
+

YON

+
+

N Loss with Sediment (kg/ha)

+
+

31

+
+

IHVD

+
+

Harvest Date (Julian Date)

+
+

8

+
+

QNO3

+
+

N Loss in Surface Runoff + (kg/ha)

+
+

32

+
+

YP

+
+

P Loss with Sediment (kg/ha)

+
+

9

+
+

SSFN

+
+

N in Subsurface Flow (kg/ha)

+
+

33

+
+

QAP

+
+

Labile P Loss in Runoff (kg/ha)

+
+

10

+
+

PRKN

+
+

N Loss in Percolate (kg/ha)

+
+

34

+
+

YW

+
+

Wind Erosion (ton/ha)

+
+

11

+
+

FNO

+
+

N - Organic Fertilizer (kg/ha)

+
+

35

+
+

Q*

+
+

Runoff (mm)

+
+

12

+
+

FNO3

+
+

N - Nitrate Fertilize (kg/ha)

+
+

36

+
+

SSF

+
+

Subsurface flow (mm)

+
+

13

+
+

FNH3

+
+

N - Ammonia Fertilize (kg/ha)

+
+

37

+
+

PRK

+
+

Percolation (mm)

+
+

14

+
+

OCPD

+
+

Organic Carbon in Plow Layer + (mt/ha)

+
+

38

+
+

PRCP

+
+

Rainfall (mm)

+
+

15

+
+

TOC

+
+

Organic Carbon in Soil Profile + (mt/ha)

+
+

39

+
+

PET

+
+

Potential Evapotranspiration + (mm)

+
+

16

+
+

TNO3

+
+

Total NO3 in Soil Profile + (kg/ha)

+
+

40

+
+

ET

+
+

Evapotranspiration (mm)

+
+

      17

+
+

DN2

+
+

N-N2O from NO3 Denitrification + (kg/ha)

+
+

41

+
+

QDRN

+
+

Drain Tile Flow (mm)

+
+

18

+
+

YLDG

+
+

Grain Yield (t/ha)

+
+

42

+
+

MUSL

+
+

Water erosion (ton/ha)

+
+

19

+
+

T_YLDG

+
+

T - Grain Yield (1000ton)

+
+

43

+
+

DRNN

+
+

Nitrogen in drain tile flow (kg/ha)

+
+

20

+
+

YLDF

+
+

Forage Yield (t/ha)

+
+

44

+
+

DRNP

+
+

P in Drain Tile Flow (kg/ha)

+
+

21

+
+

T_YLDF

+
+

T - Forage Yield (1000ton)

+
+

45

+
+

PRKP

+
+

P in Percolation (kg/ha)

+
+

22

+
+

YLN

+
+

N Used by Crop (kg/ha)

+
+

46

+
+

FPO

+
+

Organic P Fertilizer (kg/ha)

+
+

23

+
+

YLP

+
+

P Used by Crop (kg/ha)

+
+

47

+
+

FPL

+
+

Labile P Fertilizer (kg/ha)

+
+

24

+
+

FTN

+
+

N Applied (kg/ha)

+
+

48

+
+

MNP

+
+

P Mineralized (kg/ha)

+
+

 

+
+

 

+
+

 

+
+

 

+
+

 

+
+

 

+
+

epic2cmaq_year_total.nc - crop weighted + output

+
+

 

+
+

 

+
+

 

+
+

Index

+
+

Name

+
+

Variable

+
+

Index

+
+

Name

+
+

Variable

+
+

1

+
+

T_GMN

+
+

N Mineralized (mt - metric ton)

+
+

21

+
+

T_FTP

+
+

P Applied (mt)

+
+

2

+
+

T_NMN

+
+

Humus Mineralization (mt)

+
+

22

+
+

T_IRGA*

+
+

Irrigation Volume Applied (mm)

+
+

3

+
+

T_NFIX

+
+

N Fixation (mt)

+
+

23

+
+

T_YP

+
+

T - P Loss with Sediment (mt)

+
+

4

+
+

T_NITR

+
+

N - Nitrified NH3 (mt)

+
+

24

+
+

T_QAP

+
+

T - Labile P Loss in Runoff + (mt)

+
+

5

+
+

T_AVOL

+
+

N - Volatilization (mt)

+
+

25

+
+

T_YW

+
+

T - Wind Erosion (1000ton)

+
+

6

+
+

T_DN

+
+

N-NO3 Denitrification (mt)

+
+

26

+
+

T_Q*

+
+

T - Runoff (mm)

+
+

7

+
+

T_YON

+
+

N Loss with Sediment (mt)

+
+

27

+
+

T_SSF

+
+

T - Subsurface flow (mm)

+
+

8

+
+

T_QNO3

+
+

N Loss in Surface Runoff (mt)

+
+

28

+
+

T_PRK

+
+

T - Percolation (mm)

+
+

9

+
+

T_SSFN

+
+

N in Subsurface Flow (mt)

+
+

29

+
+

T_PRCP

+
+

T - Rainfall (mm)

+
+

10

+
+

T_PRKN

+
+

N Loss in Percolate (mt)

+
+

30

+
+

T_PET

+
+

T - Potential + Evapotranspiration (mm)

+
+

11

+
+

T_FNO

+
+

N - Organic Fertilizer (mt)

+
+

31

+
+

T_ET

+
+

T - Evapotranspiration (mm)

+
+

12

+
+

T_FNO3

+
+

N - Nitrate Fertilizer (mt)

+
+

32

+
+

T_QDRN

+
+

T - Drain Tile Flow (mm)

+
+

13

+
+

T_FNH3

+
+

N - Ammonia Fertilizer (mt)

+
+

33

+
+

T_MUSL

+
+

T - Water erosion (ton/ha)

+
+

14

+
+

T_OCPD

+
+

Organic Carbon in Plow Layer + (1000mt)

+
+

34

+
+

T_DRNN

+
+

T – N in drain tile flow + (kg/ha)

+
+

15

+
+

T_TOC

+
+

Organic Carbon in Soil Profile + (1000mt)

+
+

35

+
+

T_DRNP

+
+

T - P in Drain Tile Flow + (kg/ha)

+
+

16

+
+

T_TNO3

+
+

Total NO3 in Soil Profile (mt)

+
+

36

+
+

T_PRKP

+
+

T - P in Percolation (kg/ha)

+
+

17

+
+

T_DN2

+
+

N-N2O from NO3 Denitrification + (mt)

+
+

37

+
+

T_FPO

+
+

T - Organic P Fertilizer + (kg/ha)

+
+

18

+
+

T_YLN

+
+

N Used by Crop (mt)

+
+

38

+
+

T_FPL

+
+

T - Labile P Fertilizer (kg/ha)

+
+

19

+
+

T_YLP

+
+

P Used by Crop (mt)

+
+

39

+
+

T_MNP

+
+

T - P Mineralized (kg/ha)

+
+

20

+
+

T_FTN

+
+

N Applied (mt)

+
+

 

+
+

 

+
+

 

+
+ +
+ +

*Water +on agricultural lands.

+ +

7.2 +EPIC to CMAQ

+ +

The EPIC to CMAQ +tool is used to extract 13 variables from EPIC soil output files and 41 +variables from EPIC daily output files into NetCDF files for all simulated +crops within the grid cells that were selected.  The output from this tool is +used as input to CMAQ bidirectional NH3 modeling over the domain +area.  Figure 19 shows the tool interface used for the test_case +scenario. 

+ +

The user needs to +input the following two items:

+ +

·         +Output File Prefix – this is used as the file prefix for +all of the NetCDF output file names

+ +

·         +Output Type – select “EPIC SPINUP” to extract +yearly average variables from the EPIC spin-up simulations under the “scenario +name”/output4CMAQ/spinup/5years directory and “EPIC APP” to extract +yearly average variables from the EPIC simulations for the application year +under the “scenario name”/output4CMAQ/app/year directory.   

+ +

The following output files produced +by the tool are stored under the scenarios/“scenario +name”/output4CMAQ/app/toCMAQ directory:

+ +

·         +Output File Prefix”_soil.nc – soil output file that +contains 13 soil variables extracted from the EPIC soil output files (“scenario +name”/output4CMAQ /app/daily/“BELD4 Crop Number”.NCS); these variables are +listed in Table 5.  L1 and L2 are for the soil depth from 0 to 1 cm and from 1 cm +to 10 cm, respectively. 

+ +

·         +Output File Prefix”_timeYYYYMMDD.nc – daily NetCDF files +for the simulation year.  A daily NetCDF file contains 41 variables extracted +from the EPIC daily output files (e.g. “scenario name”/output4CMAQ +/app/daily/“BELD4 Crop Number”.NCD”); these variables are listed in Table 6.  +L1, L2, and T1 are for the soil depth from 0 to 1 cm, from 1 cm to 10 cm, +and from 0 cm to the full Baumer soil profile depth, which can be more than +1 m.   

+ +

 

+ +

+ +

Figure +19. The EPIC to CMAQ tool interface used for the test_case +scenario.

+ +

 

+ +

Table 5. EPIC to CMAQ soil output variables

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Index

+
+

Name

+
+

Soil + Variable

+
+

Index

+
+

Name

+
+

Soil + Variable

+
+

1

+
+

L1_SoilNum

+
+

Soil Number (none)

+
+

8

+
+

L2_Bulk_D

+
+

Layer2 Bulk Density (t/m**3)

+
+

2

+
+

L1_Bulk_D

+
+

Layer1 Bulk Density (t/m**3)

+
+

9

+
+

L2_Wilt_P

+
+

Layer2 Wilting Point (m/m)

+
+

3

+
+

L1_Wilt_P

+
+

Layer1 Wilting Point(m/m)

+
+

10

+
+

 L2_Field_C

+
+

Layer2 Field Capacity (m/m)

+
+

4

+
+

L1_Field_C

+
+

Layer1 Field Capacity (m/m)

+
+

11

+
+

L2_Porosity

+
+

Layer2 Porosity (%)

+
+

5

+
+

L1_Porosity

+
+

Layer1 Porosity (%)

+
+

12

+
+

L2_PH

+
+

Layer2 PH (none)

+
+

6

+
+

L1_PH

+
+

Layer1 PH (none)

+
+

13

+
+

L2_Cation

+
+

Layer2 Cation Ex (cmol/kg)

+
+

7

+
+

L1_Cation

+
+

Layer1 Cation Ex (cmol/kg)

+
+

 

+
+

 

+
+

 

+
+ +
+ +

 

+ +

 

+ +

Table 6. EPIC to CMAQ daily output variables

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Index

+
+

Name

+
+

Variable

+
+

Index

+
+

Name

+
+

Variable

+
+

1

+
+

DN

+
+

N-NO3 Denitrification (kg/ha)

+
+

22

+
+

L2_NH3

+
+

Layer2 N - Ammonia (kg/ha)

+
+

2

+
+

DN2

+
+

N-N2O from NO3 Denitrification + (kg/ha)

+
+

23

+
+

L2_ON

+
+

Layer2 Organic N (kg/ha)

+
+

3

+
+

HMN

+
+

OC Change by Soil Respiration + (kg/ha)

+
+

24

+
+

L2_C

+
+

Layer2 Carbon (kg/ha)

+
+

4

+
+

NFIX

+
+

N Fixation (kg/ha)

+
+

25

+
+

L2_NITR

+
+

Layer2 N - Nitrified NH3 + (kg/ha)

+
+

5

+
+

GMN

+
+

N Mineralized (kg/ha)

+
+

26

+
+

T1_DEP

+
+

Layert Depth (m)

+
+

6

+
+

YW

+
+

Wind Erosion (ton/ha)

+
+

27

+
+

T1_BD

+
+

Layert Bulk Density (t/m**3)

+
+

7

+
+

FPO

+
+

Organic P Fertilizer (kg/ha)

+
+

28

+
+

T1_NO3

+
+

Layert N - Nitrate (kg/ha)

+
+

8

+
+

FPL

+
+

Labile P Fertilizer (kg/ha)

+
+

29

+
+

T1_NH3

+
+

Layert N - Ammonia (kg/ha)

+
+

9

+
+

MNP

+
+

P Mineralized (kg/ha)

+
+

30

+
+

T1_ON

+
+

Layert Organic N (kg/ha)

+
+

10

+
+

L1_DEP

+
+

Layer1 Depth (m)

+
+

31

+
+

T1_C

+
+

Layert Carbon (kg/ha)

+
+

11

+
+

L1_BD

+
+

Layer1 Bulk Density (t/m**3)

+
+

32

+
+

T1_NITR

+
+

Layert N - Nitrified NH3 + (kg/ha)

+
+

12

+
+

L1_SW

+
+

Layer 1 Soil Moisture (mm)

+
+

33

+
+

L1_ANO3

+
+

Layer1 N-NO3 AppRate (kg/ha)

+
+

13

+
+

L1_NO3

+
+

Layer1 N - Nitrate (kg/ha)

+
+

34

+
+

L1_ANH3

+
+

Layer1 N-NH3 AppRate (kg/ha)

+
+

14

+
+

L1_NH3

+
+

Layer1 N - Ammonia (kg/ha)

+
+

35

+
+

L1_AON

+
+

Layer1 ON AppRate (kg/ha)

+
+

15

+
+

 L1_ON

+
+

Layer1 Organic N (kg/ha)

+
+

36

+
+

L2_ANO3

+
+

Layer2 N-NO3 AppRate (kg/ha)

+
+

16

+
+

L1_C

+
+

Layer1 Carbon (kg/ha)

+
+

37

+
+

L2_ANH3

+
+

Layer2 N-NH3 AppRate (kg/ha)

+
+

17

+
+

L1_NITR

+
+

Layer1 N - Nitrified NH3 + (kg/ha)

+
+

38

+
+

L2_AON

+
+

Layer2 ON AppRate (kg/ha)

+
+

18

+
+

L2_DEP

+
+

Layer2 Depth (m)

+
+

39

+
+

LAI

+
+

Leaf Area Index (none)

+
+

19

+
+

L2_BD

+
+

Layer2 Bulk Density (t/m**3)

+
+

40

+
+

CPHT

+
+

Crop Height (m)

+
+

20

+
+

L2_SW

+
+

Layer 2 Soil Moisture (mm)

+
+

41

+
+

FBARE

+
+

Bare Land Fraction for Wind + Erosion (Fraction)

+
+

21

+
+

L2_NO3

+
+

Layer2 N - Nitrate (kg/ha)

+
+

 

+
+

 

+
+

 

+
+

Note: + EPIC is a daily time step model while the CMAQ bidirectional NH3 + flux model is at a time scale which could be less than 10 minutes. 

+
+ +
+ +

 

+ +

When the user clicks the Run +button, a script file is generated under the scenario’s scripts directory.  +The script file is submitted to the queue for execution after the user clicks +OK.  A CMAQ-ready file is generated for each day and is viewable in VERDI.  After +the queue job has completed, users should check the log file under the scripts +directory to see whether any errors occurred during execution.

+ +

7.3 +EPIC to SWAT

+ +

 

+ +

The EPIC to SWAT tool is used +to extract EPIC output and WRF/CMAQ weather and N deposition data for SWAT +simulations in 8-digit HUC watersheds defined by users.  “EPIC”, “NDEP”, and “DailyWETH” +are tools which users can click in any order to aggregate EPIC daily output and +N deposition and weather data in CMAQ grid format into the different areas listed.  +After aggregated EPIC, N deposition, and weather files are created, users can +click “SWAT INPUTS” to generate SWAT-ready input files.  The output from +“SWAT INPUTS” can be used by SWAT modelers to replace default or “traditional” +SWAT weather, atmospheric deposition and agricultural land nutrient and runoff input.  + Figure 20 shows the tool interface which is used for the test_case +scenario.  Users need to make sure that the following fields are filled and selected +correctly:

+ +

·         +HUC8 Delivery Ratio File – EPIC to SWAT integration file.  +This text file contains SWAT 8-digit HUC watershed information with average +delivery ratios from EPIC edge-of-field output to SWAT watershed output.  Users +can view the delivery ratio file – “test_case/share_data/subbasins-mapping_test_case.csv” +included for the test_case scenario for items and format required.

+ +

·         +Daily Average N Deposition – select the source of N +deposition for SWAT extraction.  Users can select CMAQ application year N +deposition or one of the 5-year average CMAQ N deposition. 

+ +

·         +Area Selection – select area for generating SWAT-ready +input files by the “SWAT INPUTS” button.  The current system only works for +8-digit HUC SWAT input file generation regardless of which area is selected.  +The “EPIC”, “NDEP”, and DailyWETH” extraction buttons will generate aggregated +data for all areas listed.

+ +

 

+ +

+ +

Figure 20. The +EPIC to SWAT interface.

+ +

The button tools with descriptions +in this subinterface are:

+ +

·         +EPIC – aggregate the daily variables +required by SWAT (Table 7) from EPIC application run output to all areas listed +on the interface (Domain, State, County, HUC8, HUC6, and HUC2).  This tool uses +the R program epic2swat_extract_dailyEPIC.R stored under ${FESTC_HOME}/epic/util/swat. + After clicking the EPIC button, a script file is generated to run the program +using all information defined by environment variables.  The user submits the +script file to the queue by clicking OK.  After the job is finished, users +should check the queue job and log file in the “scenario name”/scripts +directory, based on the information provided in the Message Box (shown in +Figure 20).  The output files from the tool are stored under the sub-directories +with corresponding area names in the “scenario name”/output4SWAT/dailyEPIC directory.   +  

+ +
+
+ +

 

+ +

Table 7. Conversion of EPIC +daily output to SWAT point source input

+ +

 

+ +

+ +

Notes: Area is for the crop area in a specific +grid.  is the summation for all grids +in a region (e.g. HUC8).

+ +

 

+ +

 

+ +

·         +NDEP - aggregate daily N deposition variables required by +SWAT (Table 8) from daily deposition NetCDF file generated from CMAQ to all +areas listed on the interface (Domain, State, County, HUC8, HUC6, and HUC2).  This +tool uses the R program epic2swat_extract_daily_ndepCMAQ.R stored under ${FESTC_HOME}/epic/util/swat.  +After clicking the NDEP button, a script file is generated to run the program +using all information defined by environment variables.  The user submits the +script file to the queue by clicking OK.  After the job is finished, users +should check the queue job and log file in the “scenario name”/scripts +directory, based on the information provided in the Message Box (shown in +Figure 20).  The output files from the tool are stored under the sub-directories +with corresponding area names in the “scenario name”/output4SWAT/NDEP directory.   +  

+ +

 

+ +
+
+ +

 

+ +

Table 8. CMAQ N Deposition +to SWAT

+ +

 

+ +

+ +

Note: N is the total +number of grid cells in a specific region (e.g. HUC8).

+ +

 

+ +

·         +DailyWETH - aggregate +daily weather variables required by SWAT (Table 9) from daily weather NetCDF +file generated from WRF to all areas listed on the interface (Domain, State, +County, HUC8, HUC6, and HUC2).  This tool uses the R program epic2swat_extract_daily_metCMAQ.R +stored under ${FESTC_HOME}/epic/util/swat.  After clicking the DailyWETH +button, a script file is generated to run the program using all information +defined by environment variables.  The user submits the script file to the +queue by clicking OK.  After the job is finished, users should check the queue +job and log file in the “scenario name”/scripts directory, based on the +information provided in the Message Box (shown in Figure 20).  The output files +from the tool are stored under the sub-directories with corresponding area +names in the “scenario name”/output4SWAT/dailyWETH directory.     

+ +

 

+ +
+
+ +

 

+ +

Table 9. WRF daily weather to +SWAT  

+ +

 

+ +

+ +

Note: N is the total +number of grid cells in a specific region (e.g. HUC8).

+ +

 

+ +

 

+ +

·         +SWAT INPUTS – generate SWAT-ready input files from aggregated +daily EPIC, weather, and N deposition files by the previous three button tools +for the watersheds specified in the “HUC8 Delivery Ratio File” field.  This +tool calls the R program extract_swatInputs.R stored under ${FESTC_HOME}/epic/util/swat.  +After clicking the “SWAT INPUTS” button, a script file is generated to run the program +using all information defined by environment variables.  The user submits the +script file to the queue by clicking OK.  After the job is finished, users +should check the queue job and log file in the “scenario name”/scripts +directory, based on the information provided in the Message Box (shown in +Figure 20).  The output files from the tool are stored under the +sub-directories for EPIC, weather, and N deposition individually in the “scenario +name”/output4SWAT/swat_inputs directory.

+ +

7.4 Visualization

+ +

The Visualization +tool interface is used to invoke the VERDI interface to view a selected NetCDF +data set.  Figure 21 shows the appearance of the tool interface before an input +file has been selected.  Users can select the data type on the left side of the +interface window and then by browse through the file systems to select a NetCDF +file created or used within the FEST-C system (e.g., an EPIC output NetCDF file +created by the previous two tools, a BELD4 data set, MCIP and CMAQ data sets, a +daily weather and N deposition NetCDF output file).  Clicking the Display button +invokes the VERDI interface to visualize the selected NetCDF file.  Note: +For this to work properly, the user has to have set the VERDI system in the +FEST-C configuration file config.properties (see Section 1.3).  +Information on how to use the VERDI system can be obtained from the CMAS VERDI +site: http://www.cmascenter.org/verdi/.  +

+ +

+ +

Figure 21. The +Visualization tool interface.

+ +

8. Future Work

+ +

In this release, +2011 NLCD/MODIS data is available to produce crop fractions for Canada and the +US.  To accompany this data, a future release will include an updated +fertilizer type scenario for 2011.  In addition, we will continue to improve +the crop fraction coverage with the upcoming NLCD 2016 release using the USDA +2017 census data and corresponding crop census data for Canada and Mexico.  We +are continuing our efforts to improve the C-N-P budgets within this systems for +different crops.  We are also exploring the possibility of moving to computing +crop land use data directly from USDA National Agricultural Statistics Service (NASS) +Cropland Data Layer (CDL) data.  This would provide higher-resolution crop +spatial information, however, CDL data do not include some information that is +critical for FEST-C EPIC (such as differentiation between irrigated and +rain-fed crops).  Thus, further exploration on using this data set in +combination with other irrigation data is needed.

+ +

 

+ +
+ + + + diff --git a/festc_bootstrap/help/userManual_files/colorschememapping.xml b/festc_bootstrap/help/userManual_files/colorschememapping.xml index b200daa..6a0069c 100644 --- a/festc_bootstrap/help/userManual_files/colorschememapping.xml +++ b/festc_bootstrap/help/userManual_files/colorschememapping.xml @@ -1,2 +1,2 @@ - + \ No newline at end of file diff --git a/festc_bootstrap/help/userManual_files/filelist.xml b/festc_bootstrap/help/userManual_files/filelist.xml index 365475c..68c1f15 100644 --- a/festc_bootstrap/help/userManual_files/filelist.xml +++ b/festc_bootstrap/help/userManual_files/filelist.xml @@ -1,57 +1,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/festc_bootstrap/help/userManual_files/header.htm b/festc_bootstrap/help/userManual_files/header.htm index 269de6e..ba848a7 100644 --- a/festc_bootstrap/help/userManual_files/header.htm +++ b/festc_bootstrap/help/userManual_files/header.htm @@ -1,483 +1,483 @@ - - - - - - - - - - - - - -
- -

- -


- -

- -
- -
- -

- -


- -

- -
- -
- -

- -


- -

- -
- -
- -

- -


- -

- -
- -
- -

FEST-C v1.3 and 2.0 User’s Guide

- -
- -
- -

UNC–Chapel Hill                                                                52                                                               Institute for the -Environment

- -
- -
- -

- -
- -
- -
- - - - - -
-

      

-
- -
- -
- -
- -

Draft - Do Not Cite

- -
- - - - + + + + + + + + + + + + + +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

FEST-C v1.3 and 2.0 User’s Guide

+ +
+ +
+ +

UNC–Chapel Hill                                                                52                                                               Institute for the +Environment

+ +
+ +
+ +

+ +
+ +
+ +
+ + + + + +
+

      

+
+ +
+ +
+ +
+ +

Draft - Do Not Cite

+ +
+ + + + diff --git a/festc_bootstrap/help/userManual_files/props056.xml b/festc_bootstrap/help/userManual_files/props056.xml index c9b8bb6..8196ca7 100644 --- a/festc_bootstrap/help/userManual_files/props056.xml +++ b/festc_bootstrap/help/userManual_files/props056.xml @@ -1,2 +1,2 @@ - + \ No newline at end of file diff --git a/festc_bootstrap/lib/c2dm.jar b/festc_bootstrap/lib/c2dm.jar new file mode 100644 index 0000000..1075f51 Binary files /dev/null and b/festc_bootstrap/lib/c2dm.jar differ diff --git a/festc_bootstrap/lib/jaxb-api-2.3.0.jar b/festc_bootstrap/lib/jaxb-api-2.3.0.jar new file mode 100644 index 0000000..0817c08 Binary files /dev/null and b/festc_bootstrap/lib/jaxb-api-2.3.0.jar differ diff --git a/festc_bootstrap/lib/jgoodies.jar b/festc_bootstrap/lib/jgoodies.jar new file mode 100644 index 0000000..5cc43a7 Binary files /dev/null and b/festc_bootstrap/lib/jgoodies.jar differ diff --git a/festc_bootstrap/lib/log4j-1.2-api-2.0-rc1.jar b/festc_bootstrap/lib/log4j-1.2-api-2.0-rc1.jar deleted file mode 100644 index 5353055..0000000 Binary files a/festc_bootstrap/lib/log4j-1.2-api-2.0-rc1.jar and /dev/null differ diff --git a/festc_bootstrap/lib/log4j-1.2-api-2.22.1.jar b/festc_bootstrap/lib/log4j-1.2-api-2.22.1.jar new file mode 100644 index 0000000..de57f34 Binary files /dev/null and b/festc_bootstrap/lib/log4j-1.2-api-2.22.1.jar differ diff --git a/festc_bootstrap/lib/log4j-api-2.0-rc1.jar b/festc_bootstrap/lib/log4j-api-2.0-rc1.jar deleted file mode 100644 index a8b9261..0000000 Binary files a/festc_bootstrap/lib/log4j-api-2.0-rc1.jar and /dev/null differ diff --git a/festc_bootstrap/lib/log4j-api-2.22.1.jar b/festc_bootstrap/lib/log4j-api-2.22.1.jar new file mode 100644 index 0000000..b77e55e Binary files /dev/null and b/festc_bootstrap/lib/log4j-api-2.22.1.jar differ diff --git a/festc_bootstrap/lib/log4j-core-2.0-rc1.jar b/festc_bootstrap/lib/log4j-core-2.0-rc1.jar deleted file mode 100644 index 5a9f29a..0000000 Binary files a/festc_bootstrap/lib/log4j-core-2.0-rc1.jar and /dev/null differ diff --git a/festc_bootstrap/lib/log4j-core-2.22.1.jar b/festc_bootstrap/lib/log4j-core-2.22.1.jar new file mode 100644 index 0000000..0be3f1f Binary files /dev/null and b/festc_bootstrap/lib/log4j-core-2.22.1.jar differ diff --git a/festc_bootstrap/lib/plugin.xml b/festc_bootstrap/lib/plugin.xml index 00e5a6c..0eff73e 100644 --- a/festc_bootstrap/lib/plugin.xml +++ b/festc_bootstrap/lib/plugin.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/festc_bootstrap/src/gov/epa/festc/boot/FestcClassLoader.java b/festc_bootstrap/src/gov/epa/festc/boot/FestcClassLoader.java index 132d97d..20621c2 100644 --- a/festc_bootstrap/src/gov/epa/festc/boot/FestcClassLoader.java +++ b/festc_bootstrap/src/gov/epa/festc/boot/FestcClassLoader.java @@ -1,56 +1,56 @@ -package gov.epa.festc.boot; - -import java.security.AllPermission; -import java.security.CodeSource; -import java.security.PermissionCollection; -import java.security.Permissions; - -import org.java.plugin.PluginManager; -import org.java.plugin.registry.PluginDescriptor; -import org.java.plugin.standard.StandardPluginClassLoader; - -/** - * Classloader used by FEST-C. This extends jpf's StandardPluginClassLoader - * but overrides getPermissions to return all permissions. This allows jpf to - * work with webstart. - * - * @author IE, UNC - * @version $Revision$ $Date$ - */ - -public class FestcClassLoader extends StandardPluginClassLoader { - - public FestcClassLoader(PluginManager pluginManager, PluginDescriptor pluginDescriptor, ClassLoader classLoader) { - super(pluginManager, pluginDescriptor, classLoader); - } - - - /** - * Returns the permissions for the given codesource object. - * The implementation of this method first calls super.getPermissions - * and then adds permissions based on the URL of the codesource. - *

- * If the protocol of this URL is "jar", then the permission granted - * is based on the permission that is required by the URL of the Jar - * file. - *

- * If the protocol is "file" - * and the path specifies a file, then permission to read that - * file is granted. If protocol is "file" and the path is - * a directory, permission is granted to read all files - * and (recursively) all files and subdirectories contained in - * that directory. - *

- * If the protocol is not "file", then - * to connect to and accept connections from the URL's host is granted. - * - * @param codesource the codesource - * @return the permissions granted to the codesource - */ - @Override - protected PermissionCollection getPermissions(CodeSource codesource) { - Permissions permissions = new Permissions(); - permissions.add(new AllPermission()); - return permissions; - } -} +package gov.epa.festc.boot; + +import java.security.AllPermission; +import java.security.CodeSource; +import java.security.PermissionCollection; +import java.security.Permissions; + +import org.java.plugin.PluginManager; +import org.java.plugin.registry.PluginDescriptor; +import org.java.plugin.standard.StandardPluginClassLoader; + +/** + * Classloader used by FEST-C. This extends jpf's StandardPluginClassLoader + * but overrides getPermissions to return all permissions. This allows jpf to + * work with webstart. + * + * @author IE, UNC + * @version $Revision$ $Date$ + */ + +public class FestcClassLoader extends StandardPluginClassLoader { + + public FestcClassLoader(PluginManager pluginManager, PluginDescriptor pluginDescriptor, ClassLoader classLoader) { + super(pluginManager, pluginDescriptor, classLoader); + } + + + /** + * Returns the permissions for the given codesource object. + * The implementation of this method first calls super.getPermissions + * and then adds permissions based on the URL of the codesource. + *

+ * If the protocol of this URL is "jar", then the permission granted + * is based on the permission that is required by the URL of the Jar + * file. + *

+ * If the protocol is "file" + * and the path specifies a file, then permission to read that + * file is granted. If protocol is "file" and the path is + * a directory, permission is granted to read all files + * and (recursively) all files and subdirectories contained in + * that directory. + *

+ * If the protocol is not "file", then + * to connect to and accept connections from the URL's host is granted. + * + * @param codesource the codesource + * @return the permissions granted to the codesource + */ + @Override + protected PermissionCollection getPermissions(CodeSource codesource) { + Permissions permissions = new Permissions(); + permissions.add(new AllPermission()); + return permissions; + } +} diff --git a/festc_bootstrap/src/gov/epa/festc/boot/FestcLifecycleHandler.java b/festc_bootstrap/src/gov/epa/festc/boot/FestcLifecycleHandler.java index 886f805..c0c2d22 100644 --- a/festc_bootstrap/src/gov/epa/festc/boot/FestcLifecycleHandler.java +++ b/festc_bootstrap/src/gov/epa/festc/boot/FestcLifecycleHandler.java @@ -1,23 +1,23 @@ -package gov.epa.festc.boot; - -import org.java.plugin.PluginClassLoader; -import org.java.plugin.registry.PluginDescriptor; -import org.java.plugin.standard.StandardPluginLifecycleHandler; - -import simphony.util.messages.MessageCenter; - -/** - * LifecycleHandler that creates PavePluginClassLoaders. - * - * @author IE, UNC - * @version $Revision$ $Date$ - */ -public class FestcLifecycleHandler extends StandardPluginLifecycleHandler { - - private static final MessageCenter msgCenter = MessageCenter.getMessageCenter(FestcLifecycleHandler.class); - - protected PluginClassLoader createPluginClassLoader(PluginDescriptor descriptor) { - msgCenter.debug("Creating class loader"); - return new FestcClassLoader(getPluginManager(), descriptor, getClass().getClassLoader()); - } -} +package gov.epa.festc.boot; + +import org.java.plugin.PluginClassLoader; +import org.java.plugin.registry.PluginDescriptor; +import org.java.plugin.standard.StandardPluginLifecycleHandler; + +import simphony.util.messages.MessageCenter; + +/** + * LifecycleHandler that creates PavePluginClassLoaders. + * + * @author IE, UNC + * @version $Revision$ $Date$ + */ +public class FestcLifecycleHandler extends StandardPluginLifecycleHandler { + + private static final MessageCenter msgCenter = MessageCenter.getMessageCenter(FestcLifecycleHandler.class); + + protected PluginClassLoader createPluginClassLoader(PluginDescriptor descriptor) { + msgCenter.debug("Creating class loader"); + return new FestcClassLoader(getPluginManager(), descriptor, getClass().getClassLoader()); + } +} diff --git a/festc_bootstrap/ui.properties b/festc_bootstrap/ui.properties index 5edee0e..1d17b6f 100644 --- a/festc_bootstrap/ui.properties +++ b/festc_bootstrap/ui.properties @@ -1,9 +1,9 @@ -# menu order -- elements are menu ids, or menu labels, sub menus are not -# supported yet -menu.order=File, Plots, Window, Help - -# toolbar group order. "," separates groups but does NOT insert a -# toolbar separator. ":" separates groups and does insert a separator -toolbar.group.order= file : window : runGraph, anl.verdi.core.bar.formula_group - - +# menu order -- elements are menu ids, or menu labels, sub menus are not +# supported yet +menu.order=File, Plots, Window, Help + +# toolbar group order. "," separates groups but does NOT insert a +# toolbar separator. ":" separates groups and does insert a separator +toolbar.group.order= file : window : runGraph, anl.verdi.core.bar.formula_group + + diff --git a/festc_core/.project b/festc_core/.project index 68a6dc2..8ac7f5b 100644 --- a/festc_core/.project +++ b/festc_core/.project @@ -1,17 +1,17 @@ - - - festc_core - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - + + + festc_core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/festc_core/bin/gov/epa/festc/core/FestcApplication$1.class b/festc_core/bin/gov/epa/festc/core/FestcApplication$1.class deleted file mode 100644 index 6c55d8f..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/FestcApplication$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/FestcApplication$ProjectEvent.class b/festc_core/bin/gov/epa/festc/core/FestcApplication$ProjectEvent.class deleted file mode 100644 index 5d130da..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/FestcApplication$ProjectEvent.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/FestcApplication.class b/festc_core/bin/gov/epa/festc/core/FestcApplication.class deleted file mode 100644 index d99892b..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/FestcApplication.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/FestcConfigurator.class b/festc_core/bin/gov/epa/festc/core/FestcConfigurator.class deleted file mode 100644 index e4c81de..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/FestcConfigurator.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/FestcConstants.class b/festc_core/bin/gov/epa/festc/core/FestcConstants.class deleted file mode 100644 index 6906e26..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/FestcConstants.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/FestcGUI.class b/festc_core/bin/gov/epa/festc/core/FestcGUI.class deleted file mode 100644 index 7132927..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/FestcGUI.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/FestcPlugin.class b/festc_core/bin/gov/epa/festc/core/FestcPlugin.class deleted file mode 100644 index 91e14b2..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/FestcPlugin.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/Project.class b/festc_core/bin/gov/epa/festc/core/Project.class deleted file mode 100644 index b770e4c..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/Project.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/VersionInfo.class b/festc_core/bin/gov/epa/festc/core/VersionInfo.class deleted file mode 100644 index cc86ea0..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/VersionInfo.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/WriteVersionInfo.class b/festc_core/bin/gov/epa/festc/core/WriteVersionInfo.class deleted file mode 100644 index dbef987..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/WriteVersionInfo.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/action/About.class b/festc_core/bin/gov/epa/festc/core/action/About.class deleted file mode 100644 index 9e26912..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/action/About.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/action/CopyAction.class b/festc_core/bin/gov/epa/festc/core/action/CopyAction.class deleted file mode 100644 index dfd6737..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/action/CopyAction.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/action/CreateAction.class b/festc_core/bin/gov/epa/festc/core/action/CreateAction.class deleted file mode 100644 index 60ff190..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/action/CreateAction.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/action/DeleteAction.class b/festc_core/bin/gov/epa/festc/core/action/DeleteAction.class deleted file mode 100644 index e4aa1a0..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/action/DeleteAction.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/action/ExitAction.class b/festc_core/bin/gov/epa/festc/core/action/ExitAction.class deleted file mode 100644 index 6333a79..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/action/ExitAction.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/action/Help.class b/festc_core/bin/gov/epa/festc/core/action/Help.class deleted file mode 100644 index c0dbcdc..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/action/Help.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/action/OpenAction.class b/festc_core/bin/gov/epa/festc/core/action/OpenAction.class deleted file mode 100644 index a3ed3b5..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/action/OpenAction.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/action/SaveAction.class b/festc_core/bin/gov/epa/festc/core/action/SaveAction.class deleted file mode 100644 index d4f0a95..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/action/SaveAction.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/Beld4DataGenFields.class b/festc_core/bin/gov/epa/festc/core/proj/Beld4DataGenFields.class deleted file mode 100644 index 3fa08aa..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/Beld4DataGenFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/CallBack.class b/festc_core/bin/gov/epa/festc/core/proj/CallBack.class deleted file mode 100644 index 4050f5f..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/CallBack.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/DomainFields.class b/festc_core/bin/gov/epa/festc/core/proj/DomainFields.class deleted file mode 100644 index c6da34b..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/DomainFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/Epic2CMAQFields.class b/festc_core/bin/gov/epa/festc/core/proj/Epic2CMAQFields.class deleted file mode 100644 index af41d96..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/Epic2CMAQFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/EpicAppFields.class b/festc_core/bin/gov/epa/festc/core/proj/EpicAppFields.class deleted file mode 100644 index 22a7919..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/EpicAppFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/EpicSpinupFields.class b/festc_core/bin/gov/epa/festc/core/proj/EpicSpinupFields.class deleted file mode 100644 index e39171f..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/EpicSpinupFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/EpicYearlyAverage2CMAQFields.class b/festc_core/bin/gov/epa/festc/core/proj/EpicYearlyAverage2CMAQFields.class deleted file mode 100644 index b17bac9..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/EpicYearlyAverage2CMAQFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/ManFileModFields.class b/festc_core/bin/gov/epa/festc/core/proj/ManFileModFields.class deleted file mode 100644 index c642e0a..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/ManFileModFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/ManageAppFields.class b/festc_core/bin/gov/epa/festc/core/proj/ManageAppFields.class deleted file mode 100644 index f5172f8..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/ManageAppFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/ManageSpinupFields.class b/festc_core/bin/gov/epa/festc/core/proj/ManageSpinupFields.class deleted file mode 100644 index 7206d4f..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/ManageSpinupFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/Mcip2EpicFields.class b/festc_core/bin/gov/epa/festc/core/proj/Mcip2EpicFields.class deleted file mode 100644 index 7fdbe17..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/Mcip2EpicFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/PageFields.class b/festc_core/bin/gov/epa/festc/core/proj/PageFields.class deleted file mode 100644 index 679e45c..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/PageFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/ProjectLoader.class b/festc_core/bin/gov/epa/festc/core/proj/ProjectLoader.class deleted file mode 100644 index 189bf6d..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/ProjectLoader.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/SiteFilesFields.class b/festc_core/bin/gov/epa/festc/core/proj/SiteFilesFields.class deleted file mode 100644 index 8c79a46..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/SiteFilesFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/SiteInfoGenFields.class b/festc_core/bin/gov/epa/festc/core/proj/SiteInfoGenFields.class deleted file mode 100644 index 23d83aa..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/SiteInfoGenFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/SoilFilesFields.class b/festc_core/bin/gov/epa/festc/core/proj/SoilFilesFields.class deleted file mode 100644 index abfc832..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/SoilFilesFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/core/proj/VisualizationFields.class b/festc_core/bin/gov/epa/festc/core/proj/VisualizationFields.class deleted file mode 100644 index 61073d2..0000000 Binary files a/festc_core/bin/gov/epa/festc/core/proj/VisualizationFields.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/AboutDialog$1.class b/festc_core/bin/gov/epa/festc/gui/AboutDialog$1.class deleted file mode 100644 index d67952a..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/AboutDialog$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/AboutDialog.class b/festc_core/bin/gov/epa/festc/gui/AboutDialog.class deleted file mode 100644 index 3d9b7ae..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/AboutDialog.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Beld4DataGenPanel$1.class b/festc_core/bin/gov/epa/festc/gui/Beld4DataGenPanel$1.class deleted file mode 100644 index 88c7efe..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Beld4DataGenPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Beld4DataGenPanel$2.class b/festc_core/bin/gov/epa/festc/gui/Beld4DataGenPanel$2.class deleted file mode 100644 index 695f66d..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Beld4DataGenPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Beld4DataGenPanel.class b/festc_core/bin/gov/epa/festc/gui/Beld4DataGenPanel.class deleted file mode 100644 index 2e79557..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Beld4DataGenPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CopyProjectPanel.class b/festc_core/bin/gov/epa/festc/gui/CopyProjectPanel.class deleted file mode 100644 index 102cac3..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CopyProjectPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateAppManFilesPanel$1.class b/festc_core/bin/gov/epa/festc/gui/CreateAppManFilesPanel$1.class deleted file mode 100644 index 9147604..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateAppManFilesPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateAppManFilesPanel$2.class b/festc_core/bin/gov/epa/festc/gui/CreateAppManFilesPanel$2.class deleted file mode 100644 index 4f2f52a..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateAppManFilesPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateAppManFilesPanel.class b/festc_core/bin/gov/epa/festc/gui/CreateAppManFilesPanel.class deleted file mode 100644 index ec4e414..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateAppManFilesPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateSiteFilesPanel.class b/festc_core/bin/gov/epa/festc/gui/CreateSiteFilesPanel.class deleted file mode 100644 index 982b355..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateSiteFilesPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateSiteInfoPanel$1.class b/festc_core/bin/gov/epa/festc/gui/CreateSiteInfoPanel$1.class deleted file mode 100644 index a9245d9..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateSiteInfoPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateSiteInfoPanel$2.class b/festc_core/bin/gov/epa/festc/gui/CreateSiteInfoPanel$2.class deleted file mode 100644 index 5bae925..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateSiteInfoPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateSiteInfoPanel.class b/festc_core/bin/gov/epa/festc/gui/CreateSiteInfoPanel.class deleted file mode 100644 index 471d43b..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateSiteInfoPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateSoilFilesPanel.class b/festc_core/bin/gov/epa/festc/gui/CreateSoilFilesPanel.class deleted file mode 100644 index 552563a..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateSoilFilesPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateSpinupManFilesPanel$1.class b/festc_core/bin/gov/epa/festc/gui/CreateSpinupManFilesPanel$1.class deleted file mode 100644 index 54ed415..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateSpinupManFilesPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateSpinupManFilesPanel$2.class b/festc_core/bin/gov/epa/festc/gui/CreateSpinupManFilesPanel$2.class deleted file mode 100644 index 2a1b2fc..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateSpinupManFilesPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CreateSpinupManFilesPanel.class b/festc_core/bin/gov/epa/festc/gui/CreateSpinupManFilesPanel.class deleted file mode 100644 index bbeecf8..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CreateSpinupManFilesPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CropSelectionPanel$1.class b/festc_core/bin/gov/epa/festc/gui/CropSelectionPanel$1.class deleted file mode 100644 index a65d54a..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CropSelectionPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CropSelectionPanel$2.class b/festc_core/bin/gov/epa/festc/gui/CropSelectionPanel$2.class deleted file mode 100644 index 0fb9f38..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CropSelectionPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/CropSelectionPanel.class b/festc_core/bin/gov/epa/festc/gui/CropSelectionPanel.class deleted file mode 100644 index 526d505..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/CropSelectionPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/DeleteProjectPanel.class b/festc_core/bin/gov/epa/festc/gui/DeleteProjectPanel.class deleted file mode 100644 index f58e17b..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/DeleteProjectPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/DomainPanel.class b/festc_core/bin/gov/epa/festc/gui/DomainPanel.class deleted file mode 100644 index 18f0658..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/DomainPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$1.class b/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$1.class deleted file mode 100644 index a0b95b3..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$2.class b/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$2.class deleted file mode 100644 index 2a76165..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$3$1.class b/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$3$1.class deleted file mode 100644 index cd0ecae..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$3$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$3.class b/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$3.class deleted file mode 100644 index 6f40065..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel$3.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel.class b/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel.class deleted file mode 100644 index a43e396..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Epic2CMAQPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicRunAppPanel$1.class b/festc_core/bin/gov/epa/festc/gui/EpicRunAppPanel$1.class deleted file mode 100644 index b26ea08..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicRunAppPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicRunAppPanel$2.class b/festc_core/bin/gov/epa/festc/gui/EpicRunAppPanel$2.class deleted file mode 100644 index 344009e..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicRunAppPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicRunAppPanel.class b/festc_core/bin/gov/epa/festc/gui/EpicRunAppPanel.class deleted file mode 100644 index 0c4e394..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicRunAppPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicSpinupPanel$1.class b/festc_core/bin/gov/epa/festc/gui/EpicSpinupPanel$1.class deleted file mode 100644 index 7b7b464..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicSpinupPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicSpinupPanel$2.class b/festc_core/bin/gov/epa/festc/gui/EpicSpinupPanel$2.class deleted file mode 100644 index 87085dd..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicSpinupPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicSpinupPanel.class b/festc_core/bin/gov/epa/festc/gui/EpicSpinupPanel.class deleted file mode 100644 index 0120696..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicSpinupPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$1.class b/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$1.class deleted file mode 100644 index bfd130a..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$2.class b/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$2.class deleted file mode 100644 index c60b459..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$3.class b/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$3.class deleted file mode 100644 index 4b6cec7..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$3.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$4.class b/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$4.class deleted file mode 100644 index 7f35645..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel$4.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel.class b/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel.class deleted file mode 100644 index 9020530..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents$1.class b/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents$1.class deleted file mode 100644 index 450f0bf..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents$2.class b/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents$2.class deleted file mode 100644 index 8b5bfb3..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents$3.class b/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents$3.class deleted file mode 100644 index 859cd23..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents$3.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents.class b/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents.class deleted file mode 100644 index 2c4d338..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/HelpWindowWithContents.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ListWidget.class b/festc_core/bin/gov/epa/festc/gui/ListWidget.class deleted file mode 100644 index 78ff410..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ListWidget.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$1.class b/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$1.class deleted file mode 100644 index 8680108..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$2.class b/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$2.class deleted file mode 100644 index 690c42e..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$3.class b/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$3.class deleted file mode 100644 index 9537ffe..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$3.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$4.class b/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$4.class deleted file mode 100644 index d601bea..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel$4.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel.class b/festc_core/bin/gov/epa/festc/gui/ManFileModPanel.class deleted file mode 100644 index 7d7cc75..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ManFileModPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$1.class b/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$1.class deleted file mode 100644 index f050998..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$2.class b/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$2.class deleted file mode 100644 index 7b00040..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$3.class b/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$3.class deleted file mode 100644 index 5debae3..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$3.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$4.class b/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$4.class deleted file mode 100644 index b161d5d..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel$4.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel.class b/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel.class deleted file mode 100644 index 270b0d9..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/Mcip2EpicPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/MessageBoard.class b/festc_core/bin/gov/epa/festc/gui/MessageBoard.class deleted file mode 100644 index 9292447..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/MessageBoard.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/MessagePanel.class b/festc_core/bin/gov/epa/festc/gui/MessagePanel.class deleted file mode 100644 index c26c225..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/MessagePanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/PlotEventListener.class b/festc_core/bin/gov/epa/festc/gui/PlotEventListener.class deleted file mode 100644 index a4c56f9..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/PlotEventListener.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/SaveProjectPanel.class b/festc_core/bin/gov/epa/festc/gui/SaveProjectPanel.class deleted file mode 100644 index 6cb7aa6..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/SaveProjectPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ScrollablePanel$IncrementInfo.class b/festc_core/bin/gov/epa/festc/gui/ScrollablePanel$IncrementInfo.class deleted file mode 100644 index 7b96a1e..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ScrollablePanel$IncrementInfo.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ScrollablePanel$IncrementType.class b/festc_core/bin/gov/epa/festc/gui/ScrollablePanel$IncrementType.class deleted file mode 100644 index ba8a164..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ScrollablePanel$IncrementType.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ScrollablePanel$ScrollableSizeHint.class b/festc_core/bin/gov/epa/festc/gui/ScrollablePanel$ScrollableSizeHint.class deleted file mode 100644 index 7b6c9d3..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ScrollablePanel$ScrollableSizeHint.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ScrollablePanel.class b/festc_core/bin/gov/epa/festc/gui/ScrollablePanel.class deleted file mode 100644 index 4df7963..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ScrollablePanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/SingleLineMessagePanel.class b/festc_core/bin/gov/epa/festc/gui/SingleLineMessagePanel.class deleted file mode 100644 index 0df38b3..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/SingleLineMessagePanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ToolsPanel$1.class b/festc_core/bin/gov/epa/festc/gui/ToolsPanel$1.class deleted file mode 100644 index d75b290..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ToolsPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ToolsPanel$JGradientButton.class b/festc_core/bin/gov/epa/festc/gui/ToolsPanel$JGradientButton.class deleted file mode 100644 index 1291aec..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ToolsPanel$JGradientButton.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ToolsPanel.class b/festc_core/bin/gov/epa/festc/gui/ToolsPanel.class deleted file mode 100644 index 2399263..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ToolsPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/UtilFieldsPanel.class b/festc_core/bin/gov/epa/festc/gui/UtilFieldsPanel.class deleted file mode 100644 index 749d085..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/UtilFieldsPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSiteFilesPanel$1.class b/festc_core/bin/gov/epa/festc/gui/UtilGenerateSiteFilesPanel$1.class deleted file mode 100644 index 4ae7089..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSiteFilesPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSiteFilesPanel$2.class b/festc_core/bin/gov/epa/festc/gui/UtilGenerateSiteFilesPanel$2.class deleted file mode 100644 index c1676ee..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSiteFilesPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSiteFilesPanel.class b/festc_core/bin/gov/epa/festc/gui/UtilGenerateSiteFilesPanel.class deleted file mode 100644 index cf4eb73..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSiteFilesPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSoilMatchPanel$1.class b/festc_core/bin/gov/epa/festc/gui/UtilGenerateSoilMatchPanel$1.class deleted file mode 100644 index 6cec1eb..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSoilMatchPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSoilMatchPanel$2.class b/festc_core/bin/gov/epa/festc/gui/UtilGenerateSoilMatchPanel$2.class deleted file mode 100644 index 54ef1b0..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSoilMatchPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSoilMatchPanel.class b/festc_core/bin/gov/epa/festc/gui/UtilGenerateSoilMatchPanel.class deleted file mode 100644 index 596c967..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/UtilGenerateSoilMatchPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ViewFileDialog$1.class b/festc_core/bin/gov/epa/festc/gui/ViewFileDialog$1.class deleted file mode 100644 index a132bbb..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ViewFileDialog$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ViewFileDialog$2.class b/festc_core/bin/gov/epa/festc/gui/ViewFileDialog$2.class deleted file mode 100644 index 9808b58..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ViewFileDialog$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/ViewFileDialog.class b/festc_core/bin/gov/epa/festc/gui/ViewFileDialog.class deleted file mode 100644 index b411d4e..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/ViewFileDialog.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$1$1.class b/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$1$1.class deleted file mode 100644 index 61ae2b1..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$1$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$1.class b/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$1.class deleted file mode 100644 index 6cc0939..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$2.class b/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$2.class deleted file mode 100644 index 6b7fc02..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$3.class b/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$3.class deleted file mode 100644 index efd9f85..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$3.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$4.class b/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$4.class deleted file mode 100644 index baefec9..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel$4.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel.class b/festc_core/bin/gov/epa/festc/gui/VisualizationPanel.class deleted file mode 100644 index 65f0046..0000000 Binary files a/festc_core/bin/gov/epa/festc/gui/VisualizationPanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/test/TestCropDataTablePanel$1.class b/festc_core/bin/gov/epa/festc/test/TestCropDataTablePanel$1.class deleted file mode 100644 index e1cc3cf..0000000 Binary files a/festc_core/bin/gov/epa/festc/test/TestCropDataTablePanel$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/test/TestCropDataTablePanel.class b/festc_core/bin/gov/epa/festc/test/TestCropDataTablePanel.class deleted file mode 100644 index 3a14414..0000000 Binary files a/festc_core/bin/gov/epa/festc/test/TestCropDataTablePanel.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/BrowseAction$1.class b/festc_core/bin/gov/epa/festc/util/BrowseAction$1.class deleted file mode 100644 index b9bbd1d..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/BrowseAction$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/BrowseAction.class b/festc_core/bin/gov/epa/festc/util/BrowseAction.class deleted file mode 100644 index 334f3fa..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/BrowseAction.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/Constants$1.class b/festc_core/bin/gov/epa/festc/util/Constants$1.class deleted file mode 100644 index 1ee6200..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/Constants$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/Constants.class b/festc_core/bin/gov/epa/festc/util/Constants.class deleted file mode 100644 index 173fe9a..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/Constants.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/CustomDialog.class b/festc_core/bin/gov/epa/festc/util/CustomDialog.class deleted file mode 100644 index e3fcd9d..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/CustomDialog.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/DateFormat.class b/festc_core/bin/gov/epa/festc/util/DateFormat.class deleted file mode 100644 index 200b870..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/DateFormat.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/FileAction$1.class b/festc_core/bin/gov/epa/festc/util/FileAction$1.class deleted file mode 100644 index 634e802..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/FileAction$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/FileAction$2.class b/festc_core/bin/gov/epa/festc/util/FileAction$2.class deleted file mode 100644 index bdbd211..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/FileAction$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/FileAction.class b/festc_core/bin/gov/epa/festc/util/FileAction.class deleted file mode 100644 index aa9671c..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/FileAction.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/FileRunner$1.class b/festc_core/bin/gov/epa/festc/util/FileRunner$1.class deleted file mode 100644 index 2fab8f7..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/FileRunner$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/FileRunner$2.class b/festc_core/bin/gov/epa/festc/util/FileRunner$2.class deleted file mode 100644 index 58e97c0..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/FileRunner$2.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/FileRunner.class b/festc_core/bin/gov/epa/festc/util/FileRunner.class deleted file mode 100644 index e84fe1f..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/FileRunner.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/FormattedTextFieldDemo$1.class b/festc_core/bin/gov/epa/festc/util/FormattedTextFieldDemo$1.class deleted file mode 100644 index d3f074d..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/FormattedTextFieldDemo$1.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/FormattedTextFieldDemo.class b/festc_core/bin/gov/epa/festc/util/FormattedTextFieldDemo.class deleted file mode 100644 index 9a50236..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/FormattedTextFieldDemo.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/Messenger.class b/festc_core/bin/gov/epa/festc/util/Messenger.class deleted file mode 100644 index 2611e65..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/Messenger.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/ModelYearInconsistantException.class b/festc_core/bin/gov/epa/festc/util/ModelYearInconsistantException.class deleted file mode 100644 index d50e31e..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/ModelYearInconsistantException.class and /dev/null differ diff --git a/festc_core/bin/gov/epa/festc/util/SpringLayoutGenerator.class b/festc_core/bin/gov/epa/festc/util/SpringLayoutGenerator.class deleted file mode 100644 index 7d78a5d..0000000 Binary files a/festc_core/bin/gov/epa/festc/util/SpringLayoutGenerator.class and /dev/null differ diff --git a/festc_core/core.iml b/festc_core/core.iml index d1df568..fc56568 100644 --- a/festc_core/core.iml +++ b/festc_core/core.iml @@ -1,46 +1,46 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/festc_core/core.jar b/festc_core/core.jar new file mode 100644 index 0000000..01b6aa1 Binary files /dev/null and b/festc_core/core.jar differ diff --git a/festc_core/dist_plugin.xml b/festc_core/dist_plugin.xml index d1f8b1a..3ebd377 100644 --- a/festc_core/dist_plugin.xml +++ b/festc_core/dist_plugin.xml @@ -1,174 +1,174 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/festc_core/lib/log4j-1.2-api-2.0-rc1.jar b/festc_core/lib/log4j-1.2-api-2.0-rc1.jar deleted file mode 100644 index 5353055..0000000 Binary files a/festc_core/lib/log4j-1.2-api-2.0-rc1.jar and /dev/null differ diff --git a/festc_core/lib/log4j-1.2-api-2.22.1.jar b/festc_core/lib/log4j-1.2-api-2.22.1.jar new file mode 100644 index 0000000..de57f34 Binary files /dev/null and b/festc_core/lib/log4j-1.2-api-2.22.1.jar differ diff --git a/festc_core/lib/log4j-api-2.0-rc1.jar b/festc_core/lib/log4j-api-2.0-rc1.jar deleted file mode 100644 index a8b9261..0000000 Binary files a/festc_core/lib/log4j-api-2.0-rc1.jar and /dev/null differ diff --git a/festc_core/lib/log4j-api-2.22.1.jar b/festc_core/lib/log4j-api-2.22.1.jar new file mode 100644 index 0000000..b77e55e Binary files /dev/null and b/festc_core/lib/log4j-api-2.22.1.jar differ diff --git a/festc_core/lib/log4j-core-2.0-rc1.jar b/festc_core/lib/log4j-core-2.0-rc1.jar deleted file mode 100644 index 5a9f29a..0000000 Binary files a/festc_core/lib/log4j-core-2.0-rc1.jar and /dev/null differ diff --git a/festc_core/lib/log4j-core-2.22.1.jar b/festc_core/lib/log4j-core-2.22.1.jar new file mode 100644 index 0000000..0be3f1f Binary files /dev/null and b/festc_core/lib/log4j-core-2.22.1.jar differ diff --git a/festc_core/lib/log4j-jcl-2.0-rc1.jar b/festc_core/lib/log4j-jcl-2.0-rc1.jar deleted file mode 100644 index 66c7369..0000000 Binary files a/festc_core/lib/log4j-jcl-2.0-rc1.jar and /dev/null differ diff --git a/festc_core/lib/log4j-jcl-2.22.1.jar b/festc_core/lib/log4j-jcl-2.22.1.jar new file mode 100644 index 0000000..3b509ac Binary files /dev/null and b/festc_core/lib/log4j-jcl-2.22.1.jar differ diff --git a/festc_core/lib/log4j-taglib-2.0-rc1.jar b/festc_core/lib/log4j-taglib-2.0-rc1.jar deleted file mode 100644 index be6d1cd..0000000 Binary files a/festc_core/lib/log4j-taglib-2.0-rc1.jar and /dev/null differ diff --git a/festc_core/lib/log4j-taglib-2.21.1.jar b/festc_core/lib/log4j-taglib-2.21.1.jar new file mode 100644 index 0000000..fb00f74 Binary files /dev/null and b/festc_core/lib/log4j-taglib-2.21.1.jar differ diff --git a/festc_core/plugin.xml b/festc_core/plugin.xml index d927212..a2ea022 100644 --- a/festc_core/plugin.xml +++ b/festc_core/plugin.xml @@ -1,179 +1,179 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/festc_core/src/gov/epa/festc/core/FestcApplication.java b/festc_core/src/gov/epa/festc/core/FestcApplication.java index 67cfa17..d5993ed 100644 --- a/festc_core/src/gov/epa/festc/core/FestcApplication.java +++ b/festc_core/src/gov/epa/festc/core/FestcApplication.java @@ -1,607 +1,628 @@ -package gov.epa.festc.core; - -import gov.epa.festc.core.proj.CallBack; -import gov.epa.festc.core.proj.DomainFields; -import gov.epa.festc.core.proj.ProjectLoader; -import gov.epa.festc.core.proj.SiteInfoGenFields; -import gov.epa.festc.gui.CopyProjectPanel; -import gov.epa.festc.gui.DeleteProjectPanel; -import gov.epa.festc.gui.DomainPanel; -import gov.epa.festc.gui.HelpWindowWithContents; -import gov.epa.festc.gui.PlotEventListener; -import gov.epa.festc.gui.SaveProjectPanel; -import gov.epa.festc.util.Constants; -import gov.epa.festc.util.CustomDialog; -import gov.epa.festc.util.FileRunner; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; - -import org.apache.log4j.Level; - -import saf.core.ui.util.FileChooserUtilities; -import simphony.util.messages.MessageCenter; -import simphony.util.messages.MessageEvent; -import simphony.util.messages.MessageEventListener; - -/** - * Main FEST-C application facade. - * - * @author IE, UNC - * @version $Revision$ $Date$ - */ -public class FestcApplication implements ListSelectionListener, - ListDataListener, CallBack { - - private static MessageCenter msg = MessageCenter - .getMessageCenter(FestcApplication.class); - - private FestcGUI gui; - - private Project project; - - private File currentDir; - private File infoDir; - - private File projFile; - - private String epicHome; - private String workdir; - - private String sSimYear; - private String sFertYear; - private String sMinAcre; - - private boolean allowDiffCheck; - - private enum ProjectEvent {CREATED, OPENED, SAVE, SAVED}; - - private List plotListeners = new ArrayList(); - - public FestcApplication() { - project = new Project(); - } - - public FestcGUI getGui() { - return gui; - } - - public void init(FestcGUI gui) { - this.gui = gui; - MessageCenter.addMessageListener(new MessageEventListener() { - public void messageReceived(MessageEvent messageEvent) { - if (messageEvent.getLevel().equals(Level.ERROR)) { - FestcApplication.this.gui.showMessage("Error", - (messageEvent.getMessage() != null ? messageEvent.getMessage().toString() : "") - + ": " - + messageEvent.getThrowable().getMessage()); - } - } - }); - - // String curdir = Constants.getProperty(Constants.EPIC_HOME, msg); - // String usrhome = Constants.getProperty(Constants.USER_HOME, msg); - epicHome = Constants.getProperty(Constants.EPIC_HOME, msg); - workdir = Constants.getProperty(Constants.WORK_DIR, msg); - this.currentDir = new File(workdir + "/scenarios/scenariosInfo/"); - this.infoDir = new File(workdir + "/scenarios/scenariosInfo/"); - File logdir = new File(workdir + "/scenarios/scenariosInfo/logs"); - if ( !logdir.exists()) - logdir.mkdirs(); - String allow = Constants.getProperty(Constants.ALLOW_DIFF_CHECK, msg); - allowDiffCheck = (allow != null && allow.equalsIgnoreCase("true")) ? true : false; - //System.out.println("Allow: " + allow + allowDiffCheck); - } - - /** - * Gets the currently loaded Project. - * - * @return the currently loaded Project. - */ - public Project getProject() { - return project; - } - - /** - * Gets the currently browsed directory. - * - * @return the currently browsed directory. - */ - public File getCurrentDir() { - return currentDir; - } - - /** - * Sets the current directory for next browsing. - * - * @return the current directory. - */ - public void setCurrentDir(File curdir) { - currentDir = curdir; - } - - /*** - * Gets the modeling year associated with the app - */ - -// public String getSSimYear() { -// return this.sSimYear; -// } -// -// public void setSSimYear(String year) { -// this.sSimYear = year; -// } - - /*** - * Sets the fertilizer year associated with the app - */ - -// public String getSFertYear() { -// return this.sFertYear; -// } -// -// public void setSFertYear(String year) { -// this.sFertYear = year; -// } - - /*** - * Sets the minimum crop acres associated with the app - */ - -// public String getSMinAcre() { -// return this.sMinAcre; -// } -// -// public void setSMinAcre(String minAcre) { -// this.sMinAcre = minAcre; -// } - - /** - * Exits the application. - * - * @return true if the exit was successful and the application should be - * terminated, otherwise false. - */ - public boolean exit() { - // - return true; - } - - public void valueChanged(ListSelectionEvent e) { - // - } - - // listeners for the formula model - public void contentsChanged(ListDataEvent e) { - } - - /** - * Shows help. - */ - public void showHelp() { - String helpDir = System.getProperty("user.dir"); - if (helpDir == null) - return; - helpDir = helpDir + "/help"; - //String helpName1 = helpDir + "/userManualIndex.htm"; - String helpName2 = helpDir + "/userManual.htm"; - HelpWindowWithContents.showContents(null, "FEST-C User Guide", - null, helpName2); - - //msg.warn("help: " + helpName1); - msg.warn("help: " + helpName2); - } - - @Override - public void intervalAdded(ListDataEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void intervalRemoved(ListDataEvent e) { - // TODO Auto-generated method stub - - } - - /** - * Create a new project -- this is to create a new scenario from scratch. - * - */ - public void createProject() { - new CustomDialog(this, gui.getFrame(), true, new DomainPanel(this), - Constants.NEW_SCENARIO, "Create a New Scenario", projFile); - } - - /** - * Copy from an existing project -- This opens a dialog. - * - */ - public void copyProject() { - new CustomDialog(this, gui.getFrame(), true, new CopyProjectPanel(this), - Constants.COPY_SCENARIO, "Copy from an Existing Scenario", projFile); - } - - public void deleteProject() { - new CustomDialog(this, gui.getFrame(), true, new DeleteProjectPanel(this), - Constants.DELETE_SCENARIO, "Delete an Existing Scenario", projFile); - } - - public static MessageCenter getMsg() { - return msg; - } - - public File getProjFile() { - return projFile; - } - - public String getEpicHome() { - return epicHome; - } - - public String getWorkDir() { - return workdir; - } - - public List getPlotListeners() { - return plotListeners; - } - - /** - * Opens a saved project -- a set of text fields and combobox selections. This opens a - * file dialog. - */ - public void openProject() { - if (projFile != null ) { -// int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); -// if ( option == 0 ) - saveProject(); - } - File file = FileChooserUtilities.getOpenFile(infoDir); - openProject(file); - } - - /** - * Opens the specified file as a project. - * - * @param file the project file - */ - public void openProject(File file) { - if (file != null) { - try { - ProjectLoader projLoader = new ProjectLoader(); - project = new Project(); - projLoader.load(file, project); - projFile = file; - currentDir = file.getParentFile(); - firePlotEvent(ProjectEvent.OPENED); - } catch (Exception e) { - msg.error("Error while loading project: ", e); - } - } - } - - /** - * Saves the current project -- the current set of text fields and comboboxes. - * @throws Exception - */ - public void saveProject() { - new CustomDialog(this, gui.getFrame(), true, new SaveProjectPanel(projFile), Constants.SAVE_SCENARIO, "Save Scenario", projFile); - } - - /** - * Saves the current project as -- the current set of text fields and comboboxes. - */ - public void saveProjectAs() { - File file = FileChooserUtilities.getSaveFile(currentDir); - //if (file != null) { - saveProj(file); - //} - } - - private void saveProj(File file) { - if (file != null) { - firePlotEvent(ProjectEvent.SAVE); - - try { - ProjectLoader projLoader = new ProjectLoader(); - projLoader.save(file, project); - projFile = file; - currentDir = file.getParentFile(); - } catch (Exception e) { - e.printStackTrace(); - msg.error("Error while saving project", e); - } - } - } - - public void showTab(String tabId) { - gui.setActive(tabId); - } - - public static MessageCenter getMessageCenter() { - return msg; - } - - public void addPlotListener(PlotEventListener listener) { - plotListeners.add(listener); - } - - public void firePlotEvent(ProjectEvent event) { - for (PlotEventListener listener : plotListeners) { - if (event == ProjectEvent.CREATED) - listener.newProjectCreated(); - - if (event == ProjectEvent.OPENED) - listener.projectLoaded(); - - if (event == ProjectEvent.SAVE) - listener.saveProjectRequested(); - } - } - - public void showMessage(String title, String message) { - this.gui.showMessage(title, message); - } - - @Override - public void onCall(String cmd, JPanel contentPanel) throws Exception { - if (cmd.equals(Constants.NEW_SCENARIO)) { - - DomainPanel panel = (DomainPanel)contentPanel; - panel.validateFields(); - String newScenario = panel.getScenaName(); - - projFile = new File(workdir + "/scenarios/scenariosInfo/", newScenario); - if ( projFile.isFile() ) - throw new Exception("New scenario name already exist."); - - DomainFields domain =(DomainFields) project.getPage(DomainFields.class.getCanonicalName()); - if (domain == null ){ - domain = new DomainFields(); - project.addPage(domain); - } - domain.setGridName(panel.getGridName()); - domain.setProj(panel.getProj4proj()); - - domain.setCols(panel.getCols()); - domain.setRows(panel.getRows()); - domain.setXcellSize(panel.getxSize()); - domain.setYcellSize(panel.getySize()); - domain.setXmin(panel.getXmin()); - domain.setYmin(panel.getYmin()); - domain.setSimYear(panel.getSimuYear()); - domain.setNlcdYear(panel.getNlcdYear()); - domain.setCMinAcres("40.0"); - domain.setScenarioDir(workdir + "/scenarios/" + newScenario); - - project.setName(newScenario); - - /*** - * NOTE: to populate all the domain info from newly created scenario, - * a new method newProjectCreated() is added to PlotEventListener interface. - */ - - firePlotEvent(ProjectEvent.CREATED); - saveProj(projFile); - - newScenarioFold(newScenario, panel.getSimuYear()); - System.out.println("Created New Scenario: " + newScenario); - } - - if (cmd.equals(Constants.COPY_SCENARIO)) { - CopyProjectPanel panel = (CopyProjectPanel)contentPanel; - panel.validateFields(); - String existScenNameWdir = panel.getExistScenario(); - String newScenName = panel.getNewScenName(); - File existScenFile = new File(existScenNameWdir); - //copyScenarioFold( existScenNameWdir, newScenName, panel.getSimuYear()); - if ( ! existScenFile.isFile() ) - throw new Exception("Scenario " + existScenNameWdir + " does not exist. " ); - - try { - openProject(existScenFile); - } catch (Exception e) { - msg.warn("Error copying scenario " + existScenNameWdir + ".", e.getMessage()); - } - SiteInfoGenFields fields = (SiteInfoGenFields) project.getPage(SiteInfoGenFields.class.getCanonicalName()); - DomainFields domain =(DomainFields) project.getPage(DomainFields.class.getCanonicalName()); - if (domain == null ){ - domain = new DomainFields(); - project.addPage(domain); - } - domain.setGridName(fields.getGridName()); - domain.setProj(fields.getProj()); - domain.setCols(fields.getCols()); - domain.setRows(fields.getRows()); - domain.setXcellSize(fields.getXcellSize()); - domain.setYcellSize(fields.getYcellSize()); - domain.setXmin(fields.getXmin()); - domain.setYmin(fields.getYmin()); - domain.setScenarioDir(workdir + "/scenarios/" + newScenName); - domain.setSimYear(panel.getSimuYear()); - // get default nlcd year from simulation year - domain.setNlcdYear(); - domain.setCMinAcres(domain.getCMinAcres()); - project.setName(newScenName); - - projFile = new File(workdir + "/scenarios/scenariosInfo/", newScenName); - if ( projFile.isFile() ) - throw new Exception("New scenario \"" + newScenName + "\" already exist."); - - System.out.println("Creating Scenario: " + newScenName); - firePlotEvent(ProjectEvent.CREATED); - System.out.println("Saving Scenario: " + newScenName); - saveProj(projFile); - /*** - * NOTE: We still need to copy all the files from the existing scenario folder to the new scenario folder - */ - System.out.println("Coping Scenario: " + newScenName); - copyScenarioFold( existScenNameWdir, newScenName, panel.getSimuYear()); - //System.out.println("Finished Coping Scenario: " + newScenName); - } - - if (cmd.equals(Constants.DELETE_SCENARIO)) { - DeleteProjectPanel panel = (DeleteProjectPanel)contentPanel; - panel.validateFields(); - String existScenName = panel.getExistScenario(); - - File existScenFile = new File(workdir + "/scenarios/scenariosInfo/", existScenName); - if ( ! existScenFile.isFile() ) - throw new Exception("Scenario " + existScenName + " does not exist. " ); - int option = JOptionPane.showConfirmDialog(null, "Confirm that you want to delete scenario: " + existScenName + "? ", "Confirmation", JOptionPane.YES_NO_OPTION); - if ( option == 0 ) - deleteScenarioFold(existScenName); - } - - if (cmd.equals(Constants.SAVE_SCENARIO)) { - if (projFile != null) { - firePlotEvent(ProjectEvent.SAVE); - saveProj(projFile); - } - } - } - - private void deleteScenarioFold(String oldName) { - String file = workdir + "/scenarios/scenariosInfo/logs/delete_" +oldName + ".csh"; - String scenFile = workdir + "/scenarios/scenariosInfo/" +oldName; - String oldScenDir = workdir + "/scenarios/" + oldName ; - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to delete an existing scenario" + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); - sb.append("# in support of the CMAS project, 2013" + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("#***************************************************************************************" + ls + ls); - sb.append("rm -rf " + oldScenDir + ls); - sb.append("rm -f " + scenFile + ls); - try { - File script = new File(file); - Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - } catch (IOException e) { - msg.error("Error generating delete scenario script file", e); - return; - } - - String log = file + ".log"; - FileRunner.runScript(file, log, msg); - - } - - private void copyScenarioFold(String oldNameWdir, String newName, String year) { - Integer lIndex = oldNameWdir.lastIndexOf("/"); - String oldName = oldNameWdir.substring(lIndex+1); - Integer sIndex = oldNameWdir.indexOf("scenarios"); - String oldDir = oldNameWdir.substring(0, sIndex); - //System.out.printf(oldDir + " " + oldName); - - String file = workdir + "/scenarios/scenariosInfo/logs/copyScenario_" + newName+ "_from_" +oldName + ".csh"; ; - String oldScenDir = oldDir + "/scenarios/" + oldName ; - String newScenDir = workdir + "/scenarios/" + newName ; - String commonDir = epicHome + "/common_data" ; - - year = "2"+(Integer.parseInt(year)-1); - - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to copy all files from an existing scenario" + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); - sb.append("# in support of the CMAS project, 2010" + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("setenv EPIC_DIR " +epicHome +ls ); - sb.append("setenv SCEN_DIR " +newScenDir +ls ); - sb.append("setenv COMM_DIR " +commonDir +ls + ls ); - sb.append("#***************************************************************************************" + ls + ls); - sb.append("cp -R " + oldScenDir + " " + newScenDir + ls); - sb.append("sed -i '1s/^.\\{,8\\}/ " + year+ "/' $SCEN_DIR/share_data/EPICCONT.DAT" +ls ) ; - - try { - File script = new File(file); - Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - } catch (IOException e) { - msg.error("Error generating copy scenario script file", e); - return; - } - - String log = file + ".log"; - FileRunner.runScript(file, log, msg); - - } - - private void newScenarioFold(String newName, String year) { - String file = workdir + "/scenarios/scenariosInfo/logs/createScenario_"+ newName + ".csh"; - String newScenDir = workdir + "/scenarios/" + newName ; - String commonDir = epicHome + "/common_data" ; - year = "2"+(Integer.parseInt(year)-1); - - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to copy all files from an existing scenario" + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); - sb.append("# in support of the CMAS project, 2010" + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("#***************************************************************************************" + ls + ls); - sb.append("setenv EPIC_DIR " +epicHome +ls ); - sb.append("setenv SCEN_DIR " +newScenDir +ls ); - sb.append("setenv COMM_DIR " +commonDir +ls + ls ); - - sb.append("# mkdir case dirs " +ls ); - sb.append("mkdir -p $SCEN_DIR/share_data" +ls ); - sb.append("mkdir -p $SCEN_DIR/scripts" +ls ); - sb.append("mkdir -p $SCEN_DIR/work_dir" +ls ); - sb.append("cp $COMM_DIR/EPIC_model/app/EPICCONT.DAT $SCEN_DIR/share_data/." +ls ); - sb.append("sed -i '1s/^.\\{,8\\}/ " + year+ "/' $SCEN_DIR/share_data/EPICCONT.DAT" +ls ) ; - - try { - File script = new File(file); - Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - } catch (IOException e) { - msg.error("Error generating new scenario script file", e); - return; - } - - String log = file + ".log"; - FileRunner.runScript(file, log, msg); -// msg.warn("Please modify " + newScenDir + "/share_data/EPICCONT.DAT ", ""); - } - - public boolean allowDiffCheck() { - return allowDiffCheck; - } - -} +package gov.epa.festc.core; + +import gov.epa.festc.core.proj.CallBack; +import gov.epa.festc.core.proj.DomainFields; +import gov.epa.festc.core.proj.ProjectLoader; +import gov.epa.festc.core.proj.SiteInfoGenFields; +import gov.epa.festc.gui.CopyProjectPanel; +import gov.epa.festc.gui.DeleteProjectPanel; +import gov.epa.festc.gui.DomainPanel; +import gov.epa.festc.gui.HelpWindowWithContents; +import gov.epa.festc.gui.PlotEventListener; +import gov.epa.festc.gui.SaveProjectPanel; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.CustomDialog; +import gov.epa.festc.util.FileRunner; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.apache.log4j.Level; + +import saf.core.ui.util.FileChooserUtilities; +import simphony.util.messages.MessageCenter; +import simphony.util.messages.MessageEvent; +import simphony.util.messages.MessageEventListener; + +/** + * Main FEST-C application facade. + * + * @author IE, UNC + * @version $Revision$ $Date$ + */ +public class FestcApplication implements ListSelectionListener, + ListDataListener, CallBack { + + private static MessageCenter msg = MessageCenter + .getMessageCenter(FestcApplication.class); + + private FestcGUI gui; + + private Project project; + + private File currentDir; + private File infoDir; + + private File projFile; + + private String epicHome; + private String workdir; + + private String sSimYear; + private String sFertYear; + private String sMinAcre; + + private boolean allowDiffCheck; + + private enum ProjectEvent {CREATED, OPENED, SAVE, SAVED}; + + private List plotListeners = new ArrayList(); + + public FestcApplication() { + project = new Project(); + } + + public FestcGUI getGui() { + return gui; + } + + public void init(FestcGUI gui) { + this.gui = gui; + MessageCenter.addMessageListener(new MessageEventListener() { + public void messageReceived(MessageEvent messageEvent) { + if (messageEvent.getLevel().equals(Level.ERROR)) { + FestcApplication.this.gui.showMessage("Error", + (messageEvent.getMessage() != null ? messageEvent.getMessage().toString() : "") + + ": " + + messageEvent.getThrowable().getMessage()); + } + } + }); + + // String curdir = Constants.getProperty(Constants.EPIC_HOME, msg); + // String usrhome = Constants.getProperty(Constants.USER_HOME, msg); + epicHome = Constants.getProperty(Constants.EPIC_HOME, msg); + workdir = Constants.getProperty(Constants.WORK_DIR, msg); + this.currentDir = new File(workdir + "/scenarios/scenariosInfo/"); + this.infoDir = new File(workdir + "/scenarios/scenariosInfo/"); + File logdir = new File(workdir + "/scenarios/scenariosInfo/logs"); + if ( !logdir.exists()) + logdir.mkdirs(); + String allow = Constants.getProperty(Constants.ALLOW_DIFF_CHECK, msg); + allowDiffCheck = (allow != null && allow.equalsIgnoreCase("true")) ? true : false; + //System.out.println("Allow: " + allow + allowDiffCheck); + } + + /** + * Gets the currently loaded Project. + * + * @return the currently loaded Project. + */ + public Project getProject() { + return project; + } + + /** + * Gets the currently browsed directory. + * + * @return the currently browsed directory. + */ + public File getCurrentDir() { + return currentDir; + } + + /** + * Sets the current directory for next browsing. + * + * @return the current directory. + */ + public void setCurrentDir(File curdir) { + currentDir = curdir; + } + + /*** + * Gets the modeling year associated with the app + */ + +// public String getSSimYear() { +// return this.sSimYear; +// } +// +// public void setSSimYear(String year) { +// this.sSimYear = year; +// } + + /*** + * Sets the fertilizer year associated with the app + */ + +// public String getSFertYear() { +// return this.sFertYear; +// } +// +// public void setSFertYear(String year) { +// this.sFertYear = year; +// } + + /*** + * Sets the minimum crop acres associated with the app + */ + +// public String getSMinAcre() { +// return this.sMinAcre; +// } +// +// public void setSMinAcre(String minAcre) { +// this.sMinAcre = minAcre; +// } + + /** + * Exits the application. + * + * @return true if the exit was successful and the application should be + * terminated, otherwise false. + */ + public boolean exit() { + // + return true; + } + + public void valueChanged(ListSelectionEvent e) { + // + } + + // listeners for the formula model + public void contentsChanged(ListDataEvent e) { + } + + /** + * Shows help. + */ + public void showHelp() { + String helpDir = System.getProperty("user.dir"); + if (helpDir == null) + return; + helpDir = helpDir + "/help"; + //String helpName1 = helpDir + "/userManualIndex.htm"; + String helpName2 = helpDir + "/userManual.htm"; + HelpWindowWithContents.showContents(null, "FEST-C User Guide", + null, helpName2); + + //msg.warn("help: " + helpName1); + msg.warn("help: " + helpName2); + } + + @Override + public void intervalAdded(ListDataEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void intervalRemoved(ListDataEvent e) { + // TODO Auto-generated method stub + + } + + /** + * Create a new project -- this is to create a new scenario from scratch. + * + */ + public void createProject() { + new CustomDialog(this, gui.getFrame(), true, new DomainPanel(this), + Constants.NEW_SCENARIO, "Create a New Scenario", projFile); + } + + /** + * Copy from an existing project -- This opens a dialog. + * + */ + public void copyProject() { + new CustomDialog(this, gui.getFrame(), true, new CopyProjectPanel(this), + Constants.COPY_SCENARIO, "Copy from an Existing Scenario", projFile); + } + + public void deleteProject() { + new CustomDialog(this, gui.getFrame(), true, new DeleteProjectPanel(this), + Constants.DELETE_SCENARIO, "Delete an Existing Scenario", projFile); + } + + public static MessageCenter getMsg() { + return msg; + } + + public File getProjFile() { + return projFile; + } + + public String getEpicHome() { + return epicHome; + } + + public String getWorkDir() { + return workdir; + } + + public List getPlotListeners() { + return plotListeners; + } + + /** + * Opens a saved project -- a set of text fields and combobox selections. This opens a + * file dialog. + */ + public void openProject() { + if (projFile != null ) { +// int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); +// if ( option == 0 ) + saveProject(); + } + File file = FileChooserUtilities.getOpenFile(infoDir); + openProject(file); + } + + /** + * Opens the specified file as a project. + * + * @param file the project file + */ + public void openProject(File file) { + if (file != null) { + try { + ProjectLoader projLoader = new ProjectLoader(); + project = new Project(); + projLoader.load(file, project); + projFile = file; + currentDir = file.getParentFile(); + firePlotEvent(ProjectEvent.OPENED); + } catch (Exception e) { + msg.error("Error while loading project: ", e); + } + } + } + + /** + * Saves the current project -- the current set of text fields and comboboxes. + * @throws Exception + */ + public void saveProject() { + new CustomDialog(this, gui.getFrame(), true, new SaveProjectPanel(projFile), Constants.SAVE_SCENARIO, "Save Scenario", projFile); + } + + /** + * Saves the current project as -- the current set of text fields and comboboxes. + */ + public void saveProjectAs() { + File file = FileChooserUtilities.getSaveFile(currentDir); + //if (file != null) { + saveProj(file); + //} + } + + private void saveProj(File file) { + if (file != null) { + firePlotEvent(ProjectEvent.SAVE); + + try { + ProjectLoader projLoader = new ProjectLoader(); + projLoader.save(file, project); + projFile = file; + currentDir = file.getParentFile(); + } catch (Exception e) { + e.printStackTrace(); + msg.error("Error while saving project", e); + } + } + } + + public void showTab(String tabId) { + gui.setActive(tabId); + } + + public static MessageCenter getMessageCenter() { + return msg; + } + + public void addPlotListener(PlotEventListener listener) { + plotListeners.add(listener); + } + + public void firePlotEvent(ProjectEvent event) { + for (PlotEventListener listener : plotListeners) { + if (event == ProjectEvent.CREATED) + listener.newProjectCreated(); + + if (event == ProjectEvent.OPENED) + listener.projectLoaded(); + + if (event == ProjectEvent.SAVE) + listener.saveProjectRequested(); + } + } + + public void showMessage(String title, String message) { + this.gui.showMessage(title, message); + } + + @Override + public void onCall(String cmd, JPanel contentPanel) throws Exception { + if (cmd.equals(Constants.NEW_SCENARIO)) { + + DomainPanel panel = (DomainPanel)contentPanel; + panel.validateFields(); + String newScenario = panel.getScenaName(); + + projFile = new File(workdir + "/scenarios/scenariosInfo/", newScenario); + if ( projFile.isFile() ) + throw new Exception("New scenario name already exist."); + + DomainFields domain =(DomainFields) project.getPage(DomainFields.class.getCanonicalName()); + if (domain == null ){ + domain = new DomainFields(); + project.addPage(domain); + } + domain.setGridName(panel.getGridName()); + domain.setProj(panel.getProj4proj()); + + domain.setCols(panel.getCols()); + domain.setRows(panel.getRows()); + domain.setXcellSize(panel.getxSize()); + domain.setYcellSize(panel.getySize()); + domain.setXmin(panel.getXmin()); + domain.setYmin(panel.getYmin()); + domain.setSimYear(panel.getSimuYear()); + domain.setNlcdYear(panel.getNlcdYear()); + domain.setCMinAcres("0.0"); + domain.setScenarioDir(workdir + "/scenarios/" + newScenario); + + project.setName(newScenario); + + /*** + * NOTE: to populate all the domain info from newly created scenario, + * a new method newProjectCreated() is added to PlotEventListener interface. + */ + + firePlotEvent(ProjectEvent.CREATED); + saveProj(projFile); + + newScenarioFold(newScenario, panel.getSimuYear()); + System.out.println("Created New Scenario: " + newScenario); + } + + if (cmd.equals(Constants.COPY_SCENARIO)) { + CopyProjectPanel panel = (CopyProjectPanel)contentPanel; + panel.validateFields(); + String existScenNameWdir = panel.getExistScenario(); + String newScenName = panel.getNewScenName(); + File existScenFile = new File(existScenNameWdir); + //copyScenarioFold( existScenNameWdir, newScenName, panel.getSimuYear()); + if ( ! existScenFile.isFile() ) + throw new Exception("Scenario " + existScenNameWdir + " does not exist. " ); + + try { + openProject(existScenFile); + } catch (Exception e) { + msg.warn("Error copying scenario " + existScenNameWdir + ".", e.getMessage()); + } + SiteInfoGenFields fields = (SiteInfoGenFields) project.getPage(SiteInfoGenFields.class.getCanonicalName()); + DomainFields domain =(DomainFields) project.getPage(DomainFields.class.getCanonicalName()); + if (domain == null ){ + domain = new DomainFields(); + project.addPage(domain); + } + domain.setGridName(fields.getGridName()); + domain.setProj(fields.getProj()); + domain.setCols(fields.getCols()); + domain.setRows(fields.getRows()); + domain.setXcellSize(fields.getXcellSize()); + domain.setYcellSize(fields.getYcellSize()); + domain.setXmin(fields.getXmin()); + domain.setYmin(fields.getYmin()); + domain.setScenarioDir(workdir + "/scenarios/" + newScenName); + domain.setSimYear(panel.getSimuYear()); + // get default nlcd year from simulation year + domain.setNlcdYear(); + domain.setCMinAcres(domain.getCMinAcres()); + project.setName(newScenName); + + projFile = new File(workdir + "/scenarios/scenariosInfo/", newScenName); + if ( projFile.isFile() ) + throw new Exception("New scenario \"" + newScenName + "\" already exist."); + + System.out.println("Creating Scenario: " + newScenName); + firePlotEvent(ProjectEvent.CREATED); + System.out.println("Saving Scenario: " + newScenName); + saveProj(projFile); + /*** + * NOTE: We still need to copy all the files from the existing scenario folder to the new scenario folder + */ + System.out.println("Coping Scenario: " + newScenName); + copyScenarioFold( existScenNameWdir, newScenName, panel.getSimuYear()); + //System.out.println("Finished Coping Scenario: " + newScenName); + } + + if (cmd.equals(Constants.DELETE_SCENARIO)) { + DeleteProjectPanel panel = (DeleteProjectPanel)contentPanel; + panel.validateFields(); + String existScenName = panel.getExistScenario(); + + File existScenFile = new File(workdir + "/scenarios/scenariosInfo/", existScenName); + if ( ! existScenFile.isFile() ) + throw new Exception("Scenario " + existScenName + " does not exist. " ); + int option = JOptionPane.showConfirmDialog(null, "Confirm that you want to delete scenario: " + existScenName + "? ", "Confirmation", JOptionPane.YES_NO_OPTION); + if ( option == 0 ) + deleteScenarioFold(existScenName); + } + + if (cmd.equals(Constants.SAVE_SCENARIO)) { + if (projFile != null) { + firePlotEvent(ProjectEvent.SAVE); + saveProj(projFile); + } + } + } + + private void deleteScenarioFold(String oldName) { + String file = workdir + "/scenarios/scenariosInfo/logs/delete_" +oldName + ".csh"; + String scenFile = workdir + "/scenarios/scenariosInfo/" +oldName; + String oldScenDir = workdir + "/scenarios/" + oldName ; + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append("#!/bin/csh -f" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: to delete an existing scenario" + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); + sb.append("# in support of the CMAS project, 2013" + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("#***************************************************************************************" + ls + ls); + sb.append("rm -rf " + oldScenDir + ls); + sb.append("rm -f " + scenFile + ls); + try { + File script = new File(file); + Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + } catch (IOException e) { + msg.error("Error generating delete scenario script file", e); + return; + } + + String log = file + ".log"; + FileRunner.runScript(file, log, msg); + + } + + private void copyScenarioFold(String oldNameWdir, String newName, String year) { + Integer lIndex = oldNameWdir.lastIndexOf("/"); + String oldName = oldNameWdir.substring(lIndex+1); + Integer sIndex = oldNameWdir.indexOf("scenarios"); + String oldDir = oldNameWdir.substring(0, sIndex); + //System.out.printf(oldDir + " " + oldName); + + String file = workdir + "/scenarios/scenariosInfo/logs/copyScenario_" + newName+ "_from_" +oldName + ".csh"; ; + String oldScenDir = oldDir + "/scenarios/" + oldName ; + String newScenDir = workdir + "/scenarios/" + newName ; + String commonDir = epicHome + "/common_data" ; + + year = "2"+(Integer.parseInt(year)-1); + + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append("#!/bin/csh -f" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: to copy all files from an existing scenario" + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); + sb.append("# in support of the CMAS project, 2010" + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("setenv EPIC_DIR " +epicHome +ls ); + sb.append("setenv SCEN_DIR " +newScenDir +ls ); + sb.append("setenv COMM_DIR " +commonDir +ls + ls ); + sb.append("#***************************************************************************************" + ls + ls); + sb.append("cp -R " + oldScenDir + " " + newScenDir + ls); + sb.append("sed -i '1s/^.\\{,8\\}/ " + year+ "/' $SCEN_DIR/share_data/EPICCONT.DAT" +ls ) ; + + try { + File script = new File(file); + Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + } catch (IOException e) { + msg.error("Error generating copy scenario script file", e); + return; + } + + String log = file + ".log"; + FileRunner.runScript(file, log, msg); + + } + + private void newScenarioFold(String newName, String year) { + String file = workdir + "/scenarios/scenariosInfo/logs/createScenario_"+ newName + ".csh"; + String newScenDir = workdir + "/scenarios/" + newName ; + String commonDir = epicHome + "/common_data" ; + year = "2"+(Integer.parseInt(year)-1); + + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append("#!/bin/csh " + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: to copy all files from an existing scenario" + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); + sb.append("# in support of the CMAS project, 2010" + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("#***************************************************************************************" + ls + ls); + sb.append("setenv EPIC_DIR " +epicHome +ls ); + sb.append("setenv SCEN_DIR " +newScenDir +ls ); + sb.append("setenv COMM_DIR " +commonDir +ls + ls ); + + sb.append("# mkdir case dirs " +ls ); + sb.append("mkdir -p $SCEN_DIR/share_data" +ls ); + sb.append("mkdir -p $SCEN_DIR/scripts" +ls ); + sb.append("mkdir -p $SCEN_DIR/work_dir" +ls ); + + String copyCmd = "cp $COMM_DIR/EPIC_model/app/EPICCONT.DAT $SCEN_DIR/share_data/." +ls; + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + } + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage != null && !qSingModule.trim().isEmpty()) { + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + copyCmd); + } else { + sb.append(copyCmd); + } + sb.append("sed -i '1s/^.\\{,8\\}/ " + year+ "/' $SCEN_DIR/share_data/EPICCONT.DAT" +ls ) ; + + try { + File script = new File(file); + Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + } catch (IOException e) { + msg.error("Error generating new scenario script file", e); + return; + } + + String log = file + ".log"; + + FileRunner.runScript(file, log, msg); + + +// msg.warn("Please modify " + newScenDir + "/share_data/EPICCONT.DAT ", ""); + } + + public boolean allowDiffCheck() { + return allowDiffCheck; + } + +} diff --git a/festc_core/src/gov/epa/festc/core/FestcConfigurator.java b/festc_core/src/gov/epa/festc/core/FestcConfigurator.java index 60efbe8..6ff4395 100644 --- a/festc_core/src/gov/epa/festc/core/FestcConfigurator.java +++ b/festc_core/src/gov/epa/festc/core/FestcConfigurator.java @@ -1,303 +1,303 @@ -package gov.epa.festc.core; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; - -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.UIManager; - -import gov.epa.festc.gui.Beld4DataGenPanel; -import gov.epa.festc.gui.CreateAppManFilesPanel; -import gov.epa.festc.gui.CreateSiteFilesPanel; -import gov.epa.festc.gui.CreateSiteInfoPanel; -import gov.epa.festc.gui.CreateSoilFilesPanel; -import gov.epa.festc.gui.CreateSpinupManFilesPanel; -import gov.epa.festc.gui.Epic2CMAQPanel; -import gov.epa.festc.gui.Epic2SWATPanel; -import gov.epa.festc.gui.EpicRunAppPanel; -import gov.epa.festc.gui.EpicSpinupPanel; -import gov.epa.festc.gui.EpicYearlyAverage2CMAQPanel; -import gov.epa.festc.gui.ManFileModPanel; -import gov.epa.festc.gui.Mcip2EpicPanel; -import gov.epa.festc.gui.ToolsPanel; -import gov.epa.festc.gui.VisualizationPanel; -import saf.core.ui.GUIBarManager; -import saf.core.ui.IAppConfigurator; -import saf.core.ui.ISAFDisplay; -import saf.core.ui.IWindowCustomizer; -import saf.core.ui.dock.DefaultDockableFrame; -import saf.core.ui.dock.DefaultDockingManager; -import saf.core.ui.dock.DockingManager.MinimizeLocation; - -/** - * Application configurator for FEST-C. - *

- *

The methods in this interface are called by the SAF application - * initialization mechanism during points in the applications lifecycle. On - * application start up, the order in which they are called is: - *

    - *
  1. #preWindowOpen
  2. - *
  3. #createLayout
  4. - *
  5. #fillBars
  6. - *
  7. #postWindowOpen
  8. - *
- * - * @author IE, UNC - * @version $Revision$ $Date$ - */ -public class FestcConfigurator implements IAppConfigurator { - - private FestcApplication festcApp; - - private DefaultDockingManager DockingManager; -// private int CLOSE = 1; -// int MINIMIZE = 2; -// int MAXIMIZE = 4; -// int FLOAT = 8; - - /** - * Creates a FestcConfigurator. - * - * @param appthe main FEST-C application object - * - */ - public FestcConfigurator(FestcApplication app) { - festcApp = app; - } - - - /** - * Creates the initial layout in the main application window. Typically, - * implementors would add the initial application views here, setting up the - * initial gui layout. - * - * @param DockingManager - * the DockingManager used to create the initial layout - */ - public void createLayout(DefaultDockingManager DockingManager) { - this.DockingManager = DockingManager; - - ToolsPanel toolsPanel = new ToolsPanel(festcApp); - DefaultDockableFrame activeview = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.TOOLS_VIEW, - new JScrollPane(toolsPanel), MinimizeLocation.UNSPECIFIED, 4 ); - activeview.setTitle("Tools"); - activeview.setToolTip("Tools"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.TOOLS_GROUP, activeview); - - Beld4DataGenPanel beld4Gen = new Beld4DataGenPanel(festcApp); - DefaultDockableFrame fview = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.BELD4_VIEW, - new JScrollPane(beld4Gen),MinimizeLocation.UNSPECIFIED, 2|4|8 ); - fview.setTitle("Beld4 Data..."); - fview.setToolTip("BELD4 Data Generation"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, fview); - - CreateSiteInfoPanel siteInfo = new CreateSiteInfoPanel(festcApp); - DefaultDockableFrame view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.SITE_INFO_VIEW, - new JScrollPane(siteInfo), MinimizeLocation.UNSPECIFIED, 2|4|8); - view.setTitle("Crop Site Info..."); - view.setToolTip("Site Utilities"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - Mcip2EpicPanel mcip2epic = new Mcip2EpicPanel(festcApp); - JScrollPane pane = new JScrollPane(mcip2epic); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.MCIP2EPIC_VIEW, pane); - view.setTitle("MCIP/CMAQ to EPIC"); - view.setToolTip("MCIP/CMAQ to EPIC"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - CreateSiteFilesPanel siteMan = new CreateSiteFilesPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.SITE_FILE_VIEW, new JScrollPane(siteMan)); - view.setTitle("EPIC Site file..."); - view.setToolTip("EPIC Site Utilities"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - CreateSoilFilesPanel soilMatchpanel = new CreateSoilFilesPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.GEN_SOIL_MAN_FILES_VIEW, new JScrollPane(soilMatchpanel)); - view.setTitle("EPIC Soil ..."); - view.setToolTip("EPIC Soil Utilities"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - CreateSpinupManFilesPanel manfilespinup = new CreateSpinupManFilesPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.MAN_FILE_SPINUP_VIEW, new JScrollPane(manfilespinup) ); - view.setTitle("Management Spinup..."); - view.setToolTip("Management File Generation for Spinup"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - ManFileModPanel managePanel = new ManFileModPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.MANAGE_VIEW, new JScrollPane(managePanel) ); - view.setTitle("View/Edit EPIC..."); - view.setToolTip("View/Edit EPIC Inputs"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - EpicSpinupPanel epicSuPanel = new EpicSpinupPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC_VIEW, new JScrollPane(epicSuPanel) ); - view.setTitle("EPIC Runs for Spinup"); - view.setToolTip("EPIC Runs for Spinup"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - EpicYearlyAverage2CMAQPanel epicYearlyAverage2cmaqPanel = new EpicYearlyAverage2CMAQPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC_YEARLY_AVERAGE2CMAQ_VIEW, new JScrollPane(epicYearlyAverage2cmaqPanel) ); - view.setTitle("EPIC Yearly Extraction"); //EPIC Yearly Ave. to CMAQ"); - view.setToolTip("EPIC Yearly Extraction"); //EPIC Yearly Ave. to CMAQ"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - CreateAppManFilesPanel manfileapp = new CreateAppManFilesPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.MAN_FILE_APP_VIEW, new JScrollPane(manfileapp) ); - view.setTitle("Management File..."); - view.setToolTip("Management File Generation for Application"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - EpicRunAppPanel epicrunapp = new EpicRunAppPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC4APP_VIEW, new JScrollPane(epicrunapp) ); - view.setTitle("EPIC Runs..."); - view.setToolTip("EPIC Runs for Application"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - Epic2CMAQPanel epic2cmaqPanel = new Epic2CMAQPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC2CMAQ_VIEW, new JScrollPane(epic2cmaqPanel) ); - view.setTitle("EPIC to CMAQ"); - view.setToolTip("EPIC to CMAQ"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - Epic2SWATPanel epic2swatPanel = new Epic2SWATPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC2SWAT_VIEW, new JScrollPane(epic2swatPanel) ); - view.setTitle("EPIC to SWAT"); - view.setToolTip("EPIC to SWAT"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - - VisualizationPanel visPanel = new VisualizationPanel(festcApp); - view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.VISUALIZE_VIEW, new JScrollPane(visPanel) ); - view.setTitle("Visualization"); - view.setToolTip("Visualization"); - DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); - -// Beld4DataGenPanel beld4Gen = new Beld4DataGenPanel(festcApp); -// DefaultDockableFrame fview = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.BELD4_VIEW, -// new JScrollPane(beld4Gen),MinimizeLocation.UNSPECIFIED, 2|4|8 ); -// fview.setTitle("Beld4 Data..."); -// fview.setToolTip("BELD4 Data Generation"); -// DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, fview); -// - festcApp.init(new FestcGUI(DockingManager)); - managePanel.setParent(festcApp.getGui()); - //epicSuPanel.setParent(festcApp.getGui()); - //System.out.println(activeview.getID()); - festcApp.showTab(fview.getID()); - toolsPanel.requestFocusInWindow(); - //DockingManager.setActiveDockable(fview.getID()); - } - - public void setStatusOneText(String text) { - DockingManager.getBarManager().setStatusBarText("festc.status.one", text); - } - - public void setStatusTwoText(String text) { - DockingManager.getBarManager().setStatusBarText("festc.status.two", text); - } - - /** - * Optionally adds menu items and actions to the menu and tool bars. This - * can be used to programmatically add tool bar and menus / menu items for - * those that are not described in an xml plugin file. - * - * @param guiBarManager - * the GUIBarManager used to configure tool and menu bars. - */ - public void fillBars(GUIBarManager guiBarManager) { - //DockingManager.createWindowMenu(); - JTextField fld = new JTextField(); - Font font = fld.getFont().deriveFont(Font.BOLD); - guiBarManager.setStatusBarFont("festc.status.two", font); - guiBarManager.setStatusBarFont("festc.status.one", font); - guiBarManager.addToolBarComponent(FestcConstants.FORMULA_BAR_GROUP, "", Box.createHorizontalGlue()); - - JPanel panel = new JPanel(); - panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); - panel.add(new JLabel("Selected Formula:")); - panel.add(Box.createRigidArea(new Dimension(5, 0))); - JLabel label = new JLabel(" "); - label.setForeground(Color.BLUE); - label.setFont(label.getFont().deriveFont(Font.BOLD)); - panel.add(label); - guiBarManager.addToolBarComponent(FestcConstants.FORMULA_BAR_GROUP, FestcConstants.FORMULA_LABEL, panel); - guiBarManager.addToolBarComponent(FestcConstants.FORMULA_BAR_GROUP, "", Box - .createRigidArea(new Dimension(10, 0))); - } - - /** - * Performs some arbitrary clean up type actions immediately prior to - * closing the main application window. - */ - public void postWindowClose() { - } - - /** - * Performs some arbitrary actions immediately after the main application - * window has been open. - * - * @param display - * the display representing the main application window. - */ - public void postWindowOpen(ISAFDisplay display) { - festcApp.getGui().setFrame(display.getFrame()); - } - - /** - * Performs some arbitrary clean up type actions immediately prior to - * closing the main application window. The calls the pave application to - * determine whether the app should exit or not. - * - * @return true if the window can continue to close, false to veto the - * window close. - */ - public boolean preWindowClose() { - if ( festcApp.getProjFile() != null ){ -// int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); -// if ( option == 0 ) - festcApp.saveProject(); - } - return festcApp.exit(); - } - - /** - * Performs some arbitrary actions prior to the main application window - * opening. This can be setting the application's look and feel, using the - * customizer parameter to set the initial window's size, title and so on. - * - * @param customizer - * the customizer used to customize the initial application - * window - * @return true if the application should continue to open, or false to - * close stop application initialization. Note that return false can - * be a normal condition, such as a login failing. - */ - public boolean preWindowOpen(IWindowCustomizer customizer) { - try { - String lf = UIManager.getSystemLookAndFeelClassName(); - if (lf.toLowerCase().contains("gtk")) - lf = UIManager.getCrossPlatformLookAndFeelClassName(); - UIManager.setLookAndFeel(lf); - } catch (Exception ex) { - ex.printStackTrace(); - } - - //PlafManager.setPreferredTheme("repast.simphony", DockingManager.class.getResource("/saf/core/ui/saf-themes.xml")); - customizer.useStoredFrameBounds(600, 600); - customizer.useSavedLayout(); - customizer.setTitle( - //"FEST-C" - "Fertilizer Emission Scenario Tool for CMAQ (FEST-C v1.4)" - ); - return true; - } - - - -} +package gov.epa.festc.core; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.UIManager; + +import gov.epa.festc.gui.Beld4DataGenPanel; +import gov.epa.festc.gui.CreateAppManFilesPanel; +import gov.epa.festc.gui.CreateSiteFilesPanel; +import gov.epa.festc.gui.CreateSiteInfoPanel; +import gov.epa.festc.gui.CreateSoilFilesPanel; +import gov.epa.festc.gui.CreateSpinupManFilesPanel; +import gov.epa.festc.gui.Epic2CMAQPanel; +import gov.epa.festc.gui.Epic2SWATPanel; +import gov.epa.festc.gui.EpicRunAppPanel; +import gov.epa.festc.gui.EpicSpinupPanel; +import gov.epa.festc.gui.EpicYearlyAverage2CMAQPanel; +import gov.epa.festc.gui.ManFileModPanel; +import gov.epa.festc.gui.Mcip2EpicPanel; +import gov.epa.festc.gui.ToolsPanel; +import gov.epa.festc.gui.VisualizationPanel; +import saf.core.ui.GUIBarManager; +import saf.core.ui.IAppConfigurator; +import saf.core.ui.ISAFDisplay; +import saf.core.ui.IWindowCustomizer; +import saf.core.ui.dock.DefaultDockableFrame; +import saf.core.ui.dock.DefaultDockingManager; +import saf.core.ui.dock.DockingManager.MinimizeLocation; + +/** + * Application configurator for FEST-C. + *

+ *

The methods in this interface are called by the SAF application + * initialization mechanism during points in the applications lifecycle. On + * application start up, the order in which they are called is: + *

    + *
  1. #preWindowOpen
  2. + *
  3. #createLayout
  4. + *
  5. #fillBars
  6. + *
  7. #postWindowOpen
  8. + *
+ * + * @author IE, UNC + * @version $Revision$ $Date$ + */ +public class FestcConfigurator implements IAppConfigurator { + + private FestcApplication festcApp; + + private DefaultDockingManager DockingManager; +// private int CLOSE = 1; +// int MINIMIZE = 2; +// int MAXIMIZE = 4; +// int FLOAT = 8; + + /** + * Creates a FestcConfigurator. + * + * @param appthe main FEST-C application object + * + */ + public FestcConfigurator(FestcApplication app) { + festcApp = app; + } + + + /** + * Creates the initial layout in the main application window. Typically, + * implementors would add the initial application views here, setting up the + * initial gui layout. + * + * @param DockingManager + * the DockingManager used to create the initial layout + */ + public void createLayout(DefaultDockingManager DockingManager) { + this.DockingManager = DockingManager; + + ToolsPanel toolsPanel = new ToolsPanel(festcApp); + DefaultDockableFrame activeview = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.TOOLS_VIEW, + new JScrollPane(toolsPanel), MinimizeLocation.UNSPECIFIED, 4 ); + activeview.setTitle("Tools"); + activeview.setToolTip("Tools"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.TOOLS_GROUP, activeview); + + Beld4DataGenPanel beld4Gen = new Beld4DataGenPanel(festcApp); + DefaultDockableFrame fview = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.BELD4_VIEW, + new JScrollPane(beld4Gen),MinimizeLocation.UNSPECIFIED, 2|4|8 ); + fview.setTitle("Beld4 Data..."); + fview.setToolTip("BELD4 Data Generation"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, fview); + + CreateSiteInfoPanel siteInfo = new CreateSiteInfoPanel(festcApp); + DefaultDockableFrame view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.SITE_INFO_VIEW, + new JScrollPane(siteInfo), MinimizeLocation.UNSPECIFIED, 2|4|8); + view.setTitle("Crop Site Info..."); + view.setToolTip("Site Utilities"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + Mcip2EpicPanel mcip2epic = new Mcip2EpicPanel(festcApp); + JScrollPane pane = new JScrollPane(mcip2epic); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.MCIP2EPIC_VIEW, pane); + view.setTitle("MCIP/CMAQ to EPIC"); + view.setToolTip("MCIP/CMAQ to EPIC"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + CreateSiteFilesPanel siteMan = new CreateSiteFilesPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.SITE_FILE_VIEW, new JScrollPane(siteMan)); + view.setTitle("EPIC Site file..."); + view.setToolTip("EPIC Site Utilities"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + CreateSoilFilesPanel soilMatchpanel = new CreateSoilFilesPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.GEN_SOIL_MAN_FILES_VIEW, new JScrollPane(soilMatchpanel)); + view.setTitle("EPIC Soil ..."); + view.setToolTip("EPIC Soil Utilities"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + CreateSpinupManFilesPanel manfilespinup = new CreateSpinupManFilesPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.MAN_FILE_SPINUP_VIEW, new JScrollPane(manfilespinup) ); + view.setTitle("Management Spinup..."); + view.setToolTip("Management File Generation for Spinup"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + ManFileModPanel managePanel = new ManFileModPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.MANAGE_VIEW, new JScrollPane(managePanel) ); + view.setTitle("View/Edit EPIC..."); + view.setToolTip("View/Edit EPIC Inputs"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + EpicSpinupPanel epicSuPanel = new EpicSpinupPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC_VIEW, new JScrollPane(epicSuPanel) ); + view.setTitle("EPIC Runs for Spinup"); + view.setToolTip("EPIC Runs for Spinup"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + EpicYearlyAverage2CMAQPanel epicYearlyAverage2cmaqPanel = new EpicYearlyAverage2CMAQPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC_YEARLY_AVERAGE2CMAQ_VIEW, new JScrollPane(epicYearlyAverage2cmaqPanel) ); + view.setTitle("EPIC Yearly Extraction"); //EPIC Yearly Ave. to CMAQ"); + view.setToolTip("EPIC Yearly Extraction"); //EPIC Yearly Ave. to CMAQ"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + CreateAppManFilesPanel manfileapp = new CreateAppManFilesPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.MAN_FILE_APP_VIEW, new JScrollPane(manfileapp) ); + view.setTitle("Management File..."); + view.setToolTip("Management File Generation for Application"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + EpicRunAppPanel epicrunapp = new EpicRunAppPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC4APP_VIEW, new JScrollPane(epicrunapp) ); + view.setTitle("EPIC Runs..."); + view.setToolTip("EPIC Runs for Application"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + Epic2CMAQPanel epic2cmaqPanel = new Epic2CMAQPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC2CMAQ_VIEW, new JScrollPane(epic2cmaqPanel) ); + view.setTitle("EPIC to CMAQ"); + view.setToolTip("EPIC to CMAQ"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + Epic2SWATPanel epic2swatPanel = new Epic2SWATPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.EPIC2SWAT_VIEW, new JScrollPane(epic2swatPanel) ); + view.setTitle("EPIC to SWAT"); + view.setToolTip("EPIC to SWAT"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + + VisualizationPanel visPanel = new VisualizationPanel(festcApp); + view = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.VISUALIZE_VIEW, new JScrollPane(visPanel) ); + view.setTitle("Visualization"); + view.setToolTip("Visualization"); + DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, view); + +// Beld4DataGenPanel beld4Gen = new Beld4DataGenPanel(festcApp); +// DefaultDockableFrame fview = (DefaultDockableFrame) DockingManager.createDockable(FestcConstants.BELD4_VIEW, +// new JScrollPane(beld4Gen),MinimizeLocation.UNSPECIFIED, 2|4|8 ); +// fview.setTitle("Beld4 Data..."); +// fview.setToolTip("BELD4 Data Generation"); +// DockingManager.addDockableToGroup(FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID, fview); +// + festcApp.init(new FestcGUI(DockingManager)); + managePanel.setParent(festcApp.getGui()); + //epicSuPanel.setParent(festcApp.getGui()); + //System.out.println(activeview.getID()); + festcApp.showTab(fview.getID()); + toolsPanel.requestFocusInWindow(); + //DockingManager.setActiveDockable(fview.getID()); + } + + public void setStatusOneText(String text) { + DockingManager.getBarManager().setStatusBarText("festc.status.one", text); + } + + public void setStatusTwoText(String text) { + DockingManager.getBarManager().setStatusBarText("festc.status.two", text); + } + + /** + * Optionally adds menu items and actions to the menu and tool bars. This + * can be used to programmatically add tool bar and menus / menu items for + * those that are not described in an xml plugin file. + * + * @param guiBarManager + * the GUIBarManager used to configure tool and menu bars. + */ + public void fillBars(GUIBarManager guiBarManager) { + //DockingManager.createWindowMenu(); + JTextField fld = new JTextField(); + Font font = fld.getFont().deriveFont(Font.BOLD); + guiBarManager.setStatusBarFont("festc.status.two", font); + guiBarManager.setStatusBarFont("festc.status.one", font); + guiBarManager.addToolBarComponent(FestcConstants.FORMULA_BAR_GROUP, "", Box.createHorizontalGlue()); + + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); + panel.add(new JLabel("Selected Formula:")); + panel.add(Box.createRigidArea(new Dimension(5, 0))); + JLabel label = new JLabel(" "); + label.setForeground(Color.BLUE); + label.setFont(label.getFont().deriveFont(Font.BOLD)); + panel.add(label); + guiBarManager.addToolBarComponent(FestcConstants.FORMULA_BAR_GROUP, FestcConstants.FORMULA_LABEL, panel); + guiBarManager.addToolBarComponent(FestcConstants.FORMULA_BAR_GROUP, "", Box + .createRigidArea(new Dimension(10, 0))); + } + + /** + * Performs some arbitrary clean up type actions immediately prior to + * closing the main application window. + */ + public void postWindowClose() { + } + + /** + * Performs some arbitrary actions immediately after the main application + * window has been open. + * + * @param display + * the display representing the main application window. + */ + public void postWindowOpen(ISAFDisplay display) { + festcApp.getGui().setFrame(display.getFrame()); + } + + /** + * Performs some arbitrary clean up type actions immediately prior to + * closing the main application window. The calls the pave application to + * determine whether the app should exit or not. + * + * @return true if the window can continue to close, false to veto the + * window close. + */ + public boolean preWindowClose() { + if ( festcApp.getProjFile() != null ){ +// int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); +// if ( option == 0 ) + festcApp.saveProject(); + } + return festcApp.exit(); + } + + /** + * Performs some arbitrary actions prior to the main application window + * opening. This can be setting the application's look and feel, using the + * customizer parameter to set the initial window's size, title and so on. + * + * @param customizer + * the customizer used to customize the initial application + * window + * @return true if the application should continue to open, or false to + * close stop application initialization. Note that return false can + * be a normal condition, such as a login failing. + */ + public boolean preWindowOpen(IWindowCustomizer customizer) { + try { + String lf = UIManager.getSystemLookAndFeelClassName(); + if (lf.toLowerCase().contains("gtk")) + lf = UIManager.getCrossPlatformLookAndFeelClassName(); + UIManager.setLookAndFeel(lf); + } catch (Exception ex) { + ex.printStackTrace(); + } + + //PlafManager.setPreferredTheme("repast.simphony", DockingManager.class.getResource("/saf/core/ui/saf-themes.xml")); + customizer.useStoredFrameBounds(600, 600); + customizer.useSavedLayout(); + customizer.setTitle( + //"FEST-C" + "Fertilizer Emission Scenario Tool for CMAQ (FEST-C v2.1)" + ); + return true; + } + + + +} diff --git a/festc_core/src/gov/epa/festc/core/FestcConstants.java b/festc_core/src/gov/epa/festc/core/FestcConstants.java index e7b4f46..4c0e203 100644 --- a/festc_core/src/gov/epa/festc/core/FestcConstants.java +++ b/festc_core/src/gov/epa/festc/core/FestcConstants.java @@ -1,35 +1,35 @@ -package gov.epa.festc.core; - -/** - * Constants used by the FEST-C application - * - * @author IE, UNC - * @version $Revision$ $Date$ - */ -public interface FestcConstants { - String MAIN_GROUP_ID = "gov.epa.festc.core.main_group"; - String DATASET_VIEW = "gov.epa.festc.core.dataset_view"; - String PERSPECTIVE_ID = "gov.epa.festc.core.perspective_one"; - String TOOLS_GROUP = "gov.epa.festc.core.tools_group"; - String FORMULA_VIEW = "gov.epa.festc.core.formula_view"; - String BELD4_VIEW = "gov.epa.festc.core.landuse_view"; - String MCIP2EPIC_VIEW = "gov.epa.festc.core.mcip2epic_view"; - String SITE_INFO_VIEW = "gov.epa.festc.core.siteinfo_gen_view"; - String SITE_FILE_VIEW = "gov.epa.festc.core.siteinfo_file_view"; - String GEN_SOIL_MAN_FILES_VIEW = "gov.epa.festc.core.gen_soil_man_files_view"; - String MAN_FILE_SPINUP_VIEW = "gov.epa.festc.core.man_file_spinup_view"; - String MAN_FILE_APP_VIEW = "gov.epa.festc.core.man_file_app_view"; - String EPIC4APP_VIEW = "gov.epa.festc.core.epic4app_view"; - String TOOLS_VIEW = "gov.epa.festc.core.tools_view"; - String MANAGE_VIEW = "gov.epa.festc.core.manage_view"; - String FORMULA_BAR_GROUP = "gov.epa.festc.core.bar.formula_group"; - String FORMULA_LABEL = "gov.epa.festc.core.bar.formula_label"; - String APP_LOG_FILE = System.getProperty("user.home") + "/festc/velocity.log"; - String OUTPUT_LOG_FILR = System.getProperty("user.home") + "/festc/festc.log"; - String EPIC_VIEW = "gov.epa.festc.core.epic_view"; - String PROCESS_EPIC_SPINUP_VIEW = "gov.epa.festc.core.proc_spinup_view"; - String EPIC2CMAQ_VIEW = "gov.epa.festc.core.epic2cmaq_view"; - String EPIC2SWAT_VIEW = "gov.epa.festc.core.epic2swat_view"; - String EPIC_YEARLY_AVERAGE2CMAQ_VIEW = "gov.epa.festc.core.epic_yearly_average2cmaq_view"; - String VISUALIZE_VIEW = "gov.epa.festc.core.visualize_view"; -} +package gov.epa.festc.core; + +/** + * Constants used by the FEST-C application + * + * @author IE, UNC + * @version $Revision$ $Date$ + */ +public interface FestcConstants { + String MAIN_GROUP_ID = "gov.epa.festc.core.main_group"; + String DATASET_VIEW = "gov.epa.festc.core.dataset_view"; + String PERSPECTIVE_ID = "gov.epa.festc.core.perspective_one"; + String TOOLS_GROUP = "gov.epa.festc.core.tools_group"; + String FORMULA_VIEW = "gov.epa.festc.core.formula_view"; + String BELD4_VIEW = "gov.epa.festc.core.landuse_view"; + String MCIP2EPIC_VIEW = "gov.epa.festc.core.mcip2epic_view"; + String SITE_INFO_VIEW = "gov.epa.festc.core.siteinfo_gen_view"; + String SITE_FILE_VIEW = "gov.epa.festc.core.siteinfo_file_view"; + String GEN_SOIL_MAN_FILES_VIEW = "gov.epa.festc.core.gen_soil_man_files_view"; + String MAN_FILE_SPINUP_VIEW = "gov.epa.festc.core.man_file_spinup_view"; + String MAN_FILE_APP_VIEW = "gov.epa.festc.core.man_file_app_view"; + String EPIC4APP_VIEW = "gov.epa.festc.core.epic4app_view"; + String TOOLS_VIEW = "gov.epa.festc.core.tools_view"; + String MANAGE_VIEW = "gov.epa.festc.core.manage_view"; + String FORMULA_BAR_GROUP = "gov.epa.festc.core.bar.formula_group"; + String FORMULA_LABEL = "gov.epa.festc.core.bar.formula_label"; + String APP_LOG_FILE = System.getProperty("user.home") + "/festc/velocity.log"; + String OUTPUT_LOG_FILR = System.getProperty("user.home") + "/festc/festc.log"; + String EPIC_VIEW = "gov.epa.festc.core.epic_view"; + String PROCESS_EPIC_SPINUP_VIEW = "gov.epa.festc.core.proc_spinup_view"; + String EPIC2CMAQ_VIEW = "gov.epa.festc.core.epic2cmaq_view"; + String EPIC2SWAT_VIEW = "gov.epa.festc.core.epic2swat_view"; + String EPIC_YEARLY_AVERAGE2CMAQ_VIEW = "gov.epa.festc.core.epic_yearly_average2cmaq_view"; + String VISUALIZE_VIEW = "gov.epa.festc.core.visualize_view"; +} diff --git a/festc_core/src/gov/epa/festc/core/FestcGUI.java b/festc_core/src/gov/epa/festc/core/FestcGUI.java index 08336ff..f870f9b 100644 --- a/festc_core/src/gov/epa/festc/core/FestcGUI.java +++ b/festc_core/src/gov/epa/festc/core/FestcGUI.java @@ -1,240 +1,242 @@ -package gov.epa.festc.core; - -import java.awt.Image; -import java.awt.Toolkit; -import java.awt.event.WindowListener; -import java.util.ArrayList; -import java.util.Date; - -import javax.swing.JFrame; -import javax.swing.JOptionPane; - -import com.sun.glass.events.ViewEvent; - -import saf.core.ui.dock.DefaultDockingManager; -import saf.core.ui.dock.DockableFrame; -import saf.core.ui.dock.DockingManager; -import saf.core.ui.event.DockableFrameEvent; -import saf.core.ui.event.DockableFrameListener; -import simphony.util.messages.MessageCenter; - -/** - * Facade for gui related application operations. - * - * @author IE, UNC - * @version $Revision$ $Date$ - */ -public class FestcGUI implements DockableFrameListener { - - private static final MessageCenter ctr = MessageCenter - .getMessageCenter(FestcGUI.class); - - private DefaultDockingManager viewManager; - private JFrame frame; - private java.util.List viewList = new ArrayList(); - private java.util.List framesToDisplay = new ArrayList(); - - public FestcGUI(DefaultDockingManager viewManager) { - this.viewManager = viewManager; - } - - public void undockAllPlots() { - java.util.List views = viewManager.getDockableFrames( - FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID); - for (DockableFrame view : views) { - view.doFloat(); - } - } - - public void setStatusTwoText(String text) { - viewManager.getBarManager().setStatusBarText("festc.status.two", text); - } - - public void setStatusOneText(String text) { - viewManager.getBarManager().setStatusBarText("festc.status.one", text); - } - - public JFrame getFrame() { - return frame; - } - - public void setFrame(JFrame frame) { - this.frame = frame; - Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/epa_logo.JPG")); - this.frame.setIconImage(image); - - for (JFrame f : framesToDisplay) { - f.setLocationRelativeTo(FestcGUI.this.frame); - f.setVisible(true); - } - framesToDisplay.clear(); - } - - public DockingManager getViewManager() { - return viewManager; - } - - public void showMessage(String title, String message) { - JOptionPane.showMessageDialog(frame, message, title, - JOptionPane.INFORMATION_MESSAGE); - } - - public boolean askMessage(String title, String message) { - return JOptionPane.showConfirmDialog(frame, message + ". Continue?", - title, JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION; - } - - /** - * Invoked when a view is closed. - * - * @param evt - */ - - public void viewClosed(ViewEvent evt) { - ctr.info("View closed at: ", new Date()); - } - - /** - * Invoked when a view receives a float request. The float can be overriden - * by setting the events handled property to true. - * - * @param evt - * details the float request - */ - public void floatRequested(ViewEvent evt) { - } - - /** - * Invoked when a view receives a restore request. The restore can be - * overriden by setting the events handled property to true. - * - * @param evt - * details the restore request - */ - public void restoreRequested(ViewEvent evt) { - } - - /** - * Invoked when a user attempts to close a view. The close can be overriden - * by setting the events handled property to true. - * - * @param evt - * the event describing the view etc. - */ - public void closeRequested(ViewEvent evt) { - } - - /** - * Invoked when a view is floated. - * - * @param evt - */ - public void viewFloated(ViewEvent evt) { - // - } - - /** - * Invoked when a view is maximized. - * - * @param evt - */ - public void viewMaximized(ViewEvent evt) { - // todo implement method - } - - /** - * Invoked when a view is minimized. - * - * @param evt - */ - public void viewMinimized(ViewEvent evt) { - // todo implement method - } - - /** - * Invoked when a view is restored to its default docking position from a - * floated, minimized, or maximized state. - * - * @param evt - */ - public void viewRestored(ViewEvent evt) { - } - - /** - * Returns the list of open plot view ids - * - * @return ArrayList - */ - public java.util.List getViewList() { - return viewList; - } - - public void setActive(String tabId) { - viewManager.setActiveDockable(tabId); - } - - public void refreshViews() { - - } - - @Override - public void dockableClosed(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - - @Override - public void dockableClosing(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - - @Override - public void dockableFloating(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - - @Override - public void dockableRestoring(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - - @Override - public void dockableMinimizing(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - - @Override - public void dockableMinimized(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - - @Override - public void dockableFloated(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - - @Override - public void dockableMaximizing(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - - @Override - public void dockableMaximized(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - - @Override - public void dockableRestored(DockableFrameEvent evt) { - // TODO Auto-generated method stub - - } - -} +package gov.epa.festc.core; + +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.event.WindowListener; +import java.util.ArrayList; +import java.util.Date; + +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +import javafx.event.Event; + +//import com.sun.glass.events.ViewEvent; + +import saf.core.ui.dock.DefaultDockingManager; +import saf.core.ui.dock.DockableFrame; +import saf.core.ui.dock.DockingManager; +import saf.core.ui.event.DockableFrameEvent; +import saf.core.ui.event.DockableFrameListener; +import simphony.util.messages.MessageCenter; + +/** + * Facade for gui related application operations. + * + * @author IE, UNC + * @version $Revision$ $Date$ + */ +public class FestcGUI implements DockableFrameListener { + + private static final MessageCenter ctr = MessageCenter + .getMessageCenter(FestcGUI.class); + + private DefaultDockingManager viewManager; + private JFrame frame; + private java.util.List viewList = new ArrayList(); + private java.util.List framesToDisplay = new ArrayList(); + + public FestcGUI(DefaultDockingManager viewManager) { + this.viewManager = viewManager; + } + + public void undockAllPlots() { + java.util.List views = viewManager.getDockableFrames( + FestcConstants.PERSPECTIVE_ID, FestcConstants.MAIN_GROUP_ID); + for (DockableFrame view : views) { + view.doFloat(); + } + } + + public void setStatusTwoText(String text) { + viewManager.getBarManager().setStatusBarText("festc.status.two", text); + } + + public void setStatusOneText(String text) { + viewManager.getBarManager().setStatusBarText("festc.status.one", text); + } + + public JFrame getFrame() { + return frame; + } + + public void setFrame(JFrame frame) { + this.frame = frame; + Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/epa_logo.JPG")); + this.frame.setIconImage(image); + + for (JFrame f : framesToDisplay) { + f.setLocationRelativeTo(FestcGUI.this.frame); + f.setVisible(true); + } + framesToDisplay.clear(); + } + + public DockingManager getViewManager() { + return viewManager; + } + + public void showMessage(String title, String message) { + JOptionPane.showMessageDialog(frame, message, title, + JOptionPane.INFORMATION_MESSAGE); + } + + public boolean askMessage(String title, String message) { + return JOptionPane.showConfirmDialog(frame, message + ". Continue?", + title, JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION; + } + + /** + * Invoked when a view is closed. + * + * @param evt + */ + + public void viewClosed(Event evt) { + ctr.info("View closed at: ", new Date()); + } + + /** + * Invoked when a view receives a float request. The float can be overriden + * by setting the events handled property to true. + * + * @param evt + * details the float request + */ + public void floatRequested(Event evt) { + } + + /** + * Invoked when a view receives a restore request. The restore can be + * overriden by setting the events handled property to true. + * + * @param evt + * details the restore request + */ + public void restoreRequested(Event evt) { + } + + /** + * Invoked when a user attempts to close a view. The close can be overriden + * by setting the events handled property to true. + * + * @param evt + * the event describing the view etc. + */ + public void closeRequested(Event evt) { + } + + /** + * Invoked when a view is floated. + * + * @param evt + */ + public void viewFloated(Event evt) { + // + } + + /** + * Invoked when a view is maximized. + * + * @param evt + */ + public void viewMaximized(Event evt) { + // todo implement method + } + + /** + * Invoked when a view is minimized. + * + * @param evt + */ + public void viewMinimized(Event evt) { + // todo implement method + } + + /** + * Invoked when a view is restored to its default docking position from a + * floated, minimized, or maximized state. + * + * @param evt + */ + public void viewRestored(Event evt) { + } + + /** + * Returns the list of open plot view ids + * + * @return ArrayList + */ + public java.util.List getViewList() { + return viewList; + } + + public void setActive(String tabId) { + viewManager.setActiveDockable(tabId); + } + + public void refreshViews() { + + } + + @Override + public void dockableClosed(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + + @Override + public void dockableClosing(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + + @Override + public void dockableFloating(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + + @Override + public void dockableRestoring(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + + @Override + public void dockableMinimizing(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + + @Override + public void dockableMinimized(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + + @Override + public void dockableFloated(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + + @Override + public void dockableMaximizing(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + + @Override + public void dockableMaximized(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + + @Override + public void dockableRestored(DockableFrameEvent evt) { + // TODO Auto-generated method stub + + } + +} diff --git a/festc_core/src/gov/epa/festc/core/FestcPlugin.java b/festc_core/src/gov/epa/festc/core/FestcPlugin.java index bd268c7..9e303a9 100644 --- a/festc_core/src/gov/epa/festc/core/FestcPlugin.java +++ b/festc_core/src/gov/epa/festc/core/FestcPlugin.java @@ -1,54 +1,54 @@ -package gov.epa.festc.core; - -import java.util.Properties; - -import org.apache.velocity.app.Velocity; -import org.java.plugin.Plugin; -import org.java.plugin.PluginLifecycleException; - -import saf.core.runtime.IApplicationRunnable; -import saf.core.ui.GUICreator; -import saf.core.ui.IAppConfigurator; -import saf.core.ui.ISAFDisplay; -import saf.core.ui.Workspace; -import simphony.util.messages.MessageCenter; - -public class FestcPlugin extends Plugin implements IApplicationRunnable { - - @Override - protected void doStart() throws Exception { - // TODO Auto-generated method stub - - } - - @Override - protected void doStop() throws Exception { - // TODO Auto-generated method stub - - } - - @Override - public void run(String[] arg0) { - try { - // initialize velocity - Properties p = new Properties(); - p.setProperty("resource.loader", "class"); - p.setProperty("class.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); - - p.setProperty("runtime.log", FestcConstants.APP_LOG_FILE); - Velocity.init(p); - - // The typical pattern for a SAF application is followed below. - FestcApplication festc = new FestcApplication(); - IAppConfigurator configurator = new FestcConfigurator(festc); - Workspace workspace = new Workspace(festc); - ISAFDisplay display = GUICreator.createDisplay(configurator, workspace); - - GUICreator.runDisplay(configurator, display); - } catch (Exception ex) { - MessageCenter.getMessageCenter(getClass()).error("Error", ex); - } - } - -} +package gov.epa.festc.core; + +import java.util.Properties; + +import org.apache.velocity.app.Velocity; +import org.java.plugin.Plugin; +import org.java.plugin.PluginLifecycleException; + +import saf.core.runtime.IApplicationRunnable; +import saf.core.ui.GUICreator; +import saf.core.ui.IAppConfigurator; +import saf.core.ui.ISAFDisplay; +import saf.core.ui.Workspace; +import simphony.util.messages.MessageCenter; + +public class FestcPlugin extends Plugin implements IApplicationRunnable { + + @Override + protected void doStart() throws Exception { + // TODO Auto-generated method stub + + } + + @Override + protected void doStop() throws Exception { + // TODO Auto-generated method stub + + } + + @Override + public void run(String[] arg0) { + try { + // initialize velocity + Properties p = new Properties(); + p.setProperty("resource.loader", "class"); + p.setProperty("class.resource.loader.class", + "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + + p.setProperty("runtime.log", FestcConstants.APP_LOG_FILE); + Velocity.init(p); + + // The typical pattern for a SAF application is followed below. + FestcApplication festc = new FestcApplication(); + IAppConfigurator configurator = new FestcConfigurator(festc); + Workspace workspace = new Workspace(festc); + ISAFDisplay display = GUICreator.createDisplay(configurator, workspace); + + GUICreator.runDisplay(configurator, display); + } catch (Exception ex) { + MessageCenter.getMessageCenter(getClass()).error("Error", ex); + } + } + +} diff --git a/festc_core/src/gov/epa/festc/core/Project.java b/festc_core/src/gov/epa/festc/core/Project.java index f9aba6a..1df2833 100644 --- a/festc_core/src/gov/epa/festc/core/Project.java +++ b/festc_core/src/gov/epa/festc/core/Project.java @@ -1,68 +1,68 @@ -package gov.epa.festc.core; - -import gov.epa.festc.core.proj.PageFields; - -import java.util.ArrayList; -import java.util.List; - -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlRootElement; - - -/** - * FESTC scenario's data collection. - * - * @author IE, UNC - * @version $Revision$ $Date$ - */ - -//This statement means that class "Project.java" is the root-element of our java object to xml mapping -@XmlRootElement(namespace = "gov.epa.festc.core") -public class Project { - List pageList; - - String name; - - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Project() { - pageList = new ArrayList(); - } - - public void addPage(PageFields page) { - pageList.add(page); - //System.out.print("Add field:" +page.getName() + "\n"); - - } - - public PageFields getPage(String name) { - if (name == null || name.trim().length() == 0) - return null; - - for (PageFields page : pageList) { - if (page.getName() != null && page.getName().equalsIgnoreCase(name)){ - //System.out.print("field:" +page.getName() + "\n"); - return page; - } - } - - return null; - } - - @XmlElementRef - public List getPageList() { - return pageList; - } - - public void setPageList(List pageList) { - this.pageList = pageList; - } - -} +package gov.epa.festc.core; + +import gov.epa.festc.core.proj.PageFields; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlRootElement; + + +/** + * FESTC scenario's data collection. + * + * @author IE, UNC + * @version $Revision$ $Date$ + */ + +//This statement means that class "Project.java" is the root-element of our java object to xml mapping +@XmlRootElement(namespace = "gov.epa.festc.core") +public class Project { + List pageList; + + String name; + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Project() { + pageList = new ArrayList(); + } + + public void addPage(PageFields page) { + pageList.add(page); + //System.out.print("Add field:" +page.getName() + "\n"); + + } + + public PageFields getPage(String name) { + if (name == null || name.trim().length() == 0) + return null; + + for (PageFields page : pageList) { + if (page.getName() != null && page.getName().equalsIgnoreCase(name)){ + //System.out.print("field:" +page.getName() + "\n"); + return page; + } + } + + return null; + } + + @XmlElementRef + public List getPageList() { + return pageList; + } + + public void setPageList(List pageList) { + this.pageList = pageList; + } + +} diff --git a/festc_core/src/gov/epa/festc/core/VersionInfo.java b/festc_core/src/gov/epa/festc/core/VersionInfo.java index a8cdd64..1871651 100644 --- a/festc_core/src/gov/epa/festc/core/VersionInfo.java +++ b/festc_core/src/gov/epa/festc/core/VersionInfo.java @@ -1,19 +1,19 @@ -package gov.epa.festc.core; - -/** - * NOTE: Auto-generated file. Please don't try to change. - * @version $Revision$ $Date$ - */ -public class VersionInfo { - public static final String version = "1.3"; - public static final String date = "2018-10-17"; - - public static String getVersion() { - return version; - } - - public static String getDate() { - return date; - } - +package gov.epa.festc.core; + +/** + * NOTE: Auto-generated file. Please don't try to change. + * @version $Revision$ $Date$ + */ +public class VersionInfo { + public static final String version = "2.1"; + public static final String date = "2025-05-05"; + + public static String getVersion() { + return version; + } + + public static String getDate() { + return date; + } + } \ No newline at end of file diff --git a/festc_core/src/gov/epa/festc/core/WriteVersionInfo.java b/festc_core/src/gov/epa/festc/core/WriteVersionInfo.java index 1db57b4..0efc288 100644 --- a/festc_core/src/gov/epa/festc/core/WriteVersionInfo.java +++ b/festc_core/src/gov/epa/festc/core/WriteVersionInfo.java @@ -1,44 +1,44 @@ -package gov.epa.festc.core; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.sql.Date; - -public class WriteVersionInfo { - private static String version = "1.3"; - private static String timestamp = new Date(new java.util.Date().getTime()).toString(); //in the yyyy-mm-dd format - private static String ls = System.getProperty("line.separator"); - - /** - * @param args - */ - public static void main(String[] args) { - String versionInfoClass = "package gov.epa.festc.core;" + ls + ls - + "/**" + ls - + " * NOTE: Auto-generated file. Please don't try to change." + ls - + " * @version $Revision$ $Date$" + ls - + " */" + ls - + "public class VersionInfo {" + ls - + " public static final String version = \"" + version + "\";" + ls - + " public static final String date = \"" + timestamp + "\";" + ls + ls - + " public static String getVersion() {" + ls - + " return version;" + ls - + " }" + ls + ls - + " public static String getDate() {" + ls - + " return date;" + ls - + " }" + ls + ls - + "}"; - - File file = new File(System.getProperty("user.dir") + "/../festc_core/src/gov/epa/festc/core/VersionInfo.java"); - - try { - FileWriter writer = new FileWriter(file); - writer.write(versionInfoClass); - writer.close(); - } catch (IOException e) { - System.out.println("Error writting VersionInfo.java file. " + e.getMessage()); - } - } - -} +package gov.epa.festc.core; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.sql.Date; + +public class WriteVersionInfo { + private static String version = "2.1"; + private static String timestamp = new Date(new java.util.Date().getTime()).toString(); //in the yyyy-mm-dd format + private static String ls = System.getProperty("line.separator"); + + /** + * @param args + */ + public static void main(String[] args) { + String versionInfoClass = "package gov.epa.festc.core;" + ls + ls + + "/**" + ls + + " * NOTE: Auto-generated file. Please don't try to change." + ls + + " * @version $Revision$ $Date$" + ls + + " */" + ls + + "public class VersionInfo {" + ls + + " public static final String version = \"" + version + "\";" + ls + + " public static final String date = \"" + timestamp + "\";" + ls + ls + + " public static String getVersion() {" + ls + + " return version;" + ls + + " }" + ls + ls + + " public static String getDate() {" + ls + + " return date;" + ls + + " }" + ls + ls + + "}"; + + File file = new File(System.getProperty("user.dir") + "/../festc_core/src/gov/epa/festc/core/VersionInfo.java"); + + try { + FileWriter writer = new FileWriter(file); + writer.write(versionInfoClass); + writer.close(); + } catch (IOException e) { + System.out.println("Error writting VersionInfo.java file. " + e.getMessage()); + } + } + +} diff --git a/festc_core/src/gov/epa/festc/core/action/About.java b/festc_core/src/gov/epa/festc/core/action/About.java index c83353c..822e1d9 100644 --- a/festc_core/src/gov/epa/festc/core/action/About.java +++ b/festc_core/src/gov/epa/festc/core/action/About.java @@ -1,32 +1,32 @@ -package gov.epa.festc.core.action; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.gui.AboutDialog; - -import java.awt.event.ActionEvent; - -import javax.swing.JFrame; - -import saf.core.ui.actions.AbstractSAFAction; - -/** - * Action to show the about dialog. - * - * @author IE, UNC - * @version $Revision$ $Date$ - */ -public class About extends AbstractSAFAction { - - private static final long serialVersionUID = 4707751873774402860L; - - /** - * Invoked when an action occurs. - */ - public void actionPerformed(ActionEvent e) { - JFrame frame = workspace.getApplicationMediator().getGui().getFrame(); - AboutDialog dialog = new AboutDialog(frame); - dialog.pack(); - dialog.setLocationRelativeTo(frame); - dialog.setVisible(true); - } -} +package gov.epa.festc.core.action; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.gui.AboutDialog; + +import java.awt.event.ActionEvent; + +import javax.swing.JFrame; + +import saf.core.ui.actions.AbstractSAFAction; + +/** + * Action to show the about dialog. + * + * @author IE, UNC + * @version $Revision$ $Date$ + */ +public class About extends AbstractSAFAction { + + private static final long serialVersionUID = 4707751873774402860L; + + /** + * Invoked when an action occurs. + */ + public void actionPerformed(ActionEvent e) { + JFrame frame = workspace.getApplicationMediator().getGui().getFrame(); + AboutDialog dialog = new AboutDialog(frame); + dialog.pack(); + dialog.setLocationRelativeTo(frame); + dialog.setVisible(true); + } +} diff --git a/festc_core/src/gov/epa/festc/core/action/CopyAction.java b/festc_core/src/gov/epa/festc/core/action/CopyAction.java index f3394d1..fe60d16 100644 --- a/festc_core/src/gov/epa/festc/core/action/CopyAction.java +++ b/festc_core/src/gov/epa/festc/core/action/CopyAction.java @@ -1,34 +1,34 @@ -package gov.epa.festc.core.action; - -import gov.epa.festc.core.FestcApplication; - -import java.awt.event.ActionEvent; - -import javax.swing.JOptionPane; - -import saf.core.ui.actions.AbstractSAFAction; - -/** - * Action for opening files. - * - * @author Qun He - * @version $Revision$ $Date$ - */ -public class CopyAction extends AbstractSAFAction { - private static final long serialVersionUID = 2948227677960767437L; - - /** - * Invoked when an action occurs. - */ - public void actionPerformed(ActionEvent e) { - FestcApplication app = workspace.getApplicationMediator(); - if ( app.getProjFile() != null ){ -// int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); -// if ( option == 0 ) - app.saveProject(); - app.copyProject(); - } - else - app.copyProject(); - } -} +package gov.epa.festc.core.action; + +import gov.epa.festc.core.FestcApplication; + +import java.awt.event.ActionEvent; + +import javax.swing.JOptionPane; + +import saf.core.ui.actions.AbstractSAFAction; + +/** + * Action for opening files. + * + * @author Qun He + * @version $Revision$ $Date$ + */ +public class CopyAction extends AbstractSAFAction { + private static final long serialVersionUID = 2948227677960767437L; + + /** + * Invoked when an action occurs. + */ + public void actionPerformed(ActionEvent e) { + FestcApplication app = workspace.getApplicationMediator(); + if ( app.getProjFile() != null ){ +// int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); +// if ( option == 0 ) + app.saveProject(); + app.copyProject(); + } + else + app.copyProject(); + } +} diff --git a/festc_core/src/gov/epa/festc/core/action/CreateAction.java b/festc_core/src/gov/epa/festc/core/action/CreateAction.java index 15ec5a5..6af232a 100644 --- a/festc_core/src/gov/epa/festc/core/action/CreateAction.java +++ b/festc_core/src/gov/epa/festc/core/action/CreateAction.java @@ -1,34 +1,34 @@ -package gov.epa.festc.core.action; - -import gov.epa.festc.core.FestcApplication; - -import java.awt.event.ActionEvent; - -import javax.swing.JOptionPane; - -import saf.core.ui.actions.AbstractSAFAction; - -/** - * Action for opening files. - * - * @author Nick Collier - * @version $Revision$ $Date$ - */ -public class CreateAction extends AbstractSAFAction { - private static final long serialVersionUID = 2948227677960767437L; - - /** - * Invoked when an action occurs. - */ - public void actionPerformed(ActionEvent e) { - FestcApplication app = workspace.getApplicationMediator(); - if ( app.getProjFile() != null ){ -// int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); -// if ( option == 0 ) - app.saveProject(); - app.createProject(); - } - else - app.createProject(); - } -} +package gov.epa.festc.core.action; + +import gov.epa.festc.core.FestcApplication; + +import java.awt.event.ActionEvent; + +import javax.swing.JOptionPane; + +import saf.core.ui.actions.AbstractSAFAction; + +/** + * Action for opening files. + * + * @author Nick Collier + * @version $Revision$ $Date$ + */ +public class CreateAction extends AbstractSAFAction { + private static final long serialVersionUID = 2948227677960767437L; + + /** + * Invoked when an action occurs. + */ + public void actionPerformed(ActionEvent e) { + FestcApplication app = workspace.getApplicationMediator(); + if ( app.getProjFile() != null ){ +// int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); +// if ( option == 0 ) + app.saveProject(); + app.createProject(); + } + else + app.createProject(); + } +} diff --git a/festc_core/src/gov/epa/festc/core/action/DeleteAction.java b/festc_core/src/gov/epa/festc/core/action/DeleteAction.java index 8443250..fa40709 100644 --- a/festc_core/src/gov/epa/festc/core/action/DeleteAction.java +++ b/festc_core/src/gov/epa/festc/core/action/DeleteAction.java @@ -1,24 +1,24 @@ -package gov.epa.festc.core.action; - -import gov.epa.festc.core.FestcApplication; - -import java.awt.event.ActionEvent; - -import saf.core.ui.actions.AbstractSAFAction; - -/** - * Action for opening files. - * - * @author Qun He - * @version $Revision$ $Date$ - */ -public class DeleteAction extends AbstractSAFAction { - private static final long serialVersionUID = 2948227677960767437L; - - /** - * Invoked when an action occurs. - */ - public void actionPerformed(ActionEvent e) { - workspace.getApplicationMediator().deleteProject(); - } -} +package gov.epa.festc.core.action; + +import gov.epa.festc.core.FestcApplication; + +import java.awt.event.ActionEvent; + +import saf.core.ui.actions.AbstractSAFAction; + +/** + * Action for opening files. + * + * @author Qun He + * @version $Revision$ $Date$ + */ +public class DeleteAction extends AbstractSAFAction { + private static final long serialVersionUID = 2948227677960767437L; + + /** + * Invoked when an action occurs. + */ + public void actionPerformed(ActionEvent e) { + workspace.getApplicationMediator().deleteProject(); + } +} diff --git a/festc_core/src/gov/epa/festc/core/action/ExitAction.java b/festc_core/src/gov/epa/festc/core/action/ExitAction.java index 1a5c51a..4453a05 100644 --- a/festc_core/src/gov/epa/festc/core/action/ExitAction.java +++ b/festc_core/src/gov/epa/festc/core/action/ExitAction.java @@ -1,31 +1,31 @@ -package gov.epa.festc.core.action; - -import gov.epa.festc.core.FestcApplication; - -import java.awt.event.ActionEvent; - -import javax.swing.JOptionPane; - -import saf.core.ui.actions.AbstractSAFAction; - -/** - * Action for exit files. - * - * @version $Revision$ $Date$ - */ -public class ExitAction extends AbstractSAFAction { - private static final long serialVersionUID = 4008068827373247119L; - - /** - * Invoked when an action occurs. - */ - public void actionPerformed(ActionEvent e) { - FestcApplication app = workspace.getApplicationMediator(); - if ( app.getProjFile() != null ){ - // int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); - // if ( option == 0 ) - app.saveProject(); - } - System.exit(0); - } -} +package gov.epa.festc.core.action; + +import gov.epa.festc.core.FestcApplication; + +import java.awt.event.ActionEvent; + +import javax.swing.JOptionPane; + +import saf.core.ui.actions.AbstractSAFAction; + +/** + * Action for exit files. + * + * @version $Revision$ $Date$ + */ +public class ExitAction extends AbstractSAFAction { + private static final long serialVersionUID = 4008068827373247119L; + + /** + * Invoked when an action occurs. + */ + public void actionPerformed(ActionEvent e) { + FestcApplication app = workspace.getApplicationMediator(); + if ( app.getProjFile() != null ){ + // int option = JOptionPane.showConfirmDialog(null, "Do you want to save scenario? ", "Confirmation", JOptionPane.YES_NO_OPTION); + // if ( option == 0 ) + app.saveProject(); + } + System.exit(0); + } +} diff --git a/festc_core/src/gov/epa/festc/core/action/Help.java b/festc_core/src/gov/epa/festc/core/action/Help.java index 2ee2ff5..33e7c18 100644 --- a/festc_core/src/gov/epa/festc/core/action/Help.java +++ b/festc_core/src/gov/epa/festc/core/action/Help.java @@ -1,25 +1,25 @@ -package gov.epa.festc.core.action; - -import gov.epa.festc.core.FestcApplication; - -import java.awt.event.ActionEvent; - -import saf.core.ui.actions.AbstractSAFAction; - -/** - * Action to show the help - * - * @author IE, UNC - * @version $Revision$ $Date$ - */ -public class Help extends AbstractSAFAction { - - private static final long serialVersionUID = -6430759498830546714L; - - /** - * Invoked when an action occurs. - */ - public void actionPerformed(ActionEvent e) { - workspace.getApplicationMediator().showHelp(); - } -} +package gov.epa.festc.core.action; + +import gov.epa.festc.core.FestcApplication; + +import java.awt.event.ActionEvent; + +import saf.core.ui.actions.AbstractSAFAction; + +/** + * Action to show the help + * + * @author IE, UNC + * @version $Revision$ $Date$ + */ +public class Help extends AbstractSAFAction { + + private static final long serialVersionUID = -6430759498830546714L; + + /** + * Invoked when an action occurs. + */ + public void actionPerformed(ActionEvent e) { + workspace.getApplicationMediator().showHelp(); + } +} diff --git a/festc_core/src/gov/epa/festc/core/action/OpenAction.java b/festc_core/src/gov/epa/festc/core/action/OpenAction.java index c2c5735..471cd3c 100644 --- a/festc_core/src/gov/epa/festc/core/action/OpenAction.java +++ b/festc_core/src/gov/epa/festc/core/action/OpenAction.java @@ -1,24 +1,24 @@ -package gov.epa.festc.core.action; - -import gov.epa.festc.core.FestcApplication; - -import java.awt.event.ActionEvent; - -import saf.core.ui.actions.AbstractSAFAction; - -/** - * Action for opening files. - * - * @author Nick Collier - * @version $Revision$ $Date$ - */ -public class OpenAction extends AbstractSAFAction { - private static final long serialVersionUID = 2948227677960767437L; - - /** - * Invoked when an action occurs. - */ - public void actionPerformed(ActionEvent e) { - workspace.getApplicationMediator().openProject(); - } -} +package gov.epa.festc.core.action; + +import gov.epa.festc.core.FestcApplication; + +import java.awt.event.ActionEvent; + +import saf.core.ui.actions.AbstractSAFAction; + +/** + * Action for opening files. + * + * @author Nick Collier + * @version $Revision$ $Date$ + */ +public class OpenAction extends AbstractSAFAction { + private static final long serialVersionUID = 2948227677960767437L; + + /** + * Invoked when an action occurs. + */ + public void actionPerformed(ActionEvent e) { + workspace.getApplicationMediator().openProject(); + } +} diff --git a/festc_core/src/gov/epa/festc/core/action/SaveAction.java b/festc_core/src/gov/epa/festc/core/action/SaveAction.java index 16cd8ac..0598578 100644 --- a/festc_core/src/gov/epa/festc/core/action/SaveAction.java +++ b/festc_core/src/gov/epa/festc/core/action/SaveAction.java @@ -1,23 +1,23 @@ -package gov.epa.festc.core.action; - -import gov.epa.festc.core.FestcApplication; - -import java.awt.event.ActionEvent; - -import saf.core.ui.actions.AbstractSAFAction; - -/** - * Action for opening files. - * - * @version $Revision$ $Date$ - */ -public class SaveAction extends AbstractSAFAction { - private static final long serialVersionUID = 8373565559359050502L; - - /** - * Invoked when an action occurs. - */ - public void actionPerformed(ActionEvent e) { - workspace.getApplicationMediator().saveProject(); - } -} +package gov.epa.festc.core.action; + +import gov.epa.festc.core.FestcApplication; + +import java.awt.event.ActionEvent; + +import saf.core.ui.actions.AbstractSAFAction; + +/** + * Action for opening files. + * + * @version $Revision$ $Date$ + */ +public class SaveAction extends AbstractSAFAction { + private static final long serialVersionUID = 8373565559359050502L; + + /** + * Invoked when an action occurs. + */ + public void actionPerformed(ActionEvent e) { + workspace.getApplicationMediator().saveProject(); + } +} diff --git a/festc_core/src/gov/epa/festc/core/proj/Beld4DataGenFields.java b/festc_core/src/gov/epa/festc/core/proj/Beld4DataGenFields.java index f5cb05b..f99de50 100644 --- a/festc_core/src/gov/epa/festc/core/proj/Beld4DataGenFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/Beld4DataGenFields.java @@ -1,46 +1,46 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - - -@XmlRootElement(name = "gov.epa.festc.core.proj.Beld4DataGenFields") - -public class Beld4DataGenFields extends DomainFields{ - //private String nlcdYear; - private String nlcdFile; - private boolean nlcdDataSelected; - private boolean modisDataSelected; - - public Beld4DataGenFields() { - //NOTE: no-op - } - - public void setNLCDfile(String nlcdFile) { - this.nlcdFile = nlcdFile; - } - public String getNLCDfile() { - return nlcdFile; - } - - public boolean isNlcdDataSelected() { - return nlcdDataSelected; - } - - public void setNlcdDataSelected(boolean nlcdDataSelected) { - this.nlcdDataSelected = nlcdDataSelected; - } - - public boolean isModisDataSelected() { - return modisDataSelected; - } - - public void setModisDataSelected(boolean modisDataSelected) { - this.modisDataSelected = modisDataSelected; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return Beld4DataGenFields.class.getCanonicalName(); - } -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + + +@XmlRootElement(name = "gov.epa.festc.core.proj.Beld4DataGenFields") + +public class Beld4DataGenFields extends DomainFields{ + //private String nlcdYear; + private String nlcdFile; + private boolean nlcdDataSelected; + private boolean modisDataSelected; + + public Beld4DataGenFields() { + //NOTE: no-op + } + + public void setNLCDfile(String nlcdFile) { + this.nlcdFile = nlcdFile; + } + public String getNLCDfile() { + return nlcdFile; + } + + public boolean isNlcdDataSelected() { + return nlcdDataSelected; + } + + public void setNlcdDataSelected(boolean nlcdDataSelected) { + this.nlcdDataSelected = nlcdDataSelected; + } + + public boolean isModisDataSelected() { + return modisDataSelected; + } + + public void setModisDataSelected(boolean modisDataSelected) { + this.modisDataSelected = modisDataSelected; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return Beld4DataGenFields.class.getCanonicalName(); + } +} diff --git a/festc_core/src/gov/epa/festc/core/proj/DomainFields.java b/festc_core/src/gov/epa/festc/core/proj/DomainFields.java index 2b9d003..43a2608 100644 --- a/festc_core/src/gov/epa/festc/core/proj/DomainFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/DomainFields.java @@ -1,62 +1,71 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.DomainFields") -public class DomainFields extends PageFields { - - protected String simYear; - protected String nlcdYear; - protected String cfertYear; - protected String cminAcres; - //protected String csimYear; - - - public String getCMinAcres() { - return cminAcres; - } - - public String getCFertYear() { - return cfertYear; - } - - public String getSimYear() { - return simYear; - } - - public String getNlcdYear() { - return nlcdYear; - } - - - public void setCMinAcres(String acres) { - this.cminAcres = acres; - } - - public void setCFertYear(String cfertYear) { - this.cfertYear = cfertYear; - } - - public void setSimYear(String year) { - this.simYear = year; - } - - public void setNlcdYear(String year) { - this.nlcdYear = year; - } - - public void setNlcdYear() { - Integer sYear = Integer.parseInt(simYear); - if ( sYear < 2006 ) this.nlcdYear = "2001"; - if ( sYear >= 2006 ) this.nlcdYear = "2006"; // sYear >= 2006 && sYear < 2011 - //if ( sYear >= 2011 ) this.nlcdYear = "2011"; - } - - - @Override - public String getName() { - // TODO Auto-generated method stub - return DomainFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.DomainFields") +public class DomainFields extends PageFields { + + protected String simYear; + protected String simEndYear; + protected String nlcdYear; + protected String cfertYear; + protected String cminAcres; + //protected String csimYear; + + + public String getCMinAcres() { + return cminAcres; + } + + public String getCFertYear() { + return cfertYear; + } + + public String getSimYear() { + return simYear; + } + + public String getSimEndYear() { + return simEndYear; + } + + public String getNlcdYear() { + return nlcdYear; + } + + + public void setCMinAcres(String acres) { + this.cminAcres = acres; + } + + public void setCFertYear(String cfertYear) { + this.cfertYear = cfertYear; + } + + public void setSimYear(String year) { + this.simYear = year; + } + + public void setSimEndYear(String year) { + this.simEndYear = year; + } + + public void setNlcdYear(String year) { + this.nlcdYear = year; + } + + public void setNlcdYear() { + Integer sYear = Integer.parseInt(simYear); + if ( sYear < 2006 ) this.nlcdYear = "2001"; + if ( sYear >= 2006 ) this.nlcdYear = "2006"; // sYear >= 2006 && sYear < 2011 + //if ( sYear >= 2011 ) this.nlcdYear = "2011"; + } + + + @Override + public String getName() { + // TODO Auto-generated method stub + return DomainFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/Epic2CMAQFields.java b/festc_core/src/gov/epa/festc/core/proj/Epic2CMAQFields.java index acfb417..f8e1736 100644 --- a/festc_core/src/gov/epa/festc/core/proj/Epic2CMAQFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/Epic2CMAQFields.java @@ -1,50 +1,50 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -//import gov.epa.festc.gui.Epic2CMAQPanel; - -@XmlRootElement(name = "gov.epa.festc.core.proj.Epic2CMAQFields") -public class Epic2CMAQFields extends PageFields{ - - private String startdate; - private String enddate; - - private String outfileprefix; - - public Epic2CMAQFields() { - //NOTE: no-op - } - - public String getStartdate() { - return startdate; - } - - public void setStartdate(String startdate) { - this.startdate = startdate; - } - - public String getEnddate() { - return enddate; - } - - public void setEnddate(String enddate) { - this.enddate = enddate; - } - - public String getOutfileprefix() { - return outfileprefix; - } - - public void setOutfileprefix(String outfileprefix) { - this.outfileprefix = outfileprefix; - } - - - @Override - public String getName() { - return Epic2CMAQFields.class.getCanonicalName(); - } - - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +//import gov.epa.festc.gui.Epic2CMAQPanel; + +@XmlRootElement(name = "gov.epa.festc.core.proj.Epic2CMAQFields") +public class Epic2CMAQFields extends PageFields{ + + private String startdate; + private String enddate; + + private String outfileprefix; + + public Epic2CMAQFields() { + //NOTE: no-op + } + + public String getStartdate() { + return startdate; + } + + public void setStartdate(String startdate) { + this.startdate = startdate; + } + + public String getEnddate() { + return enddate; + } + + public void setEnddate(String enddate) { + this.enddate = enddate; + } + + public String getOutfileprefix() { + return outfileprefix; + } + + public void setOutfileprefix(String outfileprefix) { + this.outfileprefix = outfileprefix; + } + + + @Override + public String getName() { + return Epic2CMAQFields.class.getCanonicalName(); + } + + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/Epic2SWATFields.java b/festc_core/src/gov/epa/festc/core/proj/Epic2SWATFields.java index 7f7c7d0..ce487c2 100644 --- a/festc_core/src/gov/epa/festc/core/proj/Epic2SWATFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/Epic2SWATFields.java @@ -1,73 +1,73 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -import gov.epa.festc.gui.Epic2CMAQPanel; - -@XmlRootElement(name = "gov.epa.festc.core.proj.Epic2SWATFields") -public class Epic2SWATFields extends PageFields{ - - private String beld4ncf; - private String metdep; - private String nDepSelection; - private String hucSelection; - private String ratioFile; - private String outfileprefix; - - public Epic2SWATFields() { - //NOTE: no-op - } - - public String getNDepSelection() { - return nDepSelection; - } - - public void setNDepSelection(String nDepSelection) { - this.nDepSelection = nDepSelection; - } - - public String getHucSelection() { - return hucSelection; - } - - public void setHucSelection(String hucSelection) { - this.hucSelection = hucSelection; - } - - public String getRatioFile() { - return ratioFile; - } - - public void setRatioFile(String ratioFile) { - this.ratioFile = ratioFile; - } - - public void setBeld4ncf(String beld4ncf) { - this.beld4ncf = beld4ncf; - } - public String getBeld4ncf() { - return beld4ncf; - } - - public void setMetdep(String metdep) { - this.metdep = metdep; - } - public String getMetdep() { - return metdep; - } - - public String getOutfileprefix() { - return outfileprefix; - } - - public void setOutfileprefix(String outfileprefix) { - this.outfileprefix = outfileprefix; - } - - - @Override - public String getName() { - return Epic2SWATFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +import gov.epa.festc.gui.Epic2CMAQPanel; + +@XmlRootElement(name = "gov.epa.festc.core.proj.Epic2SWATFields") +public class Epic2SWATFields extends PageFields{ + + private String beld4ncf; + private String metdep; + private String nDepSelection; + private String hucSelection; + private String ratioFile; + private String outfileprefix; + + public Epic2SWATFields() { + //NOTE: no-op + } + + public String getNDepSelection() { + return nDepSelection; + } + + public void setNDepSelection(String nDepSelection) { + this.nDepSelection = nDepSelection; + } + + public String getHucSelection() { + return hucSelection; + } + + public void setHucSelection(String hucSelection) { + this.hucSelection = hucSelection; + } + + public String getRatioFile() { + return ratioFile; + } + + public void setRatioFile(String ratioFile) { + this.ratioFile = ratioFile; + } + + public void setBeld4ncf(String beld4ncf) { + this.beld4ncf = beld4ncf; + } + public String getBeld4ncf() { + return beld4ncf; + } + + public void setMetdep(String metdep) { + this.metdep = metdep; + } + public String getMetdep() { + return metdep; + } + + public String getOutfileprefix() { + return outfileprefix; + } + + public void setOutfileprefix(String outfileprefix) { + this.outfileprefix = outfileprefix; + } + + + @Override + public String getName() { + return Epic2SWATFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/EpicAppFields.java b/festc_core/src/gov/epa/festc/core/proj/EpicAppFields.java index b4d3372..f6144cc 100644 --- a/festc_core/src/gov/epa/festc/core/proj/EpicAppFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/EpicAppFields.java @@ -1,55 +1,55 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.EpicAppFields") -public class EpicAppFields extends DomainFields { - - private String finishedCrops; - //private String simYear; - private String nDepDir; - private String co2Fac; - private String runTiledrain; - - public EpicAppFields() { - //NOTE: no-op - } - - public String getFinishedCrops() { - return finishedCrops; - } - - public void setFinishedCrops(String finishedCrops) { - this.finishedCrops = finishedCrops; - } - - public String getNDepDir() { - return nDepDir; - } - - public void setNDepDir(String nDepDir) { - this.nDepDir = nDepDir; - } - - public void setCO2Fac(String co2fac) { - this.co2Fac = co2fac; - } - public String getCO2Fac() { - return co2Fac; - } - - public void setRunTiledrain(String runTiledrain) { - this.runTiledrain = runTiledrain; - } - - public String getRunTiledrain() { - return runTiledrain; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return EpicAppFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.EpicAppFields") +public class EpicAppFields extends DomainFields { + + private String finishedCrops; + //private String simYear; + private String nDepDir; + private String co2Fac; + private String runTiledrain; + + public EpicAppFields() { + //NOTE: no-op + } + + public String getFinishedCrops() { + return finishedCrops; + } + + public void setFinishedCrops(String finishedCrops) { + this.finishedCrops = finishedCrops; + } + + public String getNDepDir() { + return nDepDir; + } + + public void setNDepDir(String nDepDir) { + this.nDepDir = nDepDir; + } + + public void setCO2Fac(String co2fac) { + this.co2Fac = co2fac; + } + public String getCO2Fac() { + return co2Fac; + } + + public void setRunTiledrain(String runTiledrain) { + this.runTiledrain = runTiledrain; + } + + public String getRunTiledrain() { + return runTiledrain; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return EpicAppFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/EpicSpinupFields.java b/festc_core/src/gov/epa/festc/core/proj/EpicSpinupFields.java index 2765ab6..ae335bd 100644 --- a/festc_core/src/gov/epa/festc/core/proj/EpicSpinupFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/EpicSpinupFields.java @@ -1,53 +1,53 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.EpicSpinupFields") -public class EpicSpinupFields extends DomainFields { - - private String finishedCrops; - private String nDepDir; - private String co2Fac; - private String runTiledrain; - public EpicSpinupFields() { - //NOTE: no-op - } - - public String getFinishedCrops() { - return finishedCrops; - } - - public void setFinishedCrops(String finishedCrops) { - this.finishedCrops = finishedCrops; - } - - public String getNDepDir() { - return nDepDir; - } - - public void setRunTiledrain(String runTiledrain) { - this.runTiledrain = runTiledrain; - } - - public String getRunTiledrain() { - return runTiledrain; - } - - public void setNDepDir(String nDepDir) { - this.nDepDir = nDepDir; - } - - public void setCO2Fac(String co2fac) { - this.co2Fac = co2fac; - } - public String getCO2Fac() { - return co2Fac; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return EpicSpinupFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.EpicSpinupFields") +public class EpicSpinupFields extends DomainFields { + + private String finishedCrops; + private String nDepDir; + private String co2Fac; + private String runTiledrain; + public EpicSpinupFields() { + //NOTE: no-op + } + + public String getFinishedCrops() { + return finishedCrops; + } + + public void setFinishedCrops(String finishedCrops) { + this.finishedCrops = finishedCrops; + } + + public String getNDepDir() { + return nDepDir; + } + + public void setRunTiledrain(String runTiledrain) { + this.runTiledrain = runTiledrain; + } + + public String getRunTiledrain() { + return runTiledrain; + } + + public void setNDepDir(String nDepDir) { + this.nDepDir = nDepDir; + } + + public void setCO2Fac(String co2fac) { + this.co2Fac = co2fac; + } + public String getCO2Fac() { + return co2Fac; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return EpicSpinupFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/ManFileModFields.java b/festc_core/src/gov/epa/festc/core/proj/ManFileModFields.java index 415e406..030c63c 100644 --- a/festc_core/src/gov/epa/festc/core/proj/ManFileModFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/ManFileModFields.java @@ -1,18 +1,18 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.ManFileModFields") -public class ManFileModFields extends PageFields{ - - public ManFileModFields() { - //NOTE: no-op - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return ManFileModFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.ManFileModFields") +public class ManFileModFields extends PageFields{ + + public ManFileModFields() { + //NOTE: no-op + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return ManFileModFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/ManageAppFields.java b/festc_core/src/gov/epa/festc/core/proj/ManageAppFields.java index 1275c4a..c4a56c2 100644 --- a/festc_core/src/gov/epa/festc/core/proj/ManageAppFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/ManageAppFields.java @@ -1,28 +1,28 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.ManageAppFields") -public class ManageAppFields extends DomainFields { - - private String fertYear; - - public ManageAppFields() { - //NOTE: no-op - } - - public String getFertYear() { - return fertYear; - } - - public void setFertYear(String fertYear) { - this.fertYear = fertYear; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return ManageAppFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.ManageAppFields") +public class ManageAppFields extends DomainFields { + + private String fertYear; + + public ManageAppFields() { + //NOTE: no-op + } + + public String getFertYear() { + return fertYear; + } + + public void setFertYear(String fertYear) { + this.fertYear = fertYear; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return ManageAppFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/ManageSpinupFields.java b/festc_core/src/gov/epa/festc/core/proj/ManageSpinupFields.java index d4c8c7c..39844f2 100644 --- a/festc_core/src/gov/epa/festc/core/proj/ManageSpinupFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/ManageSpinupFields.java @@ -1,28 +1,28 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.ManageSpinupFields") -public class ManageSpinupFields extends DomainFields { - - private String fertYear; // used for check consistent with app - - public ManageSpinupFields() { - //NOTE: no-op - } - - public String getFertYear() { - return fertYear; - } - - public void setFertYear(String fertYear) { - this.fertYear = fertYear; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return ManageSpinupFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.ManageSpinupFields") +public class ManageSpinupFields extends DomainFields { + + private String fertYear; // used for check consistent with app + + public ManageSpinupFields() { + //NOTE: no-op + } + + public String getFertYear() { + return fertYear; + } + + public void setFertYear(String fertYear) { + this.fertYear = fertYear; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return ManageSpinupFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/Mcip2EpicFields.java b/festc_core/src/gov/epa/festc/core/proj/Mcip2EpicFields.java index 9d92f9c..a83adac 100644 --- a/festc_core/src/gov/epa/festc/core/proj/Mcip2EpicFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/Mcip2EpicFields.java @@ -1,73 +1,73 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.Mcip2EpicFields") -public class Mcip2EpicFields extends PageFields{ - - private String startdate; - private String enddate; - private String mcipDataDir; - private String depSelection; - private String cmaqDepsDir; - - public Mcip2EpicFields() { - //NOTE: no-op - } - - public String getStartdate() { - return startdate; - } - - public void setStartdate(String startdate) { - this.startdate = startdate; - } - - public String getEnddate() { - return enddate; - } - - public void setEnddate(String enddate) { - this.enddate = enddate; - } - - public String getDatadir() { - return mcipDataDir; - } - - public void setDatadir(String datadir) { - this.mcipDataDir = datadir; - } - - public String getCmaqDepsDir() { - return cmaqDepsDir; - } - - public void setCmaqDepsDir(String cmaqDepsDir) { - this.cmaqDepsDir = cmaqDepsDir; - } - - public String getDepSelection() { - return depSelection; - } - - public void setDepSelection(String depSelection) { - this.depSelection = depSelection; - } - - - public void setGridName(String gridName) { - this.gridName = gridName; - } - - public String getGridName() { - return gridName; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return Mcip2EpicFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.Mcip2EpicFields") +public class Mcip2EpicFields extends PageFields{ + + private String startdate; + private String enddate; + private String mcipDataDir; + private String depSelection; + private String cmaqDepsDir; + + public Mcip2EpicFields() { + //NOTE: no-op + } + + public String getStartdate() { + return startdate; + } + + public void setStartdate(String startdate) { + this.startdate = startdate; + } + + public String getEnddate() { + return enddate; + } + + public void setEnddate(String enddate) { + this.enddate = enddate; + } + + public String getDatadir() { + return mcipDataDir; + } + + public void setDatadir(String datadir) { + this.mcipDataDir = datadir; + } + + public String getCmaqDepsDir() { + return cmaqDepsDir; + } + + public void setCmaqDepsDir(String cmaqDepsDir) { + this.cmaqDepsDir = cmaqDepsDir; + } + + public String getDepSelection() { + return depSelection; + } + + public void setDepSelection(String depSelection) { + this.depSelection = depSelection; + } + + + public void setGridName(String gridName) { + this.gridName = gridName; + } + + public String getGridName() { + return gridName; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return Mcip2EpicFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/PageFields.java b/festc_core/src/gov/epa/festc/core/proj/PageFields.java index 4878fb5..dc40cab 100644 --- a/festc_core/src/gov/epa/festc/core/proj/PageFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/PageFields.java @@ -1,84 +1,84 @@ -package gov.epa.festc.core.proj; - -public abstract class PageFields { - protected String message; - protected String scenarioDir; - - protected int rows; - protected int cols; - protected float xcellsize; - protected float ycellsize; - protected float xmin; - protected float ymin; - - protected String proj4projection; - protected String gridName; - - public String getMessage() { - return message; - } - - public void setMessage(String msg) { - this.message = msg; - } - - public void setScenarioDir(String scenarioDir) { - this.scenarioDir = scenarioDir; - } - - public String getScenarioDir() { - return scenarioDir; - } - - public void setRows(int rows) { - this.rows = rows; - } - public int getRows() { - return rows; - } - public void setCols(int cols) { - this.cols = cols; - } - public int getCols() { - return cols; - } - public void setXcellSize(float xcellsize) { - this.xcellsize = xcellsize; - } - public float getXcellSize() { - return xcellsize; - } - public void setYcellSize(float ycellsize) { - this.ycellsize = ycellsize; - } - public float getYcellSize() { - return ycellsize; - } - public void setXmin(float xmin) { - this.xmin = xmin; - } - public float getXmin() { - return xmin; - } - public void setYmin(float ymin) { - this.ymin = ymin; - } - public float getYmin() { - return ymin; - } - - public void setProj(String proj) { - this.proj4projection = proj; - } - public String getProj() { - return proj4projection; - } - public void setGridName(String gridName) { - this.gridName = gridName; - } - public String getGridName() { - return gridName; - } - - public abstract String getName(); -} +package gov.epa.festc.core.proj; + +public abstract class PageFields { + protected String message; + protected String scenarioDir; + + protected int rows; + protected int cols; + protected float xcellsize; + protected float ycellsize; + protected float xmin; + protected float ymin; + + protected String proj4projection; + protected String gridName; + + public String getMessage() { + return message; + } + + public void setMessage(String msg) { + this.message = msg; + } + + public void setScenarioDir(String scenarioDir) { + this.scenarioDir = scenarioDir; + } + + public String getScenarioDir() { + return scenarioDir; + } + + public void setRows(int rows) { + this.rows = rows; + } + public int getRows() { + return rows; + } + public void setCols(int cols) { + this.cols = cols; + } + public int getCols() { + return cols; + } + public void setXcellSize(float xcellsize) { + this.xcellsize = xcellsize; + } + public float getXcellSize() { + return xcellsize; + } + public void setYcellSize(float ycellsize) { + this.ycellsize = ycellsize; + } + public float getYcellSize() { + return ycellsize; + } + public void setXmin(float xmin) { + this.xmin = xmin; + } + public float getXmin() { + return xmin; + } + public void setYmin(float ymin) { + this.ymin = ymin; + } + public float getYmin() { + return ymin; + } + + public void setProj(String proj) { + this.proj4projection = proj; + } + public String getProj() { + return proj4projection; + } + public void setGridName(String gridName) { + this.gridName = gridName; + } + public String getGridName() { + return gridName; + } + + public abstract String getName(); +} diff --git a/festc_core/src/gov/epa/festc/core/proj/ProjectLoader.java b/festc_core/src/gov/epa/festc/core/proj/ProjectLoader.java index 5d5ee68..ac35a57 100644 --- a/festc_core/src/gov/epa/festc/core/proj/ProjectLoader.java +++ b/festc_core/src/gov/epa/festc/core/proj/ProjectLoader.java @@ -1,76 +1,76 @@ -package gov.epa.festc.core.proj; - -import gov.epa.festc.core.Project; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; - -/** - * Saves elements of the application to disk so they can be loaded later. - * - * @author IE, UNC Chapel Hill - * @version $Revision$ $Date$ - */ -public class ProjectLoader { - private JAXBContext context; - private Marshaller m; - private Unmarshaller um; - - public ProjectLoader() throws JAXBException { - // create JAXB context and instantiate marshaller/unmarshaller - // SiteInfoGenFields: EPIC Site Info: - // Mcip2EpicFields: MCIP/EPIC to EPIC - - // SiteFilesFields : EPIC Site file generation ( run two executables ) - // SoilFilesFields : EPIC Soil file generation ( run soil match) - // ManageSpinupFields: Management file generation for spinup - // ManFileModFields: View/Edit EPIC Inputs - // EpicSpinupFields : Epic runs for spinup - // EpicYearlyAverage2CMAQFields: EPIC Yearly Output - // Epic2CMAQFields: - // Epic2SWATFields: - context = JAXBContext.newInstance(Project.class, Beld4DataGenFields.class, Mcip2EpicFields.class, SiteFilesFields.class, - SoilFilesFields.class, ManageSpinupFields.class, ManFileModFields.class, EpicSpinupFields.class, - EpicYearlyAverage2CMAQFields.class, ManageAppFields.class, EpicAppFields.class, - VisualizationFields.class, SiteInfoGenFields.class, Epic2CMAQFields.class, - Epic2SWATFields.class,DomainFields.class); - m = context.createMarshaller(); - m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); - um = context.createUnmarshaller(); - } - - /** - * Saves the specified project to the specified file. - * - * @param file the file to save the model to - * @param project the project to save - * @throws IOException if there is an error duing saving - * @throws JAXBException - * @throws JAXBException if the xml mapping error occurs - */ - public void save(File file, Project project) throws IOException, JAXBException { - m.marshal(project, file); - } - - /** - * Loads the project data in specified file into the - * specified project. - * - * @param file the file containing the data to load - * @param project the project to load the data into - * @param manager used to create the Datasets - * @param creator the creator used to properly create the formula items - * @throws IOException if there is an error during loading. - * @throws JAXBException if the xml mapping error occurs - */ - public void load(File file, Project project) throws JAXBException, IOException { - Project loaded = (Project) um.unmarshal(new FileReader(file)); - project.setPageList(loaded.getPageList()); - } -} +package gov.epa.festc.core.proj; + +import gov.epa.festc.core.Project; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + +/** + * Saves elements of the application to disk so they can be loaded later. + * + * @author IE, UNC Chapel Hill + * @version $Revision$ $Date$ + */ +public class ProjectLoader { + private JAXBContext context; + private Marshaller m; + private Unmarshaller um; + + public ProjectLoader() throws JAXBException { + // create JAXB context and instantiate marshaller/unmarshaller + // SiteInfoGenFields: EPIC Site Info: + // Mcip2EpicFields: MCIP/EPIC to EPIC + + // SiteFilesFields : EPIC Site file generation ( run two executables ) + // SoilFilesFields : EPIC Soil file generation ( run soil match) + // ManageSpinupFields: Management file generation for spinup + // ManFileModFields: View/Edit EPIC Inputs + // EpicSpinupFields : Epic runs for spinup + // EpicYearlyAverage2CMAQFields: EPIC Yearly Output + // Epic2CMAQFields: + // Epic2SWATFields: + context = JAXBContext.newInstance(Project.class, Beld4DataGenFields.class, Mcip2EpicFields.class, SiteFilesFields.class, + SoilFilesFields.class, ManageSpinupFields.class, ManFileModFields.class, EpicSpinupFields.class, + EpicYearlyAverage2CMAQFields.class, ManageAppFields.class, EpicAppFields.class, + VisualizationFields.class, SiteInfoGenFields.class, Epic2CMAQFields.class, + Epic2SWATFields.class,DomainFields.class); + m = context.createMarshaller(); + m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + um = context.createUnmarshaller(); + } + + /** + * Saves the specified project to the specified file. + * + * @param file the file to save the model to + * @param project the project to save + * @throws IOException if there is an error duing saving + * @throws JAXBException + * @throws JAXBException if the xml mapping error occurs + */ + public void save(File file, Project project) throws IOException, JAXBException { + m.marshal(project, file); + } + + /** + * Loads the project data in specified file into the + * specified project. + * + * @param file the file containing the data to load + * @param project the project to load the data into + * @param manager used to create the Datasets + * @param creator the creator used to properly create the formula items + * @throws IOException if there is an error during loading. + * @throws JAXBException if the xml mapping error occurs + */ + public void load(File file, Project project) throws JAXBException, IOException { + Project loaded = (Project) um.unmarshal(new FileReader(file)); + project.setPageList(loaded.getPageList()); + } +} diff --git a/festc_core/src/gov/epa/festc/core/proj/SiteFilesFields.java b/festc_core/src/gov/epa/festc/core/proj/SiteFilesFields.java index 1b42673..883abb6 100644 --- a/festc_core/src/gov/epa/festc/core/proj/SiteFilesFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/SiteFilesFields.java @@ -1,26 +1,26 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.SiteFilesFields") -public class SiteFilesFields extends DomainFields { - - private String minAcres; - - public SiteFilesFields() { - //NOTE: no-op - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return SiteFilesFields.class.getCanonicalName(); - } - - public void setMinAcres(String acres) { - this.minAcres = acres; - } - public String getMinAcres() { - return minAcres; - } -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.SiteFilesFields") +public class SiteFilesFields extends DomainFields { + + private String minAcres; + + public SiteFilesFields() { + //NOTE: no-op + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return SiteFilesFields.class.getCanonicalName(); + } + + public void setMinAcres(String acres) { + this.minAcres = acres; + } + public String getMinAcres() { + return minAcres; + } +} diff --git a/festc_core/src/gov/epa/festc/core/proj/SiteInfoGenFields.java b/festc_core/src/gov/epa/festc/core/proj/SiteInfoGenFields.java index 6a0939a..416bbaa 100644 --- a/festc_core/src/gov/epa/festc/core/proj/SiteInfoGenFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/SiteInfoGenFields.java @@ -1,34 +1,34 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.SiteInfoGenFields") -public class SiteInfoGenFields extends PageFields{ - - private String beld4ncf; - private String minAcres; - - public SiteInfoGenFields() { - //NOTE: no-op - } - - public void setBeld4ncf(String beld4ncf) { - this.beld4ncf = beld4ncf; - } - public String getBeld4ncf() { - return beld4ncf; - } - - public void setMinAcres(String acres) { - this.minAcres = acres; - } - public String getMinAcres() { - return minAcres; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return SiteInfoGenFields.class.getCanonicalName(); - } -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.SiteInfoGenFields") +public class SiteInfoGenFields extends PageFields{ + + private String beld4ncf; + private String minAcres; + + public SiteInfoGenFields() { + //NOTE: no-op + } + + public void setBeld4ncf(String beld4ncf) { + this.beld4ncf = beld4ncf; + } + public String getBeld4ncf() { + return beld4ncf; + } + + public void setMinAcres(String acres) { + this.minAcres = acres; + } + public String getMinAcres() { + return minAcres; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return SiteInfoGenFields.class.getCanonicalName(); + } +} diff --git a/festc_core/src/gov/epa/festc/core/proj/SoilFilesFields.java b/festc_core/src/gov/epa/festc/core/proj/SoilFilesFields.java index 664d993..c7f1960 100644 --- a/festc_core/src/gov/epa/festc/core/proj/SoilFilesFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/SoilFilesFields.java @@ -1,28 +1,28 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.SoilFilesFields") -public class SoilFilesFields extends PageFields { - - private String finishedCrops; - - public SoilFilesFields() { - //NOTE: no-op - } - - public String getFinishedCrops() { - return finishedCrops; - } - - public void setFinishedCrops(String finishedCrops) { - this.finishedCrops = finishedCrops; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return SoilFilesFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.SoilFilesFields") +public class SoilFilesFields extends PageFields { + + private String finishedCrops; + + public SoilFilesFields() { + //NOTE: no-op + } + + public String getFinishedCrops() { + return finishedCrops; + } + + public void setFinishedCrops(String finishedCrops) { + this.finishedCrops = finishedCrops; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return SoilFilesFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/core/proj/VisualizationFields.java b/festc_core/src/gov/epa/festc/core/proj/VisualizationFields.java index 46dd58a..18ba67f 100644 --- a/festc_core/src/gov/epa/festc/core/proj/VisualizationFields.java +++ b/festc_core/src/gov/epa/festc/core/proj/VisualizationFields.java @@ -1,73 +1,73 @@ -package gov.epa.festc.core.proj; - -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "gov.epa.festc.core.proj.VisualizationFields") -public class VisualizationFields extends PageFields{ - - private String mcipDataDir; - private String beldDataDir; - private String epicDataDir; - private boolean mcipDataSelected; - private boolean beldDataSelected; - private boolean epicDataSelected; - - public VisualizationFields() { - //NOTE: no-op - } - - public String getMcipDataDir() { - return mcipDataDir; - } - - public void setMcipDataDir(String mcipDataDir) { - this.mcipDataDir = mcipDataDir; - } - - public String getBeldDataDir() { - return beldDataDir; - } - - public void setBeldDataDir(String beldDataDir) { - this.beldDataDir = beldDataDir; - } - - public String getEpicDataDir() { - return epicDataDir; - } - - public void setEpicDataDir(String epicDataDir) { - this.epicDataDir = epicDataDir; - } - - public boolean isMcipDataSelected() { - return mcipDataSelected; - } - - public void setMcipDataSelected(boolean mcipDataSelected) { - this.mcipDataSelected = mcipDataSelected; - } - - public boolean isBeldDataSelected() { - return beldDataSelected; - } - - public void setBeldDataSelected(boolean beldDataSelected) { - this.beldDataSelected = beldDataSelected; - } - - public boolean isEpicDataSelected() { - return epicDataSelected; - } - - public void setEpicDataSelected(boolean epicDataSelected) { - this.epicDataSelected = epicDataSelected; - } - - @Override - public String getName() { - // TODO Auto-generated method stub - return VisualizationFields.class.getCanonicalName(); - } - -} +package gov.epa.festc.core.proj; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "gov.epa.festc.core.proj.VisualizationFields") +public class VisualizationFields extends PageFields{ + + private String mcipDataDir; + private String beldDataDir; + private String epicDataDir; + private boolean mcipDataSelected; + private boolean beldDataSelected; + private boolean epicDataSelected; + + public VisualizationFields() { + //NOTE: no-op + } + + public String getMcipDataDir() { + return mcipDataDir; + } + + public void setMcipDataDir(String mcipDataDir) { + this.mcipDataDir = mcipDataDir; + } + + public String getBeldDataDir() { + return beldDataDir; + } + + public void setBeldDataDir(String beldDataDir) { + this.beldDataDir = beldDataDir; + } + + public String getEpicDataDir() { + return epicDataDir; + } + + public void setEpicDataDir(String epicDataDir) { + this.epicDataDir = epicDataDir; + } + + public boolean isMcipDataSelected() { + return mcipDataSelected; + } + + public void setMcipDataSelected(boolean mcipDataSelected) { + this.mcipDataSelected = mcipDataSelected; + } + + public boolean isBeldDataSelected() { + return beldDataSelected; + } + + public void setBeldDataSelected(boolean beldDataSelected) { + this.beldDataSelected = beldDataSelected; + } + + public boolean isEpicDataSelected() { + return epicDataSelected; + } + + public void setEpicDataSelected(boolean epicDataSelected) { + this.epicDataSelected = epicDataSelected; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return VisualizationFields.class.getCanonicalName(); + } + +} diff --git a/festc_core/src/gov/epa/festc/gui/AboutDialog.java b/festc_core/src/gov/epa/festc/gui/AboutDialog.java index 141dbec..9f98c3e 100644 --- a/festc_core/src/gov/epa/festc/gui/AboutDialog.java +++ b/festc_core/src/gov/epa/festc/gui/AboutDialog.java @@ -1,117 +1,117 @@ -package gov.epa.festc.gui; - -import gov.epa.festc.core.VersionInfo; - -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Dialog; -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.WindowConstants; - -import org.jdesktop.swingx.JXHeader; - -import com.jgoodies.forms.factories.Borders; -import com.jgoodies.forms.factories.FormFactory; -import com.jgoodies.forms.layout.CellConstraints; -import com.jgoodies.forms.layout.ColumnSpec; -import com.jgoodies.forms.layout.FormLayout; -import com.jgoodies.forms.layout.RowSpec; - -/** - * @author IE, UNC - */ -public class AboutDialog extends JDialog { - //private static final long serialVersionUID = -3158674310794549095L; - public AboutDialog(Frame owner) { - super(owner); - initComponents(); - xHeader1.setDescription("Version: " + VersionInfo.getVersion() + " " + VersionInfo.getDate()); - } - - public AboutDialog(Dialog owner) { - super(owner); - initComponents(); - xHeader1.setDescription("Version: " + VersionInfo.getVersion() + " " + VersionInfo.getDate()); - } - - private void okButtonActionPerformed(ActionEvent e) { - this.dispose(); - } - - private void initComponents() { - dialogPane = new JPanel(); - contentPanel = new JPanel(); - scrollPane1 = new JScrollPane(); - xHeader1 = new JXHeader(); - buttonBar = new JPanel(); - okButton = new JButton(); - CellConstraints cc = new CellConstraints(); - - //======== this ======== - setTitle("About FEST-C"); - setResizable(false); - setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - Container contentPane = getContentPane(); - contentPane.setLayout(new BorderLayout()); - - //======== dialogPane ======== - { - dialogPane.setBorder(Borders.DIALOG_BORDER); - dialogPane.setLayout(new BorderLayout()); - - //======== contentPanel ======== - { - contentPanel.setLayout(new FormLayout( - "default:grow", - "default")); - - //======== scrollPane1 ======== - { - xHeader1.setTitle("Fertilizer Emission Scenario Tool for CMAQ (FEST-C)"); - scrollPane1.setViewportView(xHeader1); - } - contentPanel.add(scrollPane1, cc.xy(1, 1)); - } - dialogPane.add(contentPanel, BorderLayout.CENTER); - - //======== buttonBar ======== - { - buttonBar.setBorder(Borders.BUTTON_BAR_GAP_BORDER); - buttonBar.setLayout(new FormLayout( - new ColumnSpec[] { - FormFactory.GLUE_COLSPEC, - FormFactory.BUTTON_COLSPEC - }, - RowSpec.decodeSpecs("pref"))); - - //---- okButton ---- - okButton.setText("OK"); - okButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - okButtonActionPerformed(e); - } - }); - buttonBar.add(okButton, cc.xy(2, 1)); - } - dialogPane.add(buttonBar, BorderLayout.SOUTH); - } - contentPane.add(dialogPane, BorderLayout.CENTER); - pack(); - setLocationRelativeTo(getOwner()); - } - - private JPanel dialogPane; - private JPanel contentPanel; - private JScrollPane scrollPane1; - private JXHeader xHeader1; - private JPanel buttonBar; - private JButton okButton; -} - +package gov.epa.festc.gui; + +import gov.epa.festc.core.VersionInfo; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.WindowConstants; + +import org.jdesktop.swingx.JXHeader; + +import com.jgoodies.forms.factories.Borders; +import com.jgoodies.forms.factories.FormFactory; +import com.jgoodies.forms.layout.CellConstraints; +import com.jgoodies.forms.layout.ColumnSpec; +import com.jgoodies.forms.layout.FormLayout; +import com.jgoodies.forms.layout.RowSpec; + +/** + * @author IE, UNC + */ +public class AboutDialog extends JDialog { + //private static final long serialVersionUID = -3158674310794549095L; + public AboutDialog(Frame owner) { + super(owner); + initComponents(); + xHeader1.setDescription("Version: " + VersionInfo.getVersion() + " " + VersionInfo.getDate()); + } + + public AboutDialog(Dialog owner) { + super(owner); + initComponents(); + xHeader1.setDescription("Version: " + VersionInfo.getVersion() + " " + VersionInfo.getDate()); + } + + private void okButtonActionPerformed(ActionEvent e) { + this.dispose(); + } + + private void initComponents() { + dialogPane = new JPanel(); + contentPanel = new JPanel(); + scrollPane1 = new JScrollPane(); + xHeader1 = new JXHeader(); + buttonBar = new JPanel(); + okButton = new JButton(); + CellConstraints cc = new CellConstraints(); + + //======== this ======== + setTitle("About FEST-C"); + setResizable(false); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout()); + + //======== dialogPane ======== + { + dialogPane.setBorder(Borders.DIALOG_BORDER); + dialogPane.setLayout(new BorderLayout()); + + //======== contentPanel ======== + { + contentPanel.setLayout(new FormLayout( + "default:grow", + "default")); + + //======== scrollPane1 ======== + { + xHeader1.setTitle("Fertilizer Emission Scenario Tool for CMAQ (FEST-C)"); + scrollPane1.setViewportView(xHeader1); + } + contentPanel.add(scrollPane1, cc.xy(1, 1)); + } + dialogPane.add(contentPanel, BorderLayout.CENTER); + + //======== buttonBar ======== + { + buttonBar.setBorder(Borders.BUTTON_BAR_GAP_BORDER); + buttonBar.setLayout(new FormLayout( + new ColumnSpec[] { + FormFactory.GLUE_COLSPEC, + FormFactory.BUTTON_COLSPEC + }, + RowSpec.decodeSpecs("pref"))); + + //---- okButton ---- + okButton.setText("OK"); + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + okButtonActionPerformed(e); + } + }); + buttonBar.add(okButton, cc.xy(2, 1)); + } + dialogPane.add(buttonBar, BorderLayout.SOUTH); + } + contentPane.add(dialogPane, BorderLayout.CENTER); + pack(); + setLocationRelativeTo(getOwner()); + } + + private JPanel dialogPane; + private JPanel contentPanel; + private JScrollPane scrollPane1; + private JXHeader xHeader1; + private JPanel buttonBar; + private JButton okButton; +} + diff --git a/festc_core/src/gov/epa/festc/gui/Beld4DataGenPanel.java b/festc_core/src/gov/epa/festc/gui/Beld4DataGenPanel.java index 9bce3bf..9a636ec 100644 --- a/festc_core/src/gov/epa/festc/gui/Beld4DataGenPanel.java +++ b/festc_core/src/gov/epa/festc/gui/Beld4DataGenPanel.java @@ -32,7 +32,7 @@ import gov.epa.festc.util.SpringLayoutGenerator; import simphony.util.messages.MessageCenter; -public class Beld4DataGenPanel extends UtilFieldsPanel implements PlotEventListener{ +public class Beld4DataGenPanel extends UtilFieldsPanel implements PlotEventListener { /** * @@ -40,17 +40,17 @@ public class Beld4DataGenPanel extends UtilFieldsPanel implements PlotEventListe private static final long serialVersionUID = 1403169880186710184L; private MessageCenter msg; -// private FestcApplication app; + // private FestcApplication app; private Beld4DataGenFields fields; - //private DomainFields domain; - private JCheckBox nlcdBox; + // private DomainFields domain; + private JCheckBox nlcdBox; private JCheckBox modisBox; -// private JCheckBox beld4ncBox; -// private JCheckBox nc2apiBox; + // private JCheckBox beld4ncBox; + // private JCheckBox nc2apiBox; private JComboBox nlcdYear; private JTextField inputDir; private JButton inputDirBrowser; - + public Beld4DataGenPanel(FestcApplication festcApp) { app = festcApp; msg = app.getMessageCenter(); @@ -59,24 +59,24 @@ public Beld4DataGenPanel(FestcApplication festcApp) { app.addPlotListener(this); add(createPanel()); } - + private JPanel createPanel() { JPanel main = new JPanel(); - try{ + try { init(); main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS)); main.add(getNorthPanel()); main.add(getCenterPanel()); main.add(getSouthPanel()); main.add(messageBox()); - + } catch (Exception exc) { exc.printStackTrace(); } return main; } - + private JPanel getNorthPanel() { JPanel panel = new JPanel(); JLabel title = new JLabel(Constants.BELD4_GEN, SwingConstants.CENTER); @@ -87,41 +87,42 @@ private JPanel getNorthPanel() { return panel; } - + private JPanel getCenterPanel() { JPanel panel = new JPanel(new SpringLayout()); SpringLayoutGenerator layout = new SpringLayoutGenerator(); - + JPanel dataPanel = new JPanel(); - this.nlcdBox = new JCheckBox("NLCD ", true); + this.nlcdBox = new JCheckBox("NLCD ", true); this.modisBox = new JCheckBox("MODIS ", true); -// this.beld4ncBox = new JCheckBox("Run_beld4nc", true); -// this.nc2apiBox = new JCheckBox("Run_nc2api", true); - + // this.beld4ncBox = new JCheckBox("Run_beld4nc", true); + // this.nc2apiBox = new JCheckBox("Run_nc2api", true); + dataPanel.add(this.nlcdBox); dataPanel.add(this.modisBox); -// dataPanel.add(this.beld4ncBox); -// dataPanel.add(this.nc2apiBox); - - JPanel yearPanel = new JPanel( ); + // dataPanel.add(this.beld4ncBox); + // dataPanel.add(this.nc2apiBox); + + JPanel yearPanel = new JPanel(); nlcdYear = new JComboBox(Constants.NLCDYEARS); - //nlcdYear.setEditable(false); + // nlcdYear.setEditable(false); yearPanel.add(nlcdYear); - + JPanel inputDirPanel = new JPanel(); inputDir = new JTextField(40); inputDir.setToolTipText("I.E. ../data/nlcd_modis_files_2006.txt"); - - inputDirBrowser = new JButton(BrowseAction.browseAction(this, app.getCurrentDir(),"NLCD/MODIS list file", inputDir)); + + inputDirBrowser = new JButton( + BrowseAction.browseAction(this, app.getCurrentDir(), "NLCD/MODIS list file", inputDir)); inputDirPanel.add(inputDir); - inputDirPanel.add(inputDirBrowser); + inputDirPanel.add(inputDirBrowser); layout.addLabelWidgetPair("Grid Description: ", getGridDescPanel(false), panel); layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); layout.addLabelWidgetPair("NLCD/MODIS Data Year:", yearPanel, panel); layout.addLabelWidgetPair("NLCD/MODIS List File:", inputDirPanel, panel); layout.addLabelWidgetPair("Data Selection:", dataPanel, panel); - //layout.addLabelWidgetPair(" ", new JLabel(" "), panel); + // layout.addLabelWidgetPair(" ", new JLabel(" "), panel); layout.makeCompactGrid(panel, 5, 2, // number of rows and cols 10, 10, // initial X and Y @@ -129,9 +130,7 @@ private JPanel getCenterPanel() { return panel; } - - private JPanel getSouthPanel() { JPanel panel = new JPanel(); JButton display = new JButton(runAction()); @@ -140,242 +139,346 @@ private JPanel getSouthPanel() { panel.setBorder(BorderFactory.createEmptyBorder(30, 0, 10, 0)); return panel; - } - + } + private Action runAction() { return new AbstractAction("Run") { private static final long serialVersionUID = 8573618661168062193L; public void actionPerformed(ActionEvent e) { - - try { + + try { generateRunScript(); } catch (Exception exc) { - //msg.error("ERROR", exc); + // msg.error("ERROR", exc); app.showMessage("Run script", exc.getMessage()); } } }; } - + private void generateRunScript() throws Exception { String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - if (baseDir == null || baseDir.isEmpty()) + if (baseDir == null || baseDir.isEmpty()) throw new Exception("Base dir is empty, please specify it in the configuration file!"); - + String scenarioDir = this.scenarioDir.getText(); - if (scenarioDir == null || scenarioDir.isEmpty()) + if (scenarioDir == null || scenarioDir.isEmpty()) throw new Exception("Scenario dir is empty!"); -// if (scenarioDir.trim().contains(" ") ) -// throw new Exception(" New scenario name has space in between."); -// + // if (scenarioDir.trim().contains(" ") ) + // throw new Exception(" New scenario name has space in between."); + // validateGrids(); - - - String dYear = (String)this.nlcdYear.getSelectedItem(); - if ( dYear.trim().isEmpty() ) - throw new Exception("NLCD/MODIS data year is empty!"); - + + String dYear = (String) this.nlcdYear.getSelectedItem(); + if (dYear.trim().isEmpty()) + throw new Exception("NLCD/MODIS data year is empty!"); + String inputFile = this.inputDir.getText(); - if (inputFile == null || inputFile.isEmpty()) - throw new Exception("Please select input file!"); - - String sahome = Constants.getProperty(Constants.SA_HOME, msg); - if (sahome == null || sahome.trim().isEmpty() || !(new File(sahome).exists())) - throw new Exception("SA dir is empty, please specify it in the configuration file!"); - - outMessages += ls + "Epic base: " + baseDir + ls; + if (inputFile == null || inputFile.isEmpty()) + throw new Exception("Please select input file!"); + + String sahome = Constants.getProperty(Constants.SA_HOME, msg); + // if (sahome == null || sahome.trim().isEmpty() || !(new + // File(sahome).exists())) + if (sahome == null) + throw new Exception("SA dir is empty, please specify it in the configuration file!"); + + outMessages += ls + "Epic base: " + baseDir + ls; outMessages += "SA home: " + sahome + ls; - - final String file = writeRunScriptScript(baseDir, scenarioDir, sahome, dYear.trim()); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + + final String jobFile = writeRunScriptScript(baseDir, scenarioDir, sahome, dYear.trim()); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir); + } else { + batchFile = null; + } Thread populateThread = new Thread(new Runnable() { public void run() { - runScript(file); + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + // final String batchFile = writeBatchFile(jobFile, + // scenarioDir); + runBatchScript(batchFile, jobFile); + } + } }); populateThread.start(); } - - protected String writeRunScriptScript( - String baseDir, - String scenarioDir, - String sahome, String dYear ) throws Exception { - Date now = new Date(); // java.util.Date, NOT java.sql.Date or java.sql.Timestamp! + // This is legacy code that has been moved to it's own method + protected void writeScriptFile(String file, String content) { + + String mesg = ""; + + try { + File script = new File(file); + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(content); + out.close(); + + mesg += "Script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + + } catch (IOException e) { + // printStackTrace(); + // g.error("Error generating EPIC script file", e); + app.showMessage("Write script", e.getMessage()); + } + + app.showMessage("Write script", mesg); + } + + protected String writeBatchFile(String jobFile, String scenarioDir) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - String file = scenarioDir.trim() + "/scripts/"; - file = file.trim() + "generateBeld4Data_"+ gridName.getText().trim()+ "_" + timeStamp +".csh"; + String batchFile = scenarioDir.trim() + "/scripts"; + if (!batchFile.endsWith(System.getProperty("file.separator"))) + batchFile += System.getProperty("file.separator"); + batchFile += "submitBeld4Data_" + timeStamp + ".csh"; StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh" + ls + ls); + + // TODO - add #SBATCH options here + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage == null || qSingModule.trim().isEmpty()) { + throw new Exception("Singularity image path must be specified"); + } + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + jobFile); + } else { + sb.append(jobFile); + } - //String netcdfout = (netcdfFile.getText() == null || netcdfFile.getText().trim().isEmpty()) ? "NONE" : netcdfFile.getText().trim(); + writeScriptFile(batchFile, sb.toString()); + + return batchFile; + } + + protected String writeRunScriptScript(String baseDir, String scenarioDir, String sahome, String dYear) + throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String file = scenarioDir.trim() + "/scripts/"; + file = file.trim() + "generateBeld4Data_" + gridName.getText().trim() + "_" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + + // String netcdfout = (netcdfFile.getText() == null || + // netcdfFile.getText().trim().isEmpty()) ? "NONE" : + // netcdfFile.getText().trim(); sb.append(getScriptHeader() + ls); sb.append("#" + ls + "# Set up runtime environment" + ls + "#" + ls); sb.append("source " + sahome.trim() + Constants.SA_SETUP_FILE + ls + ls); - + sb.append(ls + "#" + ls); sb.append("# Define environment variables" + ls); sb.append("#" + ls + ls); sb.append("setenv EPIC_DIR " + baseDir + ls); sb.append("setenv SCEN_DIR " + scenarioDir + ls); - sb.append("setenv SA_HOME " + sahome +ls); + sb.append("setenv SA_HOME " + sahome + ls); sb.append("setenv COMM_DIR $EPIC_DIR/common_data " + ls); sb.append("cd $SCEN_DIR/scripts " + ls); - + sb.append("#" + ls + "# Define domain grids" + ls + "#" + ls); - //sb.append("setenv GRID_PROJ \"+proj=lcc +a=6370000.0 +b=6370000.0 +lat_1=33 +lat_2=45 +lat_0=40 +lon_0=-97\"" + ls + ls); + // sb.append("setenv GRID_PROJ \"+proj=lcc +a=6370000.0 +b=6370000.0 + // +lat_1=33 +lat_2=45 +lat_0=40 +lon_0=-97\"" + ls + ls); sb.append("setenv GRID_PROJ \"" + proj4proj.getText().trim() + "\"" + ls); - sb.append("setenv GRID_ROWS " + ((Number)rows.getValue()).intValue() + ls); - sb.append("setenv GRID_COLUMNS " + ((Number)cols.getValue()).intValue() + ls + ls); - sb.append("setenv GRID_XMIN " + ((Number)xmin.getValue()).doubleValue() + ls); - sb.append("setenv GRID_YMIN " + ((Number)ymin.getValue()).doubleValue() + ls + ls); - sb.append("setenv GRID_XCELLSIZE " + ((Number)xSize.getValue()).doubleValue() + ls); - sb.append("setenv GRID_YCELLSIZE " + ((Number)ySize.getValue()).doubleValue() + ls + ls); + sb.append("setenv GRID_ROWS " + ((Number) rows.getValue()).intValue() + ls); + sb.append("setenv GRID_COLUMNS " + ((Number) cols.getValue()).intValue() + ls + ls); + sb.append("setenv GRID_XMIN " + ((Number) xmin.getValue()).doubleValue() + ls); + sb.append("setenv GRID_YMIN " + ((Number) ymin.getValue()).doubleValue() + ls + ls); + sb.append("setenv GRID_XCELLSIZE " + ((Number) xSize.getValue()).doubleValue() + ls); + sb.append("setenv GRID_YCELLSIZE " + ((Number) ySize.getValue()).doubleValue() + ls + ls); String gridN = gridName.getText() == null ? "" : gridName.getText().trim(); sb.append("setenv GRID_NAME \"" + gridN + "\"" + ls + ls); - - sb.append("# Define input file which contains NLCD and MODIS land cover files " + ls + ls ); + + sb.append("# Define input file which contains NLCD and MODIS land cover files " + ls + ls); sb.append("setenv INPUT_FILE_LIST " + inputDir.getText() + ls + ls); - - String nlcdYN = nlcdBox.isSelected()? "YES" : "NO"; - String modisYN = modisBox.isSelected()? "YES" : "NO"; -// String beld4nc = nlcdBox.isSelected()? "YES" : "NO"; -// String nc2ioapi = modisBox.isSelected()? "YES" : "NO"; - sb.append("# INCLUDE data selection " + ls ); - sb.append("setenv INCLUDE_NLCD " + nlcdYN + ls ); + + String nlcdYN = nlcdBox.isSelected() ? "YES" : "NO"; + String modisYN = modisBox.isSelected() ? "YES" : "NO"; + // String beld4nc = nlcdBox.isSelected()? "YES" : "NO"; + // String nc2ioapi = modisBox.isSelected()? "YES" : "NO"; + sb.append("# INCLUDE data selection " + ls); + sb.append("setenv INCLUDE_NLCD " + nlcdYN + ls); sb.append("setenv INCLUDE_MODIS " + modisYN + ls + ls); -// sb.append("setenv BELD4NC_YN " + beld4nc + ls ); -// sb.append("setenv BELD4IO_YN " + nc2ioapi + ls + ls); - - sb.append("# Define county shapefile " + ls ); - sb.append("setenv COUNTY_SHAPEFILE $SA_HOME/data/county_pophu02_48st.shp" + ls + ls); - sb.append("setenv COUNTY_FIPS_ATTR CNTYID" + ls + ls ); - sb.append("# BELD3 FIA tree fractions at county level for 1990s" + ls ); + // sb.append("setenv BELD4NC_YN " + beld4nc + ls ); + // sb.append("setenv BELD4IO_YN " + nc2ioapi + ls + ls); + + sb.append("# Define county shapefile " + ls); + sb.append("setenv COUNTY_SHAPEFILE $SA_HOME/data/county_pophu02_48st.shp" + ls + ls); + sb.append("setenv COUNTY_FIPS_ATTR CNTYID" + ls + ls); + sb.append("# BELD3 FIA tree fractions at county level for 1990s" + ls); sb.append("setenv US_COUNTY_FIA_FILE $SA_HOME/data/beld3-fia.dat" + ls + ls); - + sb.append("# new NASS crop/pasture fractions at county level for 2001 or 2006" + ls); - sb.append("setenv US_COUNTY_NASS_FILE $SA_HOME/data/nass" + dYear +"_beld4_ag.dat" + ls + ls); - + sb.append("setenv US_COUNTY_NASS_FILE $SA_HOME/data/nass" + dYear + "_beld4_ag.dat" + ls + ls); + sb.append("# CAN crop division or census division shapefile " + ls); sb.append("# Only divisions have crop data are incldued " + ls); - sb.append("setenv CAN_COUNTY_SHAPEFILE $SA_HOME/data/can" + dYear +"_cd_sel.shp" + ls); - sb.append("setenv CAN_COUNTY_FIPS_ATTR AGUID " + ls + ls ); - + sb.append("setenv CAN_COUNTY_SHAPEFILE $SA_HOME/data/can" + dYear + "_cd_sel.shp" + ls); + sb.append("setenv CAN_COUNTY_FIPS_ATTR AGUID " + ls + ls); + sb.append("# CAN crop fraction table at crop divisions for 2001 or 2006" + ls); - sb.append("setenv CAN_CROP_FILE $SA_HOME/data/can" + dYear +"_beld4_ag.dat" + ls +ls); - + sb.append("setenv CAN_CROP_FILE $SA_HOME/data/can" + dYear + "_beld4_ag.dat" + ls + ls); + sb.append("#table contains class names for land cover data and canopy FIA trees" + ls + ls); sb.append("setenv BELD4_CLASS_NAMES $SA_HOME/data/beld4_class_names_40classes.txt" + ls + ls); - + sb.append("# Output files" + ls); - sb.append("setenv OUTPUT_LANDUSE_TEXT_FILE $SCEN_DIR/share_data/beld4_" + gridN +"_"+ dYear +".txt" + ls); - sb.append("setenv OUTPUT_LANDUSE_NETCDF_FILE $SCEN_DIR/share_data/beld4_" + gridN +"_"+ dYear + ".nc" + ls + ls); + sb.append( + "setenv OUTPUT_LANDUSE_TEXT_FILE $SCEN_DIR/share_data/beld4_" + gridN + "_" + dYear + ".txt" + ls); + sb.append("setenv OUTPUT_LANDUSE_NETCDF_FILE $SCEN_DIR/share_data/beld4_" + gridN + "_" + dYear + ".nc" + ls + + ls); sb.append("time $SA_HOME/bin/64bits/computeGridLandUse_beld4.exe" + ls + ls); - + sb.append(" if ( $status == 0 ) then " + ls); sb.append(" echo ==== Finished Beld4 data generation. " + ls); sb.append(" else " + ls); sb.append(" echo ==== Error in Beld4 data generation." + ls + ls); - sb.append(" echo " + ls ); + sb.append(" echo " + ls); sb.append(" endif " + ls); - - - sb.append(" setenv INFILE ${OUTPUT_LANDUSE_NETCDF_FILE}" + ls ); - sb.append(" setenv OUTDIR $SCEN_DIR/output4CMAQ/app/toCMAQ"+ ls +ls ); - - sb.append(" if ( ! -e $OUTDIR ) mkdir -p $OUTDIR" + ls ); - sb.append(" setenv OUTFILE ${OUTDIR}/beld4_"+ gridN +"_"+ dYear + ".ncf " + ls ); - - sb.append(" if ( ! -e $INFILE ) then " + ls ); - sb.append(" echo $INFILE ' doesn't exist! ' " + ls ); - sb.append(" exit(1) " + ls ); - sb.append(" endif " + ls + ls ); - //sb.append(" echo 'Output file name: ' $OUTFILE " + ls + ls ); - - sb.append(" time $EPIC_DIR/util/misc/beld_nc2ioapi/Beld_nc2ioapi.exe " + ls ); - sb.append(" if ( $status == 0 ) then " + ls ); - sb.append(" echo ==== Finished Beld4 to Ioapi transformation. " + ls ); - sb.append(" endif" + ls ); - + + sb.append(" setenv INFILE ${OUTPUT_LANDUSE_NETCDF_FILE}" + ls); + sb.append(" setenv OUTDIR $SCEN_DIR/output4CMAQ/app/toCMAQ" + ls + ls); + + sb.append(" if ( ! -e $OUTDIR ) mkdir -p $OUTDIR" + ls); + sb.append(" setenv OUTFILE ${OUTDIR}/beld4_" + gridN + "_" + dYear + ".ncf " + ls); + + sb.append(" if ( ! -e $INFILE ) then " + ls); + sb.append(" echo $INFILE ' does not exist! ' " + ls); + sb.append(" exit(1) " + ls); + sb.append(" endif " + ls + ls); + // sb.append(" echo 'Output file name: ' $OUTFILE " + ls + ls ); + + sb.append(" time $EPIC_DIR/util/misc/beld_nc2ioapi/Beld_nc2ioapi.exe " + ls); + sb.append(" if ( $status == 0 ) then " + ls); + sb.append(" echo ==== Finished Beld4 to Ioapi transformation. " + ls); + sb.append(" endif" + ls); + sb.append("#===================================================================" + ls); - + String mesg = ""; try { File script = new File(file); Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - mesg = "Created a script file: " + file + ls; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - } catch (IOException e) { - throw new Exception(e.getMessage()); - } - - - String ncfile = scenarioDir.trim() + "/share_data/beld4_" + gridN +"_"+ dYear +".txt"; - //String nctxtfile = scenarioDir.trim() + "/share_data/beld4_" + gridN +"_"+ dYear + ".nc"; - String ioapifile = scenarioDir.trim() + "/output4CMAQ/app/toCMAQ/beld4_"+ gridN +"_"+ dYear + ".ncf "; - + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + mesg = "Created a script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + } catch (IOException e) { + throw new Exception(e.getMessage()); + } + + String ncfile = scenarioDir.trim() + "/share_data/beld4_" + gridN + "_" + dYear + ".txt"; + // String nctxtfile = scenarioDir.trim() + "/share_data/beld4_" + gridN + // +"_"+ dYear + ".nc"; + String ioapifile = scenarioDir.trim() + "/output4CMAQ/app/toCMAQ/beld4_" + gridN + "_" + dYear + ".ncf "; + outMessages += "Script file: " + file + ls; outMessages += "Output netcdf file: " + ncfile + ls; outMessages += "Output ioapi file: " + ioapifile + ls; - - app.showMessage("Write script", mesg); + + app.showMessage("Write script", mesg); return file; } - + private String getScriptHeader() { StringBuilder sb = new StringBuilder(); String ls = "\n"; sb.append("#!/bin/csh -f" + ls); sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: generate landuse information for a given modeling " + ls ); - sb.append("# domain grids from:" + ls); + sb.append("# Purpose: generate landuse information for a given modeling " + ls); + sb.append("# domain grids from:" + ls); - sb.append("# 1. USGS NLCD 30m Landuse Files " + ls); - sb.append("# 2. USGS NLCD 30m Urban Imperviousness files " + ls); - sb.append("# 3. USGS NLCD 30m Tree Canopy Files " + ls); - sb.append("# 4. MODIS Landcove files " + ls + ls ); + sb.append("# 1. USGS NLCD 30m Landuse Files " + ls); + sb.append("# 2. USGS NLCD 30m Urban Imperviousness files " + ls); + sb.append("# 3. USGS NLCD 30m Tree Canopy Files " + ls); + sb.append("# 4. MODIS Landcove files " + ls + ls); sb.append("# NLCD data can be downloaded from: " + ls); - sb.append("# http://www.mrlc.gov/nlcd2001.php " + ls); - sb.append("# MODIS land cover tiles (e.g. MCD12Q1) can be downloaded from:" + ls); - sb.append("# http://ladsweb.nascom.nasa.gov/data/search.html" + ls + ls); - - sb.append("# Crop and FIA data used for more crop and tree classes " + ls); + sb.append("# http://www.mrlc.gov/nlcd2001.php " + ls); + sb.append("# MODIS land cover tiles (e.g. MCD12Q1) can be downloaded from:" + ls); + sb.append("# http://ladsweb.nascom.nasa.gov/data/search.html" + ls + ls); + + sb.append("# Crop and FIA data used for more crop and tree classes " + ls); sb.append("# 1. US FIA tree species fractions at county (from census data) " + ls); sb.append("# 2. US NASS crop fractions at county " + ls); sb.append("# 3. CAN crop fractions at crop divisions " + ls); - sb.append("# 4. Class names for all crops and trees " + ls +ls); - - sb.append("# Shapefiles used:" + ls); + sb.append("# 4. Class names for all crops and trees " + ls + ls); + + sb.append("# Shapefiles used:" + ls); sb.append("# 1. US county shapefile and ID attribute" + ls); sb.append("# 2. CAN census division shapefile and ID attribute " + ls); - + sb.append("# Written by: L. R., 2012-2013 " + ls); sb.append("# Updated by: D. Yang, 2017 " + ls); - sb.append("# 1. Transfer netcdf to ioapi " + ls); + sb.append("# 1. Transfer netcdf to ioapi " + ls); sb.append("#" + ls); sb.append("# Call program: computeGridLandUse.exe" + ls); - sb.append("# Needed environment variables included in the script file to run." + ls); - sb.append("#" + ls); + sb.append("# Needed environment variables included in the script file to run." + ls); + sb.append("#" + ls); sb.append("#***************************************************************************************" + ls + ls); - + return sb.toString(); } - + private void runScript(final String file) { - String log = file + ".log"; + String log = file + ".log"; outMessages += "Log file: " + log + ls; - + runMessages.setText(outMessages); runMessages.validate(); FileRunner.runScript(file, log, msg); } - + + private void runBatchScript(final String batchFile, final String jobFile) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qBeld4 = Constants.getProperty(Constants.QUEUE_BELD4_CMD, msg); + + File script = new File(batchFile.replaceAll("\\\\", "\\\\\\\\")); + + sb.append(qcmd + " " + qBeld4 + " -o " + log + " " + script.getAbsolutePath()); + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } + @Override public void newProjectCreated() { domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); @@ -388,13 +491,13 @@ public void newProjectCreated() { proj4proj.setText(domain.getProj()); gridName.setText(domain.getGridName()); scenarioDir.setText(domain.getScenarioDir()); - String nlcdY = domain.getNlcdYear(); + String nlcdY = domain.getNlcdYear(); nlcdYear.setSelectedItem(nlcdY); - String sahome = Constants.getProperty(Constants.SA_HOME, msg); + String sahome = Constants.getProperty(Constants.SA_HOME, msg); inputDir.setText(sahome.trim() + "/data/nlcd_modis_files_" + nlcdY + ".txt"); - + runMessages.setText(""); - if ( fields == null ) { + if (fields == null) { fields = new Beld4DataGenFields(); app.getProject().addPage(fields); } @@ -404,11 +507,11 @@ public void newProjectCreated() { public void projectLoaded() { fields = (Beld4DataGenFields) app.getProject().getPage(fields.getName()); domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - if( fields != null ) { + if (fields != null) { String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length()>0) + if (scenloc != null && scenloc.trim().length() > 0) this.scenarioDir.setText(scenloc); - else + else this.scenarioDir.setText(fields.getScenarioDir()); this.runMessages.setText(fields.getMessage()); rows.setValue(fields.getRows()); @@ -418,42 +521,54 @@ public void projectLoaded() { xSize.setValue(fields.getXcellSize()); ySize.setValue(fields.getYcellSize()); proj4proj.setText(fields.getProj()); - gridName.setText(fields.getGridName()); + gridName.setText(fields.getGridName()); nlcdYear.setSelectedItem(domain.getNlcdYear()); inputDir.setText(fields.getNLCDfile()); nlcdBox.setSelected(fields.isNlcdDataSelected()); modisBox.setSelected(fields.isModisDataSelected()); - - }else { + + } else { newProjectCreated(); - } - //setFalseEditable(); + } + // setFalseEditable(); } @Override public void saveProjectRequested() { - if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); - if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); - if ( rows != null ) fields.setRows(Integer.parseInt(rows.getText() == null? "0" : rows.getValue()+"")); - if ( cols != null ) fields.setCols(Integer.parseInt(cols.getText() == null? "0" : cols.getValue()+"")); - if ( xSize != null ) fields.setXcellSize(Float.parseFloat(xSize.getText() == null? "0" : xSize.getValue()+"")); - if ( ySize != null ) fields.setYcellSize(Float.parseFloat(ySize.getText() == null? "0" : ySize.getValue()+"")); - if ( xmin != null ) fields.setXmin(Float.parseFloat(xmin.getText() == null? "0" : xmin.getValue()+"")); - if ( ymin != null ) fields.setYmin(Float.parseFloat(ymin.getText() == null? "0" : ymin.getValue()+"")); - if ( proj4proj != null ) fields.setProj(proj4proj.getText() == null? "" : proj4proj.getText()); - if ( gridName != null ) fields.setGridName(gridName.getText()== null? "" : gridName.getText()); - if ( runMessages != null ) fields.setMessage(runMessages.getText().trim()); - if ( nlcdBox != null ) fields.setNlcdDataSelected(nlcdBox.isSelected()); - if ( modisBox != null ) fields.setModisDataSelected(modisBox.isSelected()); - - if ( nlcdYear != null ) { + if (scenarioDir != null) + domain.setScenarioDir(scenarioDir.getText()); + if (scenarioDir != null) + fields.setScenarioDir(scenarioDir.getText()); + if (rows != null) + fields.setRows(Integer.parseInt(rows.getText() == null ? "0" : rows.getValue() + "")); + if (cols != null) + fields.setCols(Integer.parseInt(cols.getText() == null ? "0" : cols.getValue() + "")); + if (xSize != null) + fields.setXcellSize(Float.parseFloat(xSize.getText() == null ? "0" : xSize.getValue() + "")); + if (ySize != null) + fields.setYcellSize(Float.parseFloat(ySize.getText() == null ? "0" : ySize.getValue() + "")); + if (xmin != null) + fields.setXmin(Float.parseFloat(xmin.getText() == null ? "0" : xmin.getValue() + "")); + if (ymin != null) + fields.setYmin(Float.parseFloat(ymin.getText() == null ? "0" : ymin.getValue() + "")); + if (proj4proj != null) + fields.setProj(proj4proj.getText() == null ? "" : proj4proj.getText()); + if (gridName != null) + fields.setGridName(gridName.getText() == null ? "" : gridName.getText()); + if (runMessages != null) + fields.setMessage(runMessages.getText().trim()); + if (nlcdBox != null) + fields.setNlcdDataSelected(nlcdBox.isSelected()); + if (modisBox != null) + fields.setModisDataSelected(modisBox.isSelected()); + + if (nlcdYear != null) { String dYear = (String) this.nlcdYear.getSelectedItem(); domain.setNlcdYear(dYear); } - if ( inputDir != null ) fields.setNLCDfile(inputDir.getText().trim()); - - } - -} + if (inputDir != null) + fields.setNLCDfile(inputDir.getText().trim()); + } +} diff --git a/festc_core/src/gov/epa/festc/gui/CreateAppManFilesPanel.java b/festc_core/src/gov/epa/festc/gui/CreateAppManFilesPanel.java index 6401e02..84270cb 100644 --- a/festc_core/src/gov/epa/festc/gui/CreateAppManFilesPanel.java +++ b/festc_core/src/gov/epa/festc/gui/CreateAppManFilesPanel.java @@ -152,13 +152,35 @@ else if (sFYear != null && !sFYear.trim().isEmpty() outMessages += ls + "Epic base: " + baseDir + ls; outMessages += "Fertlizer year: " + fYear + ls; - final String file = writeRunScript(baseDir, scenarioDir, seCropsString, cropIDs, fYear); + final String jobFile = writeRunScript(baseDir, scenarioDir, seCropsString, cropIDs, fYear); + + String cropNums = getChosenCropNums(); + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir); + } else { + batchFile = null; + } + Thread populateThread = new Thread(new Runnable() { public void run() { - runScript(file); + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile, cropNums); + } } }); populateThread.start(); +// +// Thread populateThread = new Thread(new Runnable() { +// public void run() { +// runScript(file); +// } +// }); +// populateThread.start(); } private void runScript(final String file) { @@ -171,6 +193,33 @@ private void runScript(final String file) { FileRunner.runScript(file, log, msg); } + private void runBatchScript(final String batchFile, final String jobFile, final String chosenCrops) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qManApp = Constants.getProperty(Constants.QUEUE_MAN_APP, msg); + if (qcmd.contains("sbatch")) { + // SLURM + sb.append("sbatch --job-name=EPICManAppArrayJob --output=runEpicManApp_JobArray_%A_%a.out --array=" + + chosenCrops + " " + qManApp + " " + batchFile + ls); + } else if (qcmd.contains("qsub")) { + // PBS + sb.append("qsub -N EPICManAppArrayJob -t " + chosenCrops + " " + qManApp + " " + batchFile + ls); + } else if (qcmd.contains("bsub")) { + // LSF + sb.append("bsub -J EPICManAppArrayJob[" + chosenCrops + "] " + qManApp + " " + batchFile + ls); + } + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } + protected String writeRunScript( String baseDir, String scenarioDir, @@ -185,36 +234,236 @@ protected String writeRunScript( if ( !file.endsWith(System.getProperty("file.separator"))) file += System.getProperty("file.separator"); file += "runEPICManApp_" + timeStamp + ".csh"; - String mesg = ""; - try { - StringBuilder sb = new StringBuilder(); + + StringBuilder sb = new StringBuilder(); + + //scriptContent contains all run instructions for direct submit, or job array + // submit instructions if using a workload manager + String scriptContent = null; + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + if (qcmd == null || qcmd.trim().isEmpty()){ + //no batch system - generate script using legacy code sb.append(getScriptHeader()); sb.append(getEnvironmentDef(baseDir, scenarioDir, fYear)); - sb.append(getManSu(cropNames, cropIDs)); + sb.append(getManSu(cropNames, cropIDs, fYear)); //tile drain script sb.append(getRunTD()); - - File script = new File(file); - - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - - mesg += "Created a script file: " + file + "\n"; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - - } catch (IOException e) { - //e.printStackTrace(); - throw new Exception(e.getMessage()); - } + scriptContent = sb.toString(); + } else { + //assume batch system that supports job arrays (SLURM, PBS, LSF, etc.) + //create job array script + scriptContent = createArrayTaskScript(baseDir, scenarioDir, fYear); + } - app.showMessage("Write script", mesg); + writeScriptFile(file, scriptContent); + +// String mesg = ""; +// try { +// StringBuilder sb = new StringBuilder(); +// sb.append(getScriptHeader()); +// sb.append(getEnvironmentDef(baseDir, scenarioDir, fYear)); +// sb.append(getManSu(cropNames, cropIDs)); +// //tile drain script +// sb.append(getRunTD()); +// +// File script = new File(file); +// +// BufferedWriter out = new BufferedWriter(new FileWriter(script)); +// out.write(sb.toString()); +// out.close(); +// +// mesg += "Created a script file: " + file + "\n"; +// boolean ok = script.setExecutable(true, false); +// mesg += "Set the script file to be executable: "; +// mesg += ok ? "ok." : "failed."; +// +// } catch (IOException e) { +// //e.printStackTrace(); +// throw new Exception(e.getMessage()); +// } +// +// app.showMessage("Write script", mesg); return file; } + // returns comma separated list of chosen crop numbers to run + private String getChosenCropNums() throws Exception{ + String[] seCrops = cropSelectionPanel.getSelectedCrops(); + if ( seCrops == null || seCrops.length == 0) + throw new Exception( "Please select crop(s) first!"); + String crop = null; + String cropIDs = ""; + for (int i=0; i= the minimum crop acres " + ls ); - sb.append("# " + ls + ls ); - - sb.append("setenv MINIMUM_CROP_ACRES " + minAcreas.getText() + ls +ls); - - sb.append("# Define BELD4 input file" + ls ); + + sb.append("# Set minimum crop acres for site selection " + ls); + sb.append("# Grids selected for EPIC modeling will have at " + ls); + sb.append("# least one crop with acreage >= the minimum crop acres " + ls); + sb.append("# " + ls + ls); + + sb.append("setenv MINIMUM_CROP_ACRES " + minAcreas.getText() + ls + ls); + + sb.append("# Define BELD4 input file" + ls); sb.append("setenv DOMAIN_BELD4_NETCDF " + beld4Dir.getText() + ls + ls); - - sb.append("# Define US county shapefiles with " + ls ); + + sb.append("# Define US county shapefiles with " + ls); sb.append("setenv COUNTY_SHAPEFILE $COMM_DIR/gisFiles/co99_d00_conus_cmaq_epic.shp" + ls + ls); - - sb.append("# Define North American State political boundary shapefile" + ls ); + + sb.append("# Define North American State political boundary shapefile" + ls); sb.append("setenv COUNTRY_SHAPEFILE $COMM_DIR/gisFiles/na_bnd_camq_epic.shp" + ls + ls); - - sb.append("# US 8-digit HUC shapefile" + ls ); + + sb.append("# US 8-digit HUC shapefile" + ls); sb.append("setenv HUC8_SHAPEFILE $COMM_DIR/gisFiles/conus_hucs_8_cmaq.shp" + ls + ls); - + sb.append("# Define Elevation image" + ls); sb.append("setenv ELEVATION_IMAGE $COMM_DIR/gisFiles/na_dem_epic.img" + ls + ls); - + sb.append("# Define slope image" + ls); sb.append("setenv SLOPE_IMAGE $COMM_DIR/gisFiles/na_slope_epic.img" + ls + ls); - + sb.append("#" + ls); sb.append("# Output files" + ls); - sb.append("setenv OUTPUT_TEXT_FILE $SCEN_DIR/share_data/EPICSites_Info.csv" + ls ); + sb.append("setenv OUTPUT_TEXT_FILE $SCEN_DIR/share_data/EPICSites_Info.csv" + ls); sb.append("setenv OUTPUT_TEXT_FILE2 $SCEN_DIR/share_data/EPICSites_Crop.csv" + ls); sb.append("setenv OUTPUT_TEXT_FILE3 $SCEN_DIR/share_data/allSites_Info.csv" + ls + ls); - + sb.append("# Run the tool" + ls); sb.append("$SA_HOME/bin/64bits/compute_EPICSiteData.exe" + ls + ls); - + sb.append(" if ( $status == 0 ) then " + ls); sb.append(" echo ==== Finished crop site info generation. " + ls); sb.append(" else " + ls); sb.append(" echo ==== Error in crop site info generation." + ls + ls); - sb.append(" echo " + ls ); + sb.append(" echo " + ls); sb.append(" endif " + ls); sb.append("#===================================================================" + ls); - outMessages += "OUTPUT_TEXT_FILE $SCEN_DIR/share_data/EPICSite_Info.csv" +ls; - outMessages += "OUTPUT_TEXT_FILE2 $SCEN_DIR/share_data/EPICSite_Crop.csv" +ls; - outMessages += "OUTPUT_TEXT_FILE3 $SCEN_DIR/share_data/allSite_Info.csv" +ls; + outMessages += "OUTPUT_TEXT_FILE $SCEN_DIR/share_data/EPICSite_Info.csv" + ls; + outMessages += "OUTPUT_TEXT_FILE2 $SCEN_DIR/share_data/EPICSite_Crop.csv" + ls; + outMessages += "OUTPUT_TEXT_FILE3 $SCEN_DIR/share_data/allSite_Info.csv" + ls; String mesg = ""; try { File script = new File(file); Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - mesg += "Created a script file: " + file + ls; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - } catch (IOException e) { - throw new Exception(e.getMessage()); - } - app.showMessage("Write script", mesg); + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + mesg += "Created a script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + } catch (IOException e) { + throw new Exception(e.getMessage()); + } + app.showMessage("Write script", mesg); return file; } - + private String getScriptHeader() { StringBuilder sb = new StringBuilder(); String ls = "\n"; sb.append("#!/bin/csh -f" + ls); sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to generate EPIC site table for EPIC modeling from:" + ls); - sb.append("# 1. Grid description " + ls); - sb.append("# 2. BELD4 NetCDF file - contains CROPF variable - 40 classes " + ls); - sb.append("# 3. US county shapefile with attributes: STATE(string), COUNTY(string), " + ls); + sb.append("# Purpose: to generate EPIC site table for EPIC modeling from:" + ls); + sb.append("# 1. Grid description " + ls); + sb.append("# 2. BELD4 NetCDF file - contains CROPF variable - 40 classes " + ls); + sb.append("# 3. US county shapefile with attributes: STATE(string), COUNTY(string), " + ls); sb.append("# FIPS(string), COUNTRY(string), STATEABB(string), REGION10(short)" + ls); sb.append("# 4. North American political state shapefile with attributes: " + ls); - sb.append("# COUNTRY(string), STATEABB(string) " + ls); - sb.append("# 5. US 8-digit HUC boundary shapefile with attribute: HUC_8(string)" + ls); - sb.append("# 6. DEM elevation data: meters and missing value=-9999" + ls); - sb.append("# 7. DEM slope data: 0 to 90 degree with scalar 0.01 and missing value -9999" + ls); + sb.append("# COUNTRY(string), STATEABB(string) " + ls); + sb.append("# 5. US 8-digit HUC boundary shapefile with attribute: HUC_8(string)" + ls); + sb.append("# 6. DEM elevation data: meters and missing value=-9999" + ls); + sb.append("# 7. DEM slope data: 0 to 90 degree with scalar 0.01 and missing value -9999" + ls); sb.append("#" + ls); sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); sb.append("# in support of the EPA CMAS project, 2012-2013." + ls); @@ -319,17 +400,17 @@ private String getScriptHeader() { sb.append("# Written by: L. R., NOV. 2012" + ls); sb.append("#" + ls); sb.append("# Call program: compute_EPICSiteData.exe" + ls); - sb.append("# Needed environment variables included in the script file to run." + ls); - sb.append("#" + ls); + sb.append("# Needed environment variables included in the script file to run." + ls); + sb.append("#" + ls); sb.append("#***************************************************************************************" + ls + ls); - + return sb.toString(); } - + private void runScript(final String file) { String log = file + ".log"; - + outMessages += "Script file: " + file + ls; outMessages += "Log file: " + log + ls; runMessages.setText(outMessages); @@ -337,6 +418,27 @@ private void runScript(final String file) { FileRunner.runScript(file, log, msg); } + private void runBatchScript(final String batchFile, final String jobFile) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qSiteInfo = Constants.getProperty(Constants.QUEUE_SITE_INFO, msg); + + File script = new File(batchFile.replaceAll("\\\\", "\\\\\\\\")); + +// sb.append(qcmd + " " + qSiteInfo + " -o " + log + " " + script.getAbsolutePath()); + sb.append(script.getAbsolutePath() + " >& " + log); + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } + @Override public void newProjectCreated() { domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); @@ -351,18 +453,18 @@ public void newProjectCreated() { scenarioDir.setText(domain.getScenarioDir()); String scenDir = domain.getScenarioDir().trim(); - String gName = domain.getGridName().trim(); + String gName = domain.getGridName().trim(); String nlcdY = domain.getNlcdYear().trim(); - String beld4file = scenDir + "/share_data/beld4_" + gName + "_" + nlcdY +".nc"; - //File f = new File(beld4file); - //if(f.exists()){ - this.beld4Dir.setText(beld4file); -// } -// else -// this.beld4Dir.setText(scenDir); + String beld4file = scenDir + "/share_data/beld4_" + gName + "_" + nlcdY + ".nc"; + // File f = new File(beld4file); + // if(f.exists()){ + this.beld4Dir.setText(beld4file); + // } + // else + // this.beld4Dir.setText(scenDir); runMessages.setText(""); - minAcreas.setText("40.0"); - if ( fields == null ) { + minAcreas.setText("0.0"); + if (fields == null) { fields = new SiteInfoGenFields(); app.getProject().addPage(fields); } @@ -372,19 +474,19 @@ public void newProjectCreated() { public void projectLoaded() { domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); fields = (SiteInfoGenFields) app.getProject().getPage(fields.getName()); - - if( fields != null ) { + + if (fields != null) { String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length()>0 ) + if (scenloc != null && scenloc.trim().length() > 0) this.scenarioDir.setText(scenloc); - else + else this.scenarioDir.setText(fields.getScenarioDir()); String scenDir = domain.getScenarioDir().trim(); - String gridNames = domain.getGridName().trim(); - String year = domain.getNlcdYear()==null?"":domain.getNlcdYear().trim(); + String gridNames = domain.getGridName().trim(); + String year = domain.getNlcdYear() == null ? "" : domain.getNlcdYear().trim(); String beld4file = fields.getBeld4ncf(); - if ( beld4file == null || beld4file.trim().isEmpty() ) - beld4file = scenDir + "/share_data/beld4_" + gridName + "_" + year +".nc"; + if (beld4file == null || beld4file.trim().isEmpty()) + beld4file = scenDir + "/share_data/beld4_" + gridName + "_" + year + ".nc"; this.beld4Dir.setText(beld4file); this.runMessages.setText(fields.getMessage()); rows.setValue(domain.getRows()); @@ -394,34 +496,45 @@ public void projectLoaded() { xSize.setValue(domain.getXcellSize()); ySize.setValue(domain.getYcellSize()); proj4proj.setText(domain.getProj()); - gridName.setText(gridNames); - minAcreas.setText(fields.getMinAcres()==null? "40.0":fields.getMinAcres()); + gridName.setText(gridNames); + minAcreas.setText(fields.getMinAcres() == null ? "0.0" : fields.getMinAcres()); domain.setCMinAcres(domain.getCMinAcres()); - }else { + } else { newProjectCreated(); - } - //setFalseEditable(); + } + // setFalseEditable(); } @Override public void saveProjectRequested() { - if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); - if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); - if ( rows != null ) fields.setRows(Integer.parseInt(rows.getText() == null? "0" : rows.getValue()+"")); - if ( beld4Dir != null ) fields.setBeld4ncf(beld4Dir.getText()== null? "" : beld4Dir.getText()); - if ( cols != null ) fields.setCols(Integer.parseInt(cols.getText() == null? "0" : cols.getValue()+"")); - if ( xSize != null ) fields.setXcellSize(Float.parseFloat(xSize.getText() == null? "0" : xSize.getValue()+"")); - if ( ySize != null ) fields.setYcellSize(Float.parseFloat(ySize.getText() == null? "0" : ySize.getValue()+"")); - if ( xmin != null ) fields.setXmin(Float.parseFloat(xmin.getText() == null? "0" : xmin.getValue()+"")); - if ( ymin != null ) fields.setYmin(Float.parseFloat(ymin.getText() == null? "0" : ymin.getValue()+"")); - if ( proj4proj != null ) fields.setProj(proj4proj.getText() == null? "" : proj4proj.getText()); - if ( gridName != null ) fields.setGridName(gridName.getText()== null? "" : gridName.getText()); - if ( runMessages != null ) fields.setMessage(runMessages.getText()); - if ( minAcreas != null) fields.setMinAcres(minAcreas.getText()); + if (scenarioDir != null) + domain.setScenarioDir(scenarioDir.getText()); + if (scenarioDir != null) + fields.setScenarioDir(scenarioDir.getText()); + if (rows != null) + fields.setRows(Integer.parseInt(rows.getText() == null ? "0" : rows.getValue() + "")); + if (beld4Dir != null) + fields.setBeld4ncf(beld4Dir.getText() == null ? "" : beld4Dir.getText()); + if (cols != null) + fields.setCols(Integer.parseInt(cols.getText() == null ? "0" : cols.getValue() + "")); + if (xSize != null) + fields.setXcellSize(Float.parseFloat(xSize.getText() == null ? "0" : xSize.getValue() + "")); + if (ySize != null) + fields.setYcellSize(Float.parseFloat(ySize.getText() == null ? "0" : ySize.getValue() + "")); + if (xmin != null) + fields.setXmin(Float.parseFloat(xmin.getText() == null ? "0" : xmin.getValue() + "")); + if (ymin != null) + fields.setYmin(Float.parseFloat(ymin.getText() == null ? "0" : ymin.getValue() + "")); + if (proj4proj != null) + fields.setProj(proj4proj.getText() == null ? "" : proj4proj.getText()); + if (gridName != null) + fields.setGridName(gridName.getText() == null ? "" : gridName.getText()); + if (runMessages != null) + fields.setMessage(runMessages.getText()); + if (minAcreas != null) + fields.setMinAcres(minAcreas.getText()); fields.setBeld4ncf(beld4Dir.getText().trim()); domain.setCMinAcres(minAcreas.getText()); } - -} - +} diff --git a/festc_core/src/gov/epa/festc/gui/CreateSpinupManFilesPanel.java b/festc_core/src/gov/epa/festc/gui/CreateSpinupManFilesPanel.java index 84d7803..d72e52f 100644 --- a/festc_core/src/gov/epa/festc/gui/CreateSpinupManFilesPanel.java +++ b/festc_core/src/gov/epa/festc/gui/CreateSpinupManFilesPanel.java @@ -1,337 +1,585 @@ -package gov.epa.festc.gui; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.core.proj.DomainFields; -import gov.epa.festc.core.proj.ManageSpinupFields; -import gov.epa.festc.util.Constants; -import gov.epa.festc.util.FileRunner; -import gov.epa.festc.util.ModelYearInconsistantException; -import gov.epa.festc.util.SpringLayoutGenerator; - -import java.awt.Dimension; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SpringLayout; -import javax.swing.SwingConstants; - -import simphony.util.messages.MessageCenter; - -public class CreateSpinupManFilesPanel extends UtilFieldsPanel implements PlotEventListener { - - /** - * - */ - private static final long serialVersionUID = 7631048430725473655L; - - private FestcApplication app; - private MessageCenter msg; - - private ManageSpinupFields fields; - //private DomainFields domain; - - private CropSelectionPanel cropSelectionPanel; - - public CreateSpinupManFilesPanel(FestcApplication application) { - app = application; - fields = new ManageSpinupFields(); - app.getProject().addPage(fields); - app.addPlotListener(this); - msg = app.getMessageCenter(); - add(createPanel()); - } - - private JPanel createPanel() { - JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - mainPanel.add(getNorthPanel()); - - mainPanel.add(scenPanel()); - mainPanel.add(fertYearPanel()); - mainPanel.add(cropsPanel()); - mainPanel.add(messageBox()); - return mainPanel; - } - - private JPanel cropsPanel(){ - JPanel panel = new JPanel(new SpringLayout()); - SpringLayoutGenerator layout = new SpringLayoutGenerator(); - JPanel buttonPanel = new JPanel(); - JButton btn = new JButton(generateManSpinupAction()); - btn.setPreferredSize(new Dimension(100,50)); - buttonPanel.add(btn); - buttonPanel.setBorder(BorderFactory.createEmptyBorder(70, 30, 70, 30)); - this.cropSelectionPanel = new CropSelectionPanel(app); - - layout.addWidgetPair(cropSelectionPanel, buttonPanel, panel); - layout.makeCompactGrid(panel, 1, 2, // number of rows and cols - 10, 10, // initial X and Y - 5, 5); // x and y pading - return panel; - } - - private JPanel getNorthPanel() { - JPanel panel = new JPanel(); - JLabel title = new JLabel(Constants.MAN_SPINUP, SwingConstants.CENTER); - title.setFont(new Font("Default", Font.BOLD, 20)); - - panel.add(title); - panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); - - return panel; - } - - private Action generateManSpinupAction() { - return new AbstractAction("Run") { - - public void actionPerformed(ActionEvent e) { - try { - generateRunScript(); - } catch (Exception exc) { - //exc.printStackTrace(); - app.showMessage("Run script", exc.getMessage()); - } - } - }; - } - - private void generateRunScript() throws Exception { - String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - if (baseDir == null || baseDir.isEmpty()) - throw new Exception("Base dir is empty, please specify it in the configuration file!"); - - String scenarioDir = this.scenarioDir.getText(); - if ( scenarioDir == null || scenarioDir.isEmpty()) - throw new Exception("Please select scenario dir first!"); - - String fYear = (String) this.fertYearSel.getSelectedItem(); - if ( fYear.trim().isEmpty() ) - throw new Exception("Please select fertilizer year!"); - - String sFYear = domain.getCFertYear(); - if (sFYear == null || sFYear.trim().isEmpty()) { - domain.setCFertYear(fYear); - sFYear = fYear; - } - else if (sFYear != null && !sFYear.trim().isEmpty() - && !sFYear.endsWith(fYear) && app.allowDiffCheck()) - throw new Exception("Current land use year " + fYear + " is inconsistent with previous one (" + sFYear + ")"); - //System.out.println("sfYear: " + sFYear + " " + fYear); - String seCropsString = cropSelectionPanel.selectedItemTostring(); - //System.out.println(); - String[] seCrops = cropSelectionPanel.getSelectedCrops(); - if ( seCrops == null || seCrops.length == 0 ) - throw new Exception("Please select crop(s) first!"); - - outMessages += ls + "Epic base: " + baseDir + ls; - outMessages += "Scen directory: " + scenarioDir + ls; - outMessages += "Fertlizer year: " + fYear + ls; - final String file = writeRunScript(baseDir, scenarioDir, seCropsString, fYear); - Thread populateThread = new Thread(new Runnable() { - public void run() { - runScript(file); - } - }); - populateThread.start(); - } - - private void runScript(final String file) { - String log = file + ".log"; - - outMessages += "Script file: " + file + ls; - outMessages += "Log file: " + log + ls; - runMessages.setText(outMessages); - runMessages.validate(); - FileRunner.runScript(file, log, msg); - } - - private String writeRunScript( - String baseDir, - String scenarioDir, - String cropNames, - String fYear) throws Exception { - Date now = new Date(); // java.util.Date, NOT java.sql.Date or java.sql.Timestamp! - String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - - String file = scenarioDir.trim() + "/scripts"; - - if ( !file.endsWith(System.getProperty("file.separator"))) - file += System.getProperty("file.separator"); - file += "runEpicManSpinup_" + timeStamp + ".csh"; - String mesg = ""; - try { - StringBuilder sb = new StringBuilder(); - sb.append(getScriptHeader()); - sb.append(getEnvironmentDef(baseDir, scenarioDir, fYear)); - sb.append(getManSu(cropNames)); - - sb.append(getRunTD(baseDir)); - - File script = new File(file); - - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - - mesg += "Script file: " + file + "\n"; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - - } catch (IOException e) { - //e.printStackTrace(); - //msg.error("Error generating EPIC script file", e); - throw new Exception(e.getMessage()); - } - - app.showMessage("Write script", mesg); - - return file; - } - - private String getScriptHeader() { - StringBuilder sb = new StringBuilder(); - - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to run management spinup utility" + ls); - sb.append("#" + ls); - sb.append("# Written by: Fortran by Benson, Script by IE. 2012" + ls); - sb.append("# Modified by:" + ls); - sb.append("#" + ls); - sb.append("# Program: ManGenSU.exe" + ls); - sb.append("# " + ls); - sb.append("#***************************************************************************************" + ls + ls); - - return sb.toString(); - } - - private String getEnvironmentDef(String baseDir, String scenarioDir, String fYear) { - StringBuilder sb = new StringBuilder(); - - sb.append(ls + "#" + ls); - sb.append("# Define environment variables" + ls); - sb.append("#" + ls + ls); - - sb.append("setenv EPIC_DIR " + baseDir + ls); - sb.append("setenv SCEN_DIR " + scenarioDir + ls); - sb.append("setenv SOIL_DIR $EPIC_DIR/common_data/BaumerSoils" +ls); - sb.append("setenv MANG_DIR $EPIC_DIR/common_data/util/manageCreate/" + fYear + ls); - sb.append("setenv WEAT_DIR $EPIC_DIR/common_data/statWeath" + ls); - - sb.append("" + ls); - sb.append("set EXEC_DIR = " + baseDir + "/util/manageCreate" + ls); - sb.append("" + ls); - - return sb.toString(); - } - - private String getManSu(String cropNames){ - StringBuilder sb = new StringBuilder(); - - sb.append("#" + ls); - sb.append("# set input variables" + ls); - sb.append("set CROPS = " + cropNames + ls); - sb.append("foreach crop ($CROPS) " + ls); - sb.append(" setenv CROP_NAME $crop " + ls); - sb.append(" if ( ! -e $SCEN_DIR/$CROP_NAME/spinup/manage/OPC ) " + - " mkdir -p $SCEN_DIR/$CROP_NAME/spinup/manage/OPC " + ls); - sb.append("#" + ls); - String exe; - exe = "$EXEC_DIR/ManGenSU.exe"; - - sb.append(ls + "#" + ls); - sb.append("# Generate management spinup files " + ls); - sb.append("#" + ls + ls); - sb.append(" echo ==== Begin EPIC management spinup run of CROP: $CROP_NAME " + ls); - sb.append(" time " + exe + ls ); - sb.append(" if ( $status == 0 ) then" + ls); - sb.append(" echo ==== Finished EPIC management spinup run of CROP: $CROP_NAME" + ls); - sb.append(" else " + ls); - sb.append(" echo ==== Error in EPIC management spinup run of CROP: $CROP_NAME" + ls); - sb.append(" endif " + ls); - sb.append("end " + ls ); - sb.append(ls); - - return sb.toString(); - } - - private String getRunTD(String baseDir){ - StringBuilder sb = new StringBuilder(); - sb.append(ls + "#" + ls); - - sb.append("# Run tile drain " + ls + ls); - sb.append("setenv WORK_DIR $SCEN_DIR/work_dir" + ls); - sb.append("setenv COMM_DIR $EPIC_DIR/common_data" + ls); - sb.append("setenv TYPE_NAME spinup" + ls); - //sb.append("set EXEC_DIR = " + baseDir + "/util/tileDrain" + ls +ls); - sb.append("foreach crop ($CROPS) " + ls); - sb.append(" setenv CROP_NAME $crop " + ls); - sb.append(" if ( ! -e $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain ) " + - "mkdir -p $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain" + ls); - sb.append(" time $EXEC_DIR/soilDrain.exe" + ls); - sb.append(" if ( $status == 0 ) then" + ls); - sb.append(" echo ==== Finished soil drain run for crop $CROP_NAME. " + ls); - sb.append(" else " + ls); - sb.append(" echo ==status== Error in soil drain run for crop $CROP_NAME. " + ls); - sb.append(" exit 1 " + ls); - sb.append(" endif " + ls); - - sb.append(" mv $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain/SOILLISTALLSU.DAT " + - "$SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain/SOILLIST.DAT" + ls); - - sb.append("end " + ls ); - sb.append(ls); - return sb.toString(); - } - - - public void projectLoaded() { - fields = (ManageSpinupFields) app.getProject().getPage(fields.getName()); - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - if ( fields != null ){ - String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length()>0 ) - this.scenarioDir.setText(scenloc); - else - this.scenarioDir.setText(fields.getScenarioDir()); - fertYearSel.setSelectedItem(fields.getFertYear()); - runMessages.setText(fields.getMessage()); - }else{ - newProjectCreated(); - } - } - - public void saveProjectRequested() { - if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); - if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); - if ( fertYearSel != null) fields.setFertYear((String)fertYearSel.getSelectedItem()); - if ( runMessages != null ) fields.setMessage(runMessages.getText()); - } - - @Override - public void newProjectCreated() { - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - - scenarioDir.setText(domain.getScenarioDir()); - runMessages.setText(""); - if ( fields == null ) { - fields = new ManageSpinupFields(); - app.getProject().addPage(fields); - } - } -} +package gov.epa.festc.gui; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.core.proj.DomainFields; +import gov.epa.festc.core.proj.ManageSpinupFields; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.FileRunner; +import gov.epa.festc.util.ModelYearInconsistantException; +import gov.epa.festc.util.SpringLayoutGenerator; + +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SpringLayout; +import javax.swing.SwingConstants; + +import simphony.util.messages.MessageCenter; + +public class CreateSpinupManFilesPanel extends UtilFieldsPanel implements PlotEventListener { + + /** + * + */ + private static final long serialVersionUID = 7631048430725473655L; + + private FestcApplication app; + private MessageCenter msg; + + private ManageSpinupFields fields; + // private DomainFields domain; + + private CropSelectionPanel cropSelectionPanel; + + public CreateSpinupManFilesPanel(FestcApplication application) { + app = application; + fields = new ManageSpinupFields(); + app.getProject().addPage(fields); + app.addPlotListener(this); + msg = app.getMessageCenter(); + add(createPanel()); + } + + private JPanel createPanel() { + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + mainPanel.add(getNorthPanel()); + + mainPanel.add(scenPanel()); + mainPanel.add(fertYearPanel()); + mainPanel.add(cropsPanel()); + mainPanel.add(messageBox()); + return mainPanel; + } + + private JPanel cropsPanel() { + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + JPanel buttonPanel = new JPanel(); + JButton btn = new JButton(generateManSpinupAction()); + btn.setPreferredSize(new Dimension(100, 50)); + buttonPanel.add(btn); + buttonPanel.setBorder(BorderFactory.createEmptyBorder(70, 30, 70, 30)); + this.cropSelectionPanel = new CropSelectionPanel(app); + + layout.addWidgetPair(cropSelectionPanel, buttonPanel, panel); + layout.makeCompactGrid(panel, 1, 2, // number of rows and cols + 10, 10, // initial X and Y + 5, 5); // x and y pading + return panel; + } + + private JPanel getNorthPanel() { + JPanel panel = new JPanel(); + JLabel title = new JLabel(Constants.MAN_SPINUP, SwingConstants.CENTER); + title.setFont(new Font("Default", Font.BOLD, 20)); + + panel.add(title); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + + return panel; + } + + private Action generateManSpinupAction() { + return new AbstractAction("Run") { + + public void actionPerformed(ActionEvent e) { + try { + generateRunScript(); + } catch (Exception exc) { + // exc.printStackTrace(); + app.showMessage("Run script", exc.getMessage()); + } + } + }; + } + + private void generateRunScript() throws Exception { + String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + if (baseDir == null || baseDir.isEmpty()) + throw new Exception("Base dir is empty, please specify it in the configuration file!"); + + String scenarioDir = this.scenarioDir.getText(); + if (scenarioDir == null || scenarioDir.isEmpty()) + throw new Exception("Please select scenario dir first!"); + + String fYear = (String) this.fertYearSel.getSelectedItem(); + if (fYear.trim().isEmpty()) + throw new Exception("Please select fertilizer year!"); + + String sFYear = domain.getCFertYear(); + if (sFYear == null || sFYear.trim().isEmpty()) { + domain.setCFertYear(fYear); + sFYear = fYear; + } else if (sFYear != null && !sFYear.trim().isEmpty() && !sFYear.endsWith(fYear) && app.allowDiffCheck()) + throw new Exception( + "Current land use year " + fYear + " is inconsistent with previous one (" + sFYear + ")"); + // System.out.println("sfYear: " + sFYear + " " + fYear); + String seCropsString = cropSelectionPanel.selectedItemTostring(); + // System.out.println(); + String[] seCrops = cropSelectionPanel.getSelectedCrops(); + if (seCrops == null || seCrops.length == 0) + throw new Exception("Please select crop(s) first!"); + + outMessages += ls + "Epic base: " + baseDir + ls; + outMessages += "Scen directory: " + scenarioDir + ls; + outMessages += "Fertlizer year: " + fYear + ls; + final String jobFile = writeRunScript(baseDir, scenarioDir, seCropsString, fYear); + + String cropNums = getChosenCropNums(); + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir); + } else { + batchFile = null; + } + + Thread populateThread = new Thread(new Runnable() { + public void run() { + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile, cropNums); + } + } + }); + populateThread.start(); + + // Thread populateThread = new Thread(new Runnable() { + // public void run() { + // runScript(file); + // } + // }); + // populateThread.start(); + } + + private void runScript(final String file) { + String log = file + ".log"; + + outMessages += "Script file: " + file + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + FileRunner.runScript(file, log, msg); + } + + private void runBatchScript(final String batchFile, final String jobFile, final String chosenCrops) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qManSpinup = Constants.getProperty(Constants.QUEUE_MAN_SPINUP, msg); + if (qcmd.contains("sbatch")) { + // SLURM + sb.append("sbatch --job-name=EPICManSpinupArrayJob --output=runEpicManSpinup_JobArray_%A_%a.out --array=" + + chosenCrops + " " + qManSpinup + " " + batchFile + ls); + } else if (qcmd.contains("qsub")) { + // PBS + sb.append("qsub -N EPICManSpinupArrayJob -t " + chosenCrops + " " + qManSpinup + " " + batchFile + ls); + } else if (qcmd.contains("bsub")) { + // LSF + sb.append("bsub -J EPICManSpinupArrayJob[" + chosenCrops + "] " + qManSpinup + " " + batchFile + ls); + } + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } + + private String writeRunScript(String baseDir, String scenarioDir, String cropNames, String fYear) throws Exception { + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + + String file = scenarioDir.trim() + "/scripts"; + + if (!file.endsWith(System.getProperty("file.separator"))) + file += System.getProperty("file.separator"); + file += "runEpicManSpinup_" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + + // scriptContent contains all run instructions for direct submit, or job + // array + // submit instructions if using a workload manager + String scriptContent = null; + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + if (qcmd == null || qcmd.trim().isEmpty()) { + // no batch system - generate script using legacy code + sb.append(getScriptHeader()); + sb.append(getEnvironmentDef(baseDir, scenarioDir, fYear)); + sb.append(getManSu(cropNames)); + sb.append(getRunTD(baseDir)); + scriptContent = sb.toString(); + } else { + // assume batch system that supports job arrays (SLURM, PBS, LSF, + // etc.) + // create job array script + scriptContent = createArrayTaskScript(baseDir, scenarioDir, fYear); + } + + writeScriptFile(file, scriptContent); + // String mesg = ""; + // try { + // StringBuilder sb = new StringBuilder(); + // sb.append(getScriptHeader()); + // sb.append(getEnvironmentDef(baseDir, scenarioDir, fYear)); + // sb.append(getManSu(cropNames)); + // + // sb.append(getRunTD(baseDir)); + // + // File script = new File(file); + // + // BufferedWriter out = new BufferedWriter(new FileWriter(script)); + // out.write(sb.toString()); + // out.close(); + // + // mesg += "Script file: " + file + "\n"; + // boolean ok = script.setExecutable(true, false); + // mesg += "Set the script file to be executable: "; + // mesg += ok ? "ok." : "failed."; + // + // } catch (IOException e) { + // //e.printStackTrace(); + // //msg.error("Error generating EPIC script file", e); + // throw new Exception(e.getMessage()); + // } + // + // app.showMessage("Write script", mesg); + + return file; + } + + // This is legacy code that has been moved to it's own method + protected void writeScriptFile(String file, String content) { + + String mesg = ""; + + try { + File script = new File(file); + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(content); + out.close(); + + mesg += "Script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + + } catch (IOException e) { + // printStackTrace(); + // g.error("Error generating EPIC script file", e); + app.showMessage("Write script", e.getMessage()); + } + + app.showMessage("Write script", mesg); + } + + protected String writeBatchFile(String jobFile, String scenarioDir) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String batchFile = scenarioDir.trim() + "/scripts"; + if (!batchFile.endsWith(System.getProperty("file.separator"))) + batchFile += System.getProperty("file.separator"); + batchFile += "submitEpicManSpinup" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh" + ls + ls); + + // TODO - add #SBATCH options here + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage == null || qSingModule.trim().isEmpty()) { + throw new Exception("Singularity image path must be specified"); + } + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + jobFile); + } else { + sb.append(jobFile); + } + + writeScriptFile(batchFile, sb.toString()); + + return batchFile; + } + + // returns comma separated list of chosen crop numbers to run + private String getChosenCropNums() throws Exception { + String[] seCrops = cropSelectionPanel.getSelectedCrops(); + if (seCrops == null || seCrops.length == 0) + throw new Exception("Please select crop(s) first!"); + String crop = null; + String cropIDs = ""; + for (int i = 0; i < seCrops.length; i++) { + crop = seCrops[i]; + Integer cropID = Constants.CROPS.get(crop); + if (cropID == null || cropID <= 0) + throw new Exception("crop id is null for crop " + crop); + // Integer cropIrID = cropID +1; + if (i != 0) { + cropIDs += "," + cropID; + } else { + cropIDs = "" + cropID; + } + // cropIDs += "," + cropIrID; + } + + return cropIDs; + } + + private String createArrayTaskScript(String baseDir, String scenarioDir, String fYear) { + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + String arrayIdEnvVar = ""; + + if (qcmd.contains("sbatch")) { + // SLURM + arrayIdEnvVar = "$SLURM_ARRAY_TASK_ID"; + } else if (qcmd.contains("qsub")) { + // PBS + arrayIdEnvVar = "$PBS_ARRAYID"; + } else if (qcmd.contains("bsub")) { + // LSF + arrayIdEnvVar = "$LSB_JOBINDEX"; + } + + StringBuilder sb = new StringBuilder(); + + // header + sb.append("#!/bin/csh -f" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: to run management spinup utility job array task" + ls); + sb.append("# SLURM example cmd:" + ls); + sb.append( + "# sbatch --job-name=EPICManSpinupArrayJob --output=submitEPICManSpinup_JobArray_%A_%a.out --array=1,31 --time=2:00:00" + + ls); + sb.append("# /PATH_TO_SCRIPT/runEpicManSpinup_TIMESTAMP.csh" + ls); + sb.append("# where 1,31 are rainfed (odd) crop numbers only" + ls); + sb.append("#" + ls); + sb.append("# Written by: Fortran by Benson, Original Script by IE. 2012" + ls); + sb.append("# Modified by: EMVL " + ls); + sb.append("#" + ls); + sb.append("# Program: ManGenSU.exe" + ls); + sb.append("# " + ls); + sb.append("#***************************************************************************************" + ls + ls); + + sb.append(getEnvironmentDef(baseDir, scenarioDir, fYear)); + + sb.append("set CROPS = (HAY ALFALFA OTHGRASS BARLEY EBEANS CORNG CORNS COTTON OATS PEANUTS POTATOES RICE RYE)" + + ls); + sb.append("set CROPS = ($CROPS SORGHUMG SORGHUMS SOYBEANS SWHEAT WWHEAT OTHER CANOLA BEANS)" + ls + ls); + + sb.append("# Set output dir" + ls); + + // sb.append("setenv CROP_NUM $SLURM_ARRAY_TASK_ID" + ls); + sb.append("setenv CROP_NUM " + arrayIdEnvVar + ls); + sb.append("@ rem = $CROP_NUM % 2" + ls); + sb.append("@ ind = ($CROP_NUM + $rem) / 2" + ls); + sb.append("setenv CROP_NAME $CROPS[$ind]" + ls); + sb.append("if ( ! -e $SCEN_DIR/$CROP_NAME/spinup/manage/OPC ) mkdir -p $SCEN_DIR/$CROP_NAME/spinup/manage/OPC" + + ls); + + sb.append("#" + ls); + sb.append("## Generate management spinup files" + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("echo ==== Begin EPIC management spinup run of CROP: $CROP_NAME" + ls); + sb.append("time $EXEC_DIR/ManGenSU.exe" + ls); + sb.append("if ( $status == 0 ) then" + ls); + sb.append(" echo ==== Finished EPIC management spinup run of CROP: $CROP_NAME" + ls); + sb.append("else" + ls); + sb.append(" echo ==== Error in EPIC management spinup run of CROP: $CROP_NAME" + ls); + sb.append("endif" + ls); + + sb.append("#" + ls); + sb.append("## Run tile drain" + ls); + + sb.append("setenv WORK_DIR $SCEN_DIR/work_dir" + ls); + sb.append("setenv COMM_DIR $EPIC_DIR/common_data" + ls); + sb.append("setenv TYPE_NAME spinup" + ls); + sb.append( + "if ( ! -e $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain ) mkdir -p $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain" + + ls); + sb.append("time $EXEC_DIR/soilDrain.exe" + ls); + sb.append(" if ( $status == 0 ) then" + ls); + sb.append(" echo ==== Finished soil drain run for crop $CROP_NAME." + ls); + sb.append(" else" + ls); + sb.append(" echo ==status== Error in soil drain run for crop $CROP_NAME." + ls); + sb.append(" exit 1" + ls); + sb.append(" endif" + ls); + sb.append( + "mv $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain/SOILLISTALLSU.DAT $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain/SOILLIST.DAT" + + ls); + + return sb.toString(); + + } + + private String getScriptHeader() { + StringBuilder sb = new StringBuilder(); + + sb.append("#!/bin/csh -f" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: to run management spinup utility" + ls); + sb.append("#" + ls); + sb.append("# Written by: Fortran by Benson, Script by IE. 2012" + ls); + sb.append("# Modified by:" + ls); + sb.append("#" + ls); + sb.append("# Program: ManGenSU.exe" + ls); + sb.append("# " + ls); + sb.append("#***************************************************************************************" + ls + ls); + + return sb.toString(); + } + + private String getEnvironmentDef(String baseDir, String scenarioDir, String fYear) { + StringBuilder sb = new StringBuilder(); + + sb.append(ls + "#" + ls); + sb.append("# Define environment variables" + ls); + sb.append("#" + ls + ls); + + sb.append("setenv EPIC_DIR " + baseDir + ls); + sb.append("setenv SCEN_DIR " + scenarioDir + ls); + sb.append("setenv SOIL_DIR $EPIC_DIR/common_data/BaumerSoils" + ls); + sb.append("setenv MANG_DIR $EPIC_DIR/common_data/util/manageCreate/" + fYear + ls); + sb.append("setenv WEAT_DIR $EPIC_DIR/common_data/statWeath" + ls); + + sb.append("" + ls); + sb.append("set EXEC_DIR = " + baseDir + "/util/manageCreate" + ls); + sb.append("" + ls); + + return sb.toString(); + } + + private String getManSu(String cropNames) { + StringBuilder sb = new StringBuilder(); + + sb.append("#" + ls); + sb.append("# set input variables" + ls); + sb.append("set CROPS = " + cropNames + ls); + sb.append("foreach crop ($CROPS) " + ls); + sb.append(" setenv CROP_NAME $crop " + ls); + sb.append(" if ( ! -e $SCEN_DIR/$CROP_NAME/spinup/manage/OPC ) " + + " mkdir -p $SCEN_DIR/$CROP_NAME/spinup/manage/OPC " + ls); + sb.append("#" + ls); + String exe; + exe = "$EXEC_DIR/ManGenSU.exe"; + + sb.append(ls + "#" + ls); + sb.append("# Generate management spinup files " + ls); + sb.append("#" + ls + ls); + sb.append(" echo ==== Begin EPIC management spinup run of CROP: $CROP_NAME " + ls); + sb.append(" time " + exe + ls); + sb.append(" if ( $status == 0 ) then" + ls); + sb.append(" echo ==== Finished EPIC management spinup run of CROP: $CROP_NAME" + ls); + sb.append(" else " + ls); + sb.append(" echo ==== Error in EPIC management spinup run of CROP: $CROP_NAME" + ls); + sb.append(" endif " + ls); + sb.append("end " + ls); + sb.append(ls); + + return sb.toString(); + } + + private String getRunTD(String baseDir) { + StringBuilder sb = new StringBuilder(); + sb.append(ls + "#" + ls); + + sb.append("# Run tile drain " + ls + ls); + sb.append("setenv WORK_DIR $SCEN_DIR/work_dir" + ls); + sb.append("setenv COMM_DIR $EPIC_DIR/common_data" + ls); + sb.append("setenv TYPE_NAME spinup" + ls); + // sb.append("set EXEC_DIR = " + baseDir + "/util/tileDrain" + ls +ls); + sb.append("foreach crop ($CROPS) " + ls); + sb.append(" setenv CROP_NAME $crop " + ls); + sb.append(" if ( ! -e $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain ) " + + "mkdir -p $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain" + ls); + sb.append(" time $EXEC_DIR/soilDrain.exe" + ls); + sb.append(" if ( $status == 0 ) then" + ls); + sb.append(" echo ==== Finished soil drain run for crop $CROP_NAME. " + ls); + sb.append(" else " + ls); + sb.append(" echo ==status== Error in soil drain run for crop $CROP_NAME. " + ls); + sb.append(" exit 1 " + ls); + sb.append(" endif " + ls); + + sb.append(" mv $SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain/SOILLISTALLSU.DAT " + + "$SCEN_DIR/$CROP_NAME/spinup/manage/tileDrain/SOILLIST.DAT" + ls); + + sb.append("end " + ls); + sb.append(ls); + return sb.toString(); + } + + public void projectLoaded() { + fields = (ManageSpinupFields) app.getProject().getPage(fields.getName()); + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + if (fields != null) { + String scenloc = domain.getScenarioDir(); + if (scenloc != null && scenloc.trim().length() > 0) + this.scenarioDir.setText(scenloc); + else + this.scenarioDir.setText(fields.getScenarioDir()); + fertYearSel.setSelectedItem(fields.getFertYear()); + runMessages.setText(fields.getMessage()); + } else { + newProjectCreated(); + } + } + + public void saveProjectRequested() { + if (scenarioDir != null) + domain.setScenarioDir(scenarioDir.getText()); + if (scenarioDir != null) + fields.setScenarioDir(scenarioDir.getText()); + if (fertYearSel != null) + fields.setFertYear((String) fertYearSel.getSelectedItem()); + if (runMessages != null) + fields.setMessage(runMessages.getText()); + } + + @Override + public void newProjectCreated() { + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + + scenarioDir.setText(domain.getScenarioDir()); + runMessages.setText(""); + if (fields == null) { + fields = new ManageSpinupFields(); + app.getProject().addPage(fields); + } + } +} diff --git a/festc_core/src/gov/epa/festc/gui/CropSelectionPanel.java b/festc_core/src/gov/epa/festc/gui/CropSelectionPanel.java index 533c72b..453056e 100644 --- a/festc_core/src/gov/epa/festc/gui/CropSelectionPanel.java +++ b/festc_core/src/gov/epa/festc/gui/CropSelectionPanel.java @@ -1,159 +1,159 @@ -package gov.epa.festc.gui; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.util.Constants; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; - -public class CropSelectionPanel extends JPanel { - - private ListWidget lstCrops; - private ListWidget selectedCrops; - private FestcApplication app; - - private JButton selectCropsButton; - private JButton unselectCropsButton; - - public CropSelectionPanel(FestcApplication application) { - app = application; - add(createPanel()); - } - - private JPanel createPanel() { - JPanel main = new JPanel(); - main.setLayout(new BoxLayout(main, BoxLayout.X_AXIS)); - main.add(Box.createRigidArea(new Dimension(8,0))); - main.add(getWestPanel()); - main.add(Box.createRigidArea(new Dimension(8,0))); - main.add(getButtonPanel()); - main.add(Box.createRigidArea(new Dimension(8,0))); - main.add(getEastPanel()); - main.add(Box.createRigidArea(new Dimension(8,0))); - main.repaint(); - return main; - } - - private JPanel getWestPanel() { -// JPanel leftPanel = new JPanel(); - JPanel cropsPanel = new JPanel(new BorderLayout()); - cropsPanel.add(new JLabel("Crops/Grasses"), BorderLayout.NORTH); - lstCrops = new ListWidget(Constants.CROPS.keySet().toArray()); - //lstCrops.setVisibleRowCount(12); - - cropsPanel.add(Box.createRigidArea(new Dimension(0,10)), BorderLayout.CENTER); - JScrollPane scrollCropList = new JScrollPane(lstCrops, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - scrollCropList.setPreferredSize(new Dimension(120, 200)); - - cropsPanel.add(scrollCropList, BorderLayout.SOUTH); -// leftPanel.add(cropsPanel); -// leftPanel.add(getButtonPanel()); - return cropsPanel; - } - - private JPanel getButtonPanel(){ - JPanel buttonPanel = new JPanel(); - buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); - - JPanel includeButtonPanel = new JPanel(); - includeButtonPanel.setLayout(new BorderLayout(0, 0)); -// includeButtonPanel.setPreferredSize(new Dimension(50, 45)); -// includeButtonPanel.setMinimumSize(new Dimension(50, 45)); - JPanel excludeButtonPanel = new JPanel(); - excludeButtonPanel.setLayout(new BorderLayout(0, 0)); -// excludeButtonPanel.setPreferredSize(new Dimension(50, 45)); -// excludeButtonPanel.setMinimumSize(new Dimension(50, 45)); - - selectCropsButton = new JButton(setCropsData()); - excludeButtonPanel.add(selectCropsButton, BorderLayout.SOUTH); - - unselectCropsButton = new JButton(unSetCropsData()); - includeButtonPanel.add(unselectCropsButton, BorderLayout.NORTH); - buttonPanel.add(excludeButtonPanel); - buttonPanel.add(Box.createRigidArea(new Dimension(0,10))); - buttonPanel.add(includeButtonPanel); - - return buttonPanel; - } - - private JPanel getEastPanel(){ - JPanel seCropsPanel = new JPanel(new BorderLayout()); - seCropsPanel.add(new JLabel("Selected Crops"), BorderLayout.NORTH); - selectedCrops = new ListWidget(new String[]{}); - //selectedCrops.setVisibleRowCount(12); - seCropsPanel.add(Box.createRigidArea(new Dimension(0,10)), BorderLayout.CENTER); - JScrollPane seScrollCropList = new JScrollPane(selectedCrops, - JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - seScrollCropList.setPreferredSize(new Dimension(120, 200)); - seCropsPanel.add(seScrollCropList, BorderLayout.SOUTH); - return seCropsPanel; - - } - - public String selectedItemTostring(){ - int size = selectedCrops.getAllElements().length; - String[] seCrops = selectedCrops.getAllElements(); - String crops = "\""; - for ( int i =0; i") { - public void actionPerformed(ActionEvent e) { - - int[] indices = lstCrops.getSelectedIndices(); - Object[] cropNames = lstCrops.getSelectedValues(); - if ( cropNames == null || cropNames.length==0) { - // TODO report error - app.showMessage("Select crop(s)", "Please select some crops first!"); - return; - } - else { - for ( int i= 0; i < indices.length; i++) - selectedCrops.addElement(cropNames[i]); - lstCrops.removeElements(cropNames); - } - } - }; - } - - private Action unSetCropsData() { - return new AbstractAction("<= Unselect") { - - public void actionPerformed(ActionEvent e) { - Object[] cropNames = selectedCrops.getSelectedValues(); - if ( cropNames == null || cropNames.length==0) { - - app.showMessage("Select crop(s)", "Please select some crops first!"); - return; - } - else { - selectedCrops.removeElements(cropNames); - String[] allSelected = selectedCrops.getAllElements(); - lstCrops.setElements(Constants.CROPS.keySet().toArray()); - lstCrops.removeElements(allSelected); - lstCrops.revalidate(); - } - } - }; - } - -} +package gov.epa.festc.gui; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.util.Constants; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +public class CropSelectionPanel extends JPanel { + + private ListWidget lstCrops; + private ListWidget selectedCrops; + private FestcApplication app; + + private JButton selectCropsButton; + private JButton unselectCropsButton; + + public CropSelectionPanel(FestcApplication application) { + app = application; + add(createPanel()); + } + + private JPanel createPanel() { + JPanel main = new JPanel(); + main.setLayout(new BoxLayout(main, BoxLayout.X_AXIS)); + main.add(Box.createRigidArea(new Dimension(8,0))); + main.add(getWestPanel()); + main.add(Box.createRigidArea(new Dimension(8,0))); + main.add(getButtonPanel()); + main.add(Box.createRigidArea(new Dimension(8,0))); + main.add(getEastPanel()); + main.add(Box.createRigidArea(new Dimension(8,0))); + main.repaint(); + return main; + } + + private JPanel getWestPanel() { +// JPanel leftPanel = new JPanel(); + JPanel cropsPanel = new JPanel(new BorderLayout()); + cropsPanel.add(new JLabel("Crops/Grasses"), BorderLayout.NORTH); + lstCrops = new ListWidget(Constants.CROPS.keySet().toArray()); + //lstCrops.setVisibleRowCount(12); + + cropsPanel.add(Box.createRigidArea(new Dimension(0,10)), BorderLayout.CENTER); + JScrollPane scrollCropList = new JScrollPane(lstCrops, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollCropList.setPreferredSize(new Dimension(120, 200)); + + cropsPanel.add(scrollCropList, BorderLayout.SOUTH); +// leftPanel.add(cropsPanel); +// leftPanel.add(getButtonPanel()); + return cropsPanel; + } + + private JPanel getButtonPanel(){ + JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); + + JPanel includeButtonPanel = new JPanel(); + includeButtonPanel.setLayout(new BorderLayout(0, 0)); +// includeButtonPanel.setPreferredSize(new Dimension(50, 45)); +// includeButtonPanel.setMinimumSize(new Dimension(50, 45)); + JPanel excludeButtonPanel = new JPanel(); + excludeButtonPanel.setLayout(new BorderLayout(0, 0)); +// excludeButtonPanel.setPreferredSize(new Dimension(50, 45)); +// excludeButtonPanel.setMinimumSize(new Dimension(50, 45)); + + selectCropsButton = new JButton(setCropsData()); + excludeButtonPanel.add(selectCropsButton, BorderLayout.SOUTH); + + unselectCropsButton = new JButton(unSetCropsData()); + includeButtonPanel.add(unselectCropsButton, BorderLayout.NORTH); + buttonPanel.add(excludeButtonPanel); + buttonPanel.add(Box.createRigidArea(new Dimension(0,10))); + buttonPanel.add(includeButtonPanel); + + return buttonPanel; + } + + private JPanel getEastPanel(){ + JPanel seCropsPanel = new JPanel(new BorderLayout()); + seCropsPanel.add(new JLabel("Selected Crops"), BorderLayout.NORTH); + selectedCrops = new ListWidget(new String[]{}); + //selectedCrops.setVisibleRowCount(12); + seCropsPanel.add(Box.createRigidArea(new Dimension(0,10)), BorderLayout.CENTER); + JScrollPane seScrollCropList = new JScrollPane(selectedCrops, + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + seScrollCropList.setPreferredSize(new Dimension(120, 200)); + seCropsPanel.add(seScrollCropList, BorderLayout.SOUTH); + return seCropsPanel; + + } + + public String selectedItemTostring(){ + int size = selectedCrops.getAllElements().length; + String[] seCrops = selectedCrops.getAllElements(); + String crops = "\""; + for ( int i =0; i") { + public void actionPerformed(ActionEvent e) { + + int[] indices = lstCrops.getSelectedIndices(); + Object[] cropNames = lstCrops.getSelectedValues(); + if ( cropNames == null || cropNames.length==0) { + // TODO report error + app.showMessage("Select crop(s)", "Please select some crops first!"); + return; + } + else { + for ( int i= 0; i < indices.length; i++) + selectedCrops.addElement(cropNames[i]); + lstCrops.removeElements(cropNames); + } + } + }; + } + + private Action unSetCropsData() { + return new AbstractAction("<= Unselect") { + + public void actionPerformed(ActionEvent e) { + Object[] cropNames = selectedCrops.getSelectedValues(); + if ( cropNames == null || cropNames.length==0) { + + app.showMessage("Select crop(s)", "Please select some crops first!"); + return; + } + else { + selectedCrops.removeElements(cropNames); + String[] allSelected = selectedCrops.getAllElements(); + lstCrops.setElements(Constants.CROPS.keySet().toArray()); + lstCrops.removeElements(allSelected); + lstCrops.revalidate(); + } + } + }; + } + +} diff --git a/festc_core/src/gov/epa/festc/gui/Epic2CMAQPanel.java b/festc_core/src/gov/epa/festc/gui/Epic2CMAQPanel.java index 2a40cbe..6a8c468 100644 --- a/festc_core/src/gov/epa/festc/gui/Epic2CMAQPanel.java +++ b/festc_core/src/gov/epa/festc/gui/Epic2CMAQPanel.java @@ -1,447 +1,555 @@ -package gov.epa.festc.gui; - -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.text.NumberFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JFormattedTextField; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JTextField; -import javax.swing.SpringLayout; -import javax.swing.SwingConstants; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.core.proj.DomainFields; -import gov.epa.festc.core.proj.Epic2CMAQFields; -import gov.epa.festc.util.Constants; -import gov.epa.festc.util.FileRunner; -import gov.epa.festc.util.SpringLayoutGenerator; -import simphony.util.messages.MessageCenter; - -public class Epic2CMAQPanel extends UtilFieldsPanel implements PlotEventListener { - private static final long serialVersionUID = 4247819754945274135L; - // - // private JTextField dataDir; - // private JButton dataDirBrowser; - // private JTextField outDir; - // private JButton outDirBrowser; - private JTextField filesPrefix; - private MessageCenter msg; - private JFormattedTextField startDate; - private JFormattedTextField endDate; - private JRadioButton applicationBtn, spinupBtn; - private boolean spinup = false; - - private FestcApplication app; - private Epic2CMAQFields fields; - - public Epic2CMAQPanel(FestcApplication festcApp) { - app = festcApp; - msg = app.getMessageCenter(); - fields = new Epic2CMAQFields(); - app.getProject().addPage(fields); - app.addPlotListener(this); - add(createPanel()); - } - - private JPanel createPanel() { - init(); - JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - mainPanel.add(getNorthPanel()); - mainPanel.add(getCenterPanel()); - mainPanel.add(getSouthPanel()); - mainPanel.add(messageBox()); - return mainPanel; - } - - private JPanel getNorthPanel() { - JPanel panel = new JPanel(); - JLabel title = new JLabel(Constants.EPIC2CMAQ, SwingConstants.CENTER); - title.setFont(new Font("Default", Font.BOLD, 20)); - - panel.add(title); - panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); - - return panel; - } - - private JPanel getSouthPanel() { - JPanel panel = new JPanel(); - JButton display = new JButton(runAction()); - panel.add(display); - - panel.setBorder(BorderFactory.createEmptyBorder(30, 0, 10, 0)); - - return panel; - } - - private JPanel getCenterPanel() { - JPanel panel = new JPanel(new SpringLayout()); - SpringLayoutGenerator layout = new SpringLayoutGenerator(); - - JPanel filesPrefixPanel = new JPanel(); - filesPrefix = new JTextField(40); - filesPrefixPanel.add(filesPrefix); - - JPanel startDatePanel = new JPanel(); - NumberFormat snf = NumberFormat.getNumberInstance(); - snf.setGroupingUsed(false); - startDate = new JFormattedTextField(snf); - startDate.setColumns(40); - startDatePanel.add(startDate); - - JPanel endDatePanel = new JPanel(); - NumberFormat enf = NumberFormat.getNumberInstance(); - enf.setGroupingUsed(false); - endDate = new JFormattedTextField(enf); - endDate.setColumns(40); - endDatePanel.add(endDate); - - JPanel butPanel = new JPanel(); - this.applicationBtn = new JRadioButton(applicationSelection()); - this.spinupBtn = new JRadioButton(spinupSelection()); - this.applicationBtn.setSelected(true); - this.spinupBtn.setSelected(false); - butPanel.add(this.spinupBtn); - butPanel.add(this.applicationBtn); - - ButtonGroup btnGroup = new ButtonGroup(); - btnGroup.add(this.spinupBtn); - btnGroup.add(this.applicationBtn); - - layout.addLabelWidgetPair("Grid Description:", getGridDescPanel(false), panel); - layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); - layout.addLabelWidgetPair("Start Date (YYYYMMDD):", startDatePanel, panel); - layout.addLabelWidgetPair("End Date (YYYYMMDD):", endDatePanel, panel); - layout.addLabelWidgetPair("Output File Prefix:", filesPrefixPanel, panel); - layout.addLabelWidgetPair("Output Type:", butPanel, panel); - - layout.makeCompactGrid(panel, 6, 2, // number of rows and cols - 10, 10, // initial X and Y - 5, 5); // x and y pading - - return panel; - } - - private Action applicationSelection() { - return new AbstractAction("EPIC APP") { - public void actionPerformed(ActionEvent e) { - processSelec(); - } - - }; - } - - private Action spinupSelection() { - return new AbstractAction("EPIC SPINUP") { - public void actionPerformed(ActionEvent e) { - processSelec(); - } - - }; - } - - private void processSelec() { - if (applicationBtn.isSelected()) { - spinup = false; - } else { - spinup = true; - } - } - - private Action runAction() { - return new AbstractAction("Run") { - private static final long serialVersionUID = 5806383737068197305L; - - public void actionPerformed(ActionEvent e) { - try { - validateFields(); - final String file = writeScript(); - - Thread populateThread = new Thread(new Runnable() { - public void run() { - runScript(file); - } - }); - populateThread.start(); - } catch (Exception exc) { - app.showMessage("Run script", exc.getMessage()); - } - } - }; - } - - private void validateFields() throws Exception { - - String sahome = Constants.getProperty(Constants.SA_HOME, msg); - if (sahome == null || sahome.trim().isEmpty() || !(new File(sahome).exists())) - throw new Exception("Error loading spacial allocator home:" + sahome + " doesn't exist"); - - String scenarioDir = this.scenarioDir.getText(); - if (scenarioDir == null || scenarioDir.isEmpty()) - throw new Exception("Please select scenario dir first!"); - - validateGrids(); - - if (filesPrefix.getText() == null || filesPrefix.getText().trim().isEmpty()) - throw new Exception("Please specify a valid output files prefix."); - - String start = startDate.getText(); - if (start == null || start.trim().isEmpty()) - throw new Exception("Start date field is empty."); - - if (start.trim().length() != 8) - throw new Exception("Star date format is not right."); - - if (start.trim().charAt(0) == '0') - throw new Exception("Start date value is invalid."); - - String end = endDate.getText(); - if (end == null || end.trim().isEmpty()) - throw new Exception("End date field is empty."); - - if (end.trim().length() != 8) - throw new Exception("End date format is not right."); - - if (end.trim().charAt(0) == '0') - throw new Exception("End date value is invalid."); - } - - protected String writeScript() throws Exception { - Date now = new Date(); // java.util.Date, NOT java.sql.Date or - // java.sql.Timestamp! - String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - String scenario = scenarioDir.getText().trim(); - String file = scenario.trim() + "/scripts"; - - String sahome = Constants.getProperty(Constants.SA_HOME, msg); - - outMessages += "SA home: " + sahome + ls; - - if (!file.endsWith(System.getProperty("file.separator"))) - file += System.getProperty("file.separator"); - - // file += "epic2CMAQ_" + timeStamp + ".csh"; - if (spinup) - file = file.trim() + "/epic2CMAQ_spinup_" + timeStamp + ".csh"; - else - file = file.trim() + "/epic2CMAQ_app_" + timeStamp + ".csh"; - - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append(getScirptHeader() + ls); - sb.append("#" + ls + "# Set up runtime environment" + ls + "#" + ls); - sb.append("source " + sahome.trim() + Constants.SA_SETUP_FILE + ls + ls); - sb.append("setenv SCEN_DIR " + scenario + ls); - sb.append("setenv SA_HOME " + sahome + ls); - sb.append("#" + ls + "# Define domain grids" + ls + "#" + ls); - sb.append("setenv GRID_PROJ \"" + proj4proj.getText().trim() + "\"" + ls + ls); - sb.append("setenv GRID_ROWS " + ((Number) rows.getValue()).intValue() + ls); - sb.append("setenv GRID_COLUMNS " + ((Number) cols.getValue()).intValue() + ls + ls); - sb.append("setenv GRID_XMIN " + ((Number) xmin.getValue()).doubleValue() + ls); - sb.append("setenv GRID_YMIN " + ((Number) ymin.getValue()).doubleValue() + ls + ls); - sb.append("setenv GRID_XCELLSIZE " + ((Number) xSize.getValue()).doubleValue() + ls); - sb.append("setenv GRID_YCELLSIZE " + ((Number) ySize.getValue()).doubleValue() + ls + ls); - sb.append("setenv GRID_NAME \"" + (gridName.getText() == null ? "" : gridName.getText().trim()) + "\"" + ls - + ls); - sb.append("#" + ls + "#set EPIC output file directory which containts each day data:" + ls + "#" + ls); - if (spinup) - sb.append("setenv DATA_DIR $SCEN_DIR/output4CMAQ/spinup/daily/" + ls + ls); - else - sb.append("setenv DATA_DIR $SCEN_DIR/output4CMAQ/app/daily/" + ls + ls); - - // sb.append("setenv DATA_DIR $SCEN_DIR/output4CMAQ/app/daily" + ls + - // ls); - sb.append("#" + ls + "#Set date and time range: YYYYMMDDHHMM" + ls + "#" + ls); - sb.append("setenv START_DATE " + startDate.getText() + ls); - sb.append("setenv END_DATE " + endDate.getText() + ls + ls); - // sb.append("#" + ls + "# Output files: three output files for soil, - // EPIC daily output, and fertilizer application data" + ls + "#" + ls); - // sb.append("setenv SOIL_OUTPUT_NETCDF_FILE \"" + - // outDir.getText().trim() + "/" + filesPrefix.getText().trim() + - // "_soil.nc\"" + ls); - // sb.append("setenv DAILY_OUTPUT_NETCDF_FILE \"" + - // outDir.getText().trim() + "/" + filesPrefix.getText().trim() + - // "_time\"" + ls + ls); - // sb.append("setenv FERTILIZER_OUTPUT_NETCDF_FILE \"" + - // outDir.getText().trim() + "/" + filesPrefix.getText().trim() + - // "_fert.nc\"" + ls + ls); - sb.append("#" + ls + "# Output file prefix for soil and EPIC daily output" + ls - + "# \"prefix\"_soil.nc for soil ouput and \"prefix\"_time\"yyyymm\".nc for daily EPIC output" + ls - + "#" + ls); - if (spinup) - sb.append("setenv OUTPUT_NETCDF_FILE_PREFIX $SCEN_DIR/output4CMAQ/spinup/toCMAQ/" - + filesPrefix.getText().trim() + ls); - else - sb.append("setenv OUTPUT_NETCDF_FILE_PREFIX $SCEN_DIR/output4CMAQ/app/toCMAQ/" - + filesPrefix.getText().trim() + ls); - sb.append("#" + ls + "# run the EPIC output processing program" + ls + "#" + ls); - sb.append("$SA_HOME/bin/64bits/extractEPIC2CMAQ.exe" + ls + ls); - sb.append("if ( $status == 0 ) then" + ls); - sb.append(" echo ==== Finished EPIC to CMAQ run. " + ls); - sb.append("else " + ls); - sb.append(" echo ==== Error in EPIC to CMAQ run. " + ls); - sb.append("endif " + ls); - sb.append("#===================================================================" + ls); - - String mesg = ""; - try { - File script = new File(file); - Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - mesg += "Created a script file: " + file + "\n"; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - } catch (IOException e) { - throw new Exception(e.getMessage()); - } - app.showMessage("Write script", mesg); - return file; - } - - private String getScirptHeader() { - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to process EPIC modeling output for CMAQ bi-directional ammonia surface" + ls); - sb.append("# flux modeling " + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); - sb.append("# in support of the CMAS project, 2010" + ls); - sb.append("#" + ls); - sb.append("# Written by: LR, July-Sept 2010" + ls); - sb.append("#" + ls); - sb.append("# Program: extractEPIC2CMAQ.exe" + ls); - sb.append("# Needed environment variables included in the script file to run." + ls); - sb.append("#" + ls); - sb.append("#***************************************************************************************" + ls + ls); - - return sb.toString(); - } - - private void runScript(final String file) { - String log = file + ".log"; - - outMessages += "Script file: " + file + ls; - outMessages += "Log file: " + log + ls; - runMessages.setText(outMessages); - runMessages.validate(); - FileRunner.runScript(file, log, msg); - } - - @Override - public void projectLoaded() { - fields = (Epic2CMAQFields) app.getProject().getPage(fields.getName()); - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - if (fields != null) { - String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length() > 0) - this.scenarioDir.setText(scenloc); - else - this.scenarioDir.setText(fields.getScenarioDir()); - rows.setValue(fields.getRows()); - cols.setValue(fields.getCols()); - xSize.setValue(fields.getXcellSize()); - ySize.setValue(fields.getYcellSize()); - xmin.setValue(fields.getXmin()); - ymin.setValue(fields.getYmin()); - proj4proj.setText(fields.getProj()); - gridName.setText(fields.getGridName()); - try { - startDate.setValue(NumberFormat.getNumberInstance() - .parse(fields.getStartdate() == null ? "" : fields.getStartdate())); - endDate.setValue( - NumberFormat.getNumberInstance().parse(fields.getEnddate() == null ? "" : fields.getEnddate())); - } catch (ParseException e) { - startDate.setValue(0); - endDate.setValue(0); - } - filesPrefix.setText(fields.getOutfileprefix()); - runMessages.setText(fields.getMessage()); - } else { - newProjectCreated(); - } - } - - @Override - public void saveProjectRequested() { - if (scenarioDir != null) - domain.setScenarioDir(scenarioDir.getText() == null ? "" : scenarioDir.getText()); - if (scenarioDir != null) - fields.setScenarioDir(scenarioDir.getText()); - if (rows != null) - fields.setRows(Integer.parseInt(rows.getText() == null ? "" : rows.getValue() + "")); - if (cols != null) - fields.setCols(Integer.parseInt(cols.getText() == null ? "" : cols.getValue() + "")); - if (xSize != null) - fields.setXcellSize(Float.parseFloat(xSize.getText() == null ? "" : xSize.getValue() + "")); - if (ySize != null) - fields.setYcellSize(Float.parseFloat(ySize.getText() == null ? "" : ySize.getValue() + "")); - if (xmin != null) - fields.setXmin(Float.parseFloat(xmin.getText() == null ? "" : xmin.getValue() + "")); - if (ymin != null) - fields.setYmin(Float.parseFloat(ymin.getText() == null ? "" : ymin.getValue() + "")); - if (proj4proj != null) - fields.setProj(proj4proj.getText() == null ? "" : proj4proj.getText()); - if (gridName != null) - fields.setGridName(gridName.getText() == null ? "" : gridName.getText()); - if (startDate != null) - fields.setStartdate(startDate.getValue() == null ? "" : startDate.getText()); - if (endDate != null) - fields.setEnddate(endDate.getValue() == null ? "" : endDate.getText()); - if (filesPrefix != null) - fields.setOutfileprefix(filesPrefix.getText() == null ? "" : filesPrefix.getText()); - if (runMessages != null) - fields.setMessage(runMessages.getText()); - } - - @Override - public void newProjectCreated() { - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - scenarioDir.setText(domain.getScenarioDir()); - rows.setValue(domain.getRows()); - cols.setValue(domain.getCols()); - xmin.setValue(domain.getXmin()); - ymin.setValue(domain.getYmin()); - xSize.setValue(domain.getXcellSize()); - ySize.setValue(domain.getYcellSize()); - proj4proj.setText(domain.getProj()); - gridName.setText(domain.getGridName()); - runMessages.setText(""); - fields.setOutfileprefix(""); - try { - startDate.setValue(NumberFormat.getNumberInstance().parse(domain.getSimYear().trim() + "0101")); - endDate.setValue(NumberFormat.getNumberInstance().parse(domain.getSimYear().trim() + "1231")); - } catch (ParseException e) { - startDate.setValue(0); - endDate.setValue(0); - } - - if (fields == null) { - fields = new Epic2CMAQFields(); - app.getProject().addPage(fields); - } - } - -} +package gov.epa.festc.gui; + +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.NumberFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JFormattedTextField; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.SpringLayout; +import javax.swing.SwingConstants; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.core.proj.DomainFields; +import gov.epa.festc.core.proj.Epic2CMAQFields; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.FileRunner; +import gov.epa.festc.util.SpringLayoutGenerator; +import simphony.util.messages.MessageCenter; + +public class Epic2CMAQPanel extends UtilFieldsPanel implements PlotEventListener { + private static final long serialVersionUID = 4247819754945274135L; + // + // private JTextField dataDir; + // private JButton dataDirBrowser; + // private JTextField outDir; + // private JButton outDirBrowser; + private JTextField filesPrefix; + private MessageCenter msg; + private JFormattedTextField startDate; + private JFormattedTextField endDate; + private JRadioButton applicationBtn, spinupBtn; + private boolean spinup = false; + + private FestcApplication app; + private Epic2CMAQFields fields; + + public Epic2CMAQPanel(FestcApplication festcApp) { + app = festcApp; + msg = app.getMessageCenter(); + fields = new Epic2CMAQFields(); + app.getProject().addPage(fields); + app.addPlotListener(this); + add(createPanel()); + } + + private JPanel createPanel() { + init(); + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + mainPanel.add(getNorthPanel()); + mainPanel.add(getCenterPanel()); + mainPanel.add(getSouthPanel()); + mainPanel.add(messageBox()); + return mainPanel; + } + + private JPanel getNorthPanel() { + JPanel panel = new JPanel(); + JLabel title = new JLabel(Constants.EPIC2CMAQ, SwingConstants.CENTER); + title.setFont(new Font("Default", Font.BOLD, 20)); + + panel.add(title); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); + + return panel; + } + + private JPanel getSouthPanel() { + JPanel panel = new JPanel(); + JButton display = new JButton(runAction()); + panel.add(display); + + panel.setBorder(BorderFactory.createEmptyBorder(30, 0, 10, 0)); + + return panel; + } + + private JPanel getCenterPanel() { + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + + JPanel filesPrefixPanel = new JPanel(); + filesPrefix = new JTextField(40); + filesPrefixPanel.add(filesPrefix); + + JPanel startDatePanel = new JPanel(); + NumberFormat snf = NumberFormat.getNumberInstance(); + snf.setGroupingUsed(false); + startDate = new JFormattedTextField(snf); + startDate.setColumns(40); + startDatePanel.add(startDate); + + JPanel endDatePanel = new JPanel(); + NumberFormat enf = NumberFormat.getNumberInstance(); + enf.setGroupingUsed(false); + endDate = new JFormattedTextField(enf); + endDate.setColumns(40); + endDatePanel.add(endDate); + + JPanel butPanel = new JPanel(); + this.applicationBtn = new JRadioButton(applicationSelection()); + this.spinupBtn = new JRadioButton(spinupSelection()); + this.applicationBtn.setSelected(true); + this.spinupBtn.setSelected(false); + butPanel.add(this.spinupBtn); + butPanel.add(this.applicationBtn); + + ButtonGroup btnGroup = new ButtonGroup(); + btnGroup.add(this.spinupBtn); + btnGroup.add(this.applicationBtn); + + layout.addLabelWidgetPair("Grid Description:", getGridDescPanel(false), panel); + layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); + layout.addLabelWidgetPair("Start Date (YYYYMMDD):", startDatePanel, panel); + layout.addLabelWidgetPair("End Date (YYYYMMDD):", endDatePanel, panel); + layout.addLabelWidgetPair("Output File Prefix:", filesPrefixPanel, panel); + layout.addLabelWidgetPair("Output Type:", butPanel, panel); + + layout.makeCompactGrid(panel, 6, 2, // number of rows and cols + 10, 10, // initial X and Y + 5, 5); // x and y pading + + return panel; + } + + private Action applicationSelection() { + return new AbstractAction("EPIC APP") { + public void actionPerformed(ActionEvent e) { + processSelec(); + } + + }; + } + + private Action spinupSelection() { + return new AbstractAction("EPIC SPINUP") { + public void actionPerformed(ActionEvent e) { + processSelec(); + } + + }; + } + + private void processSelec() { + if (applicationBtn.isSelected()) { + spinup = false; + } else { + spinup = true; + } + } + + private Action runAction() { + return new AbstractAction("Run") { + private static final long serialVersionUID = 5806383737068197305L; + + public void actionPerformed(ActionEvent e) { + try { + validateFields(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + final String jobFile = writeScript(); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir.getText()); + } else { + batchFile = null; + } + + Thread populateThread = new Thread(new Runnable() { + public void run() { + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile); + } + } + }); + populateThread.start(); + } catch (Exception exc) { + app.showMessage("Run script", exc.getMessage()); + } + } + }; + } + + private void validateFields() throws Exception { + + String sahome = Constants.getProperty(Constants.SA_HOME, msg); +// if (sahome == null || sahome.trim().isEmpty() || !(new File(sahome).exists())) + if (sahome == null || sahome.trim().isEmpty()) + throw new Exception("Error loading spacial allocator home:" + sahome + " doesn't exist"); + + String scenarioDir = this.scenarioDir.getText(); + if (scenarioDir == null || scenarioDir.isEmpty()) + throw new Exception("Please select scenario dir first!"); + + validateGrids(); + + if (filesPrefix.getText() == null || filesPrefix.getText().trim().isEmpty()) + throw new Exception("Please specify a valid output files prefix."); + + String start = startDate.getText(); + if (start == null || start.trim().isEmpty()) + throw new Exception("Start date field is empty."); + + if (start.trim().length() != 8) + throw new Exception("Star date format is not right."); + + if (start.trim().charAt(0) == '0') + throw new Exception("Start date value is invalid."); + + String end = endDate.getText(); + if (end == null || end.trim().isEmpty()) + throw new Exception("End date field is empty."); + + if (end.trim().length() != 8) + throw new Exception("End date format is not right."); + + if (end.trim().charAt(0) == '0') + throw new Exception("End date value is invalid."); + } + + protected String writeScript() throws Exception { + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String scenario = scenarioDir.getText().trim(); + String file = scenario.trim() + "/scripts"; + + String sahome = Constants.getProperty(Constants.SA_HOME, msg); + + outMessages += "SA home: " + sahome + ls; + + if (!file.endsWith(System.getProperty("file.separator"))) + file += System.getProperty("file.separator"); + + // file += "epic2CMAQ_" + timeStamp + ".csh"; + if (spinup) + file = file.trim() + "/epic2CMAQ_spinup_" + timeStamp + ".csh"; + else + file = file.trim() + "/epic2CMAQ_app_" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append(getScirptHeader() + ls); + sb.append("#" + ls + "# Set up runtime environment" + ls + "#" + ls); + +// String rModules = Constants.getProperty(Constants.QUEUE_R_MODULE, msg); +// sb.append("module load " + rModules + ls); + + sb.append("source " + sahome.trim() + Constants.SA_SETUP_FILE + ls + ls); + sb.append("setenv SCEN_DIR " + scenario + ls); + sb.append("setenv SA_HOME " + sahome + ls); + sb.append("#" + ls + "# Define domain grids" + ls + "#" + ls); + sb.append("setenv GRID_PROJ \"" + proj4proj.getText().trim() + "\"" + ls + ls); + sb.append("setenv GRID_ROWS " + ((Number) rows.getValue()).intValue() + ls); + sb.append("setenv GRID_COLUMNS " + ((Number) cols.getValue()).intValue() + ls + ls); + sb.append("setenv GRID_XMIN " + ((Number) xmin.getValue()).doubleValue() + ls); + sb.append("setenv GRID_YMIN " + ((Number) ymin.getValue()).doubleValue() + ls + ls); + sb.append("setenv GRID_XCELLSIZE " + ((Number) xSize.getValue()).doubleValue() + ls); + sb.append("setenv GRID_YCELLSIZE " + ((Number) ySize.getValue()).doubleValue() + ls + ls); + sb.append("setenv GRID_NAME \"" + (gridName.getText() == null ? "" : gridName.getText().trim()) + "\"" + ls + + ls); + + if (!spinup) { + sb.append("#Process multiple years" + ls); + sb.append("set SIM_YEAR=\"$SCEN_DIR/output4CMAQ/app/[1-2][0-9][0-9][0-9]\"" + ls); + } + + + if (spinup) { + sb.append("#" + ls + "#set EPIC output file directory which contains each day data:" + ls + "#" + ls); + sb.append("setenv DATA_DIR $SCEN_DIR/output4CMAQ/spinup/daily/" + ls + ls); + sb.append("#" + ls + "#Set date and time range: YYYYMMDDHHMM" + ls + "#" + ls); + sb.append("setenv START_DATE " + startDate.getText() + ls); + sb.append("setenv END_DATE " + endDate.getText() + ls + ls); + sb.append("#" + ls + "# Output file prefix for soil and EPIC daily output" + ls + + "# \"prefix\"_soil.nc for soil ouput and \"prefix\"_time\"yyyymm\".nc for daily EPIC output" + ls + + "#" + ls); + sb.append("setenv OUTPUT_NETCDF_FILE_PREFIX $SCEN_DIR/output4CMAQ/spinup/toCMAQ/" + + filesPrefix.getText().trim() + ls); + sb.append("#" + ls + "# run the EPIC output processing program" + ls + "#" + ls); + sb.append("$SA_HOME/bin/64bits/extractEPIC2CMAQ.exe" + ls + ls); + } else { + sb.append("foreach MULTI_YEAR_DIR ($SIM_YEAR)" + ls); + sb.append(" set MULTI_YEAR=`basename $MULTI_YEAR_DIR`" + ls); + sb.append(" #" + ls + " #set EPIC output file directory which contains each day data:" + ls + " #" + ls); + sb.append(" setenv DATA_DIR $SCEN_DIR/output4CMAQ/app/${MULTI_YEAR}/daily/" + ls + ls); + sb.append(" #" + ls + " #Set date and time range: YYYYMMDDHHMM" + ls + " #" + ls); +// sb.append(" setenv START_DATE ${MULTI_YEAR}" + startDate.getText() + ls); +// sb.append(" setenv END_DATE ${MULTI_YEAR}" + endDate.getText() + ls + ls); + sb.append(" setenv START_DATE ${MULTI_YEAR}\"0101\"" + ls); + sb.append(" setenv END_DATE ${MULTI_YEAR}\"1231\"" + ls); + sb.append(" #" + ls + " # Output file prefix for soil and EPIC daily output" + ls + + " # \"prefix\"_soil.nc for soil ouput and \"prefix\"_time\"yyyymm\".nc for daily EPIC output" + ls + + " #" + ls); + sb.append(" setenv OUTPUT_NETCDF_FILE_PREFIX $SCEN_DIR/output4CMAQ/app/${MULTI_YEAR}/toCMAQ/" + + filesPrefix.getText().trim() + ls); + sb.append(" #" + ls + " # run the EPIC output processing program" + ls + " #" + ls); + sb.append(" $SA_HOME/bin/64bits/extractEPIC2CMAQ.exe" + ls + "end" + ls + ls); + } + + sb.append("if ( $status == 0 ) then" + ls); + sb.append(" echo ==== Finished EPIC to CMAQ run. " + ls); + sb.append("else " + ls); + sb.append(" echo ==== Error in EPIC to CMAQ run. " + ls); + sb.append("endif " + ls); + sb.append("#===================================================================" + ls); + + String mesg = ""; + try { + File script = new File(file); + Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + mesg += "Created a script file: " + file + "\n"; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + } catch (IOException e) { + throw new Exception(e.getMessage()); + } + app.showMessage("Write script", mesg); + return file; + } + + // This is legacy code that has been moved to it's own method + protected void writeScriptFile(String file, String content) { + + String mesg = ""; + + try { + File script = new File(file); + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(content); + out.close(); + + mesg += "Script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + + } catch (IOException e) { + // printStackTrace(); + // g.error("Error generating EPIC script file", e); + app.showMessage("Write script", e.getMessage()); + } + + app.showMessage("Write script", mesg); + } + + protected String writeBatchFile(String jobFile, String scenarioDir) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String batchFile = scenarioDir.trim() + "/scripts"; + if (!batchFile.endsWith(System.getProperty("file.separator"))) + batchFile += System.getProperty("file.separator"); + batchFile += "submitEpic2CMAQ_" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh" + ls + ls); + + // TODO - add #SBATCH options here + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage == null || qSingModule.trim().isEmpty()) { + throw new Exception("Singularity image path must be specified"); + } + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + jobFile); + } else { + sb.append(jobFile); + } + + writeScriptFile(batchFile, sb.toString()); + + return batchFile; + } + + private String getScirptHeader() { + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append("#!/bin/csh -f" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: to process EPIC modeling output for CMAQ bi-directional ammonia surface" + ls); + sb.append("# flux modeling " + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); + sb.append("# in support of the CMAS project, 2010" + ls); + sb.append("#" + ls); + sb.append("# Written by: LR, July-Sept 2010" + ls); + sb.append("#" + ls); + sb.append("# Program: extractEPIC2CMAQ.exe" + ls); + sb.append("# Needed environment variables included in the script file to run." + ls); + sb.append("#" + ls); + sb.append("#***************************************************************************************" + ls + ls); + + return sb.toString(); + } + + private void runScript(final String file) { + String log = file + ".log"; + + outMessages += "Script file: " + file + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + FileRunner.runScript(file, log, msg); + } + + private void runBatchScript(final String batchFile, final String jobFile) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qEpic2Cmaq = Constants.getProperty(Constants.QUEUE_EPIC2CMAQ, msg); + + File script = new File(batchFile.replaceAll("\\\\", "\\\\\\\\")); + + sb.append(qcmd + " " + qEpic2Cmaq + " -o " + log + " " + script.getAbsolutePath()); + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } + + @Override + public void projectLoaded() { + fields = (Epic2CMAQFields) app.getProject().getPage(fields.getName()); + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + if (fields != null) { + String scenloc = domain.getScenarioDir(); + if (scenloc != null && scenloc.trim().length() > 0) + this.scenarioDir.setText(scenloc); + else + this.scenarioDir.setText(fields.getScenarioDir()); + rows.setValue(fields.getRows()); + cols.setValue(fields.getCols()); + xSize.setValue(fields.getXcellSize()); + ySize.setValue(fields.getYcellSize()); + xmin.setValue(fields.getXmin()); + ymin.setValue(fields.getYmin()); + proj4proj.setText(fields.getProj()); + gridName.setText(fields.getGridName()); + try { + startDate.setValue(NumberFormat.getNumberInstance() + .parse(fields.getStartdate() == null ? "" : fields.getStartdate())); + endDate.setValue( + NumberFormat.getNumberInstance().parse(fields.getEnddate() == null ? "" : fields.getEnddate())); + } catch (ParseException e) { + startDate.setValue(0); + endDate.setValue(0); + } + filesPrefix.setText(fields.getOutfileprefix()); + runMessages.setText(fields.getMessage()); + } else { + newProjectCreated(); + } + } + + @Override + public void saveProjectRequested() { + if (scenarioDir != null) + domain.setScenarioDir(scenarioDir.getText() == null ? "" : scenarioDir.getText()); + if (scenarioDir != null) + fields.setScenarioDir(scenarioDir.getText()); + if (rows != null) + fields.setRows(Integer.parseInt(rows.getText() == null ? "" : rows.getValue() + "")); + if (cols != null) + fields.setCols(Integer.parseInt(cols.getText() == null ? "" : cols.getValue() + "")); + if (xSize != null) + fields.setXcellSize(Float.parseFloat(xSize.getText() == null ? "" : xSize.getValue() + "")); + if (ySize != null) + fields.setYcellSize(Float.parseFloat(ySize.getText() == null ? "" : ySize.getValue() + "")); + if (xmin != null) + fields.setXmin(Float.parseFloat(xmin.getText() == null ? "" : xmin.getValue() + "")); + if (ymin != null) + fields.setYmin(Float.parseFloat(ymin.getText() == null ? "" : ymin.getValue() + "")); + if (proj4proj != null) + fields.setProj(proj4proj.getText() == null ? "" : proj4proj.getText()); + if (gridName != null) + fields.setGridName(gridName.getText() == null ? "" : gridName.getText()); + if (startDate != null) + fields.setStartdate(startDate.getValue() == null ? "" : startDate.getText()); + if (endDate != null) + fields.setEnddate(endDate.getValue() == null ? "" : endDate.getText()); + if (filesPrefix != null) + fields.setOutfileprefix(filesPrefix.getText() == null ? "" : filesPrefix.getText()); + if (runMessages != null) + fields.setMessage(runMessages.getText()); + } + + @Override + public void newProjectCreated() { + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + scenarioDir.setText(domain.getScenarioDir()); + rows.setValue(domain.getRows()); + cols.setValue(domain.getCols()); + xmin.setValue(domain.getXmin()); + ymin.setValue(domain.getYmin()); + xSize.setValue(domain.getXcellSize()); + ySize.setValue(domain.getYcellSize()); + proj4proj.setText(domain.getProj()); + gridName.setText(domain.getGridName()); + runMessages.setText(""); + fields.setOutfileprefix(""); + try { + startDate.setValue(NumberFormat.getNumberInstance().parse(domain.getSimYear().trim() + "0101")); + endDate.setValue(NumberFormat.getNumberInstance().parse(domain.getSimYear().trim() + "1231")); + } catch (ParseException e) { + startDate.setValue(0); + endDate.setValue(0); + } + + if (fields == null) { + fields = new Epic2CMAQFields(); + app.getProject().addPage(fields); + } + } + +} diff --git a/festc_core/src/gov/epa/festc/gui/Epic2SWATPanel.java b/festc_core/src/gov/epa/festc/gui/Epic2SWATPanel.java index 32ce08c..5808793 100644 --- a/festc_core/src/gov/epa/festc/gui/Epic2SWATPanel.java +++ b/festc_core/src/gov/epa/festc/gui/Epic2SWATPanel.java @@ -1,774 +1,943 @@ -package gov.epa.festc.gui; - -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.text.NumberFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFormattedTextField; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SpringLayout; -import javax.swing.SwingConstants; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.core.proj.DomainFields; -import gov.epa.festc.core.proj.Epic2SWATFields; -import gov.epa.festc.util.BrowseAction; -import gov.epa.festc.util.Constants; -import gov.epa.festc.util.FileRunner; -import gov.epa.festc.util.SpringLayoutGenerator; -import simphony.util.messages.MessageCenter; - -public class Epic2SWATPanel extends UtilFieldsPanel implements PlotEventListener { - private static final long serialVersionUID = 4247819754945274135L; - private JTextField beld4Dir; - private JButton beld4FileBrowser; - private JButton ratioFileBrowser; - private JButton weathFileBrowser; - - // private JTextField filesPrefix; - private MessageCenter msg; - private JTextField metdepFile; - private JTextField depFile; - private JTextField ratioFile; - private JComboBox nDepSel; - private JComboBox hucSel; - private JFormattedTextField simYear; - - private FestcApplication app; - private Epic2SWATFields fields; - - public Epic2SWATPanel(FestcApplication application) { - app = application; - msg = app.getMessageCenter(); - fields = new Epic2SWATFields(); - app.getProject().addPage(fields); - app.addPlotListener(this); - add(createPanel()); - } - - private JPanel createPanel() { - init(); - JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - mainPanel.add(getNorthPanel()); - mainPanel.add(getCenterPanel()); - mainPanel.add(getSouthPanel()); - mainPanel.add(messageBox()); - return mainPanel; - } - - private JPanel getNorthPanel() { - JPanel panel = new JPanel(); - JLabel title = new JLabel(Constants.EPIC2SWAT, SwingConstants.CENTER); - title.setFont(new Font("Default", Font.BOLD, 20)); - - panel.add(title); - panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); - - return panel; - } - - private JPanel getSouthPanel() { - JPanel panel = new JPanel(); - JButton runDaily = new JButton(runDailyAction()); - panel.add(runDaily); - JButton runNDep = new JButton(runNDepAction()); - panel.add(runNDep); - JButton runWeather = new JButton(runWeatAction()); - panel.add(runWeather); - JButton runSWATin = new JButton(runSWATAction()); - panel.add(runSWATin); - - panel.setBorder(BorderFactory.createEmptyBorder(30, 0, 10, 0)); - - return panel; - } - - private JPanel getCenterPanel() { - JPanel panel = new JPanel(new SpringLayout()); - SpringLayoutGenerator layout = new SpringLayoutGenerator(); - - JPanel beld4DirPanel = new JPanel(); - beld4Dir = new JTextField(40); - beld4Dir.setToolTipText("I.E. share_data/beld4_cmaq12km_2001.nc"); - beld4FileBrowser = new JButton(BrowseAction.browseAction(this, app.getCurrentDir(), "BELD4 file", beld4Dir)); - beld4DirPanel.add(beld4Dir); - beld4DirPanel.add(beld4FileBrowser); - - JPanel weatherPanel = new JPanel(); - metdepFile = new JTextField(40); - metdepFile.setToolTipText("Select Site_weather_dep* file"); - weathFileBrowser = new JButton(BrowseAction.browseAction(this, app.getCurrentDir(), "WETDEP file", metdepFile)); - weatherPanel.add(metdepFile); - weatherPanel.add(weathFileBrowser); - - JPanel ratioPanel = new JPanel(); - ratioFile = new JTextField(40); - ratioFile.setToolTipText("Huc8 Delivery Ratio file"); - ratioFileBrowser = new JButton( - BrowseAction.browseAction(this, app.getCurrentDir(), "HUC8 Ratio file", ratioFile)); - ratioPanel.add(ratioFile); - ratioPanel.add(ratioFileBrowser); - - nDepSel = new JComboBox(Constants.SWAT_NDEPS); - nDepSel.setSelectedIndex(1); - nDepSel.setToolTipText("Select CMAQ deposition. "); - hucSel = new JComboBox(Constants.AREAS); - hucSel.setSelectedIndex(1); - hucSel.setToolTipText("Select HUC. "); - - JPanel filesPrefixPanel = new JPanel(); - // filesPrefix = new JTextField(40); - // filesPrefixPanel.add(filesPrefix); - // - - // JPanel depField = new JPanel(); - // depFile = new JTextField(40); - // depField.add(depFile); - // - // JPanel ratioField = new JPanel(); - // ratioFile = new JTextField(40); - // ratioField.add(ratioFile); - - // JPanel startDatePanel = new JPanel(); - // NumberFormat snf = NumberFormat.getNumberInstance(); - // snf.setGroupingUsed(false); - // startDate = new JFormattedTextField(snf); - // startDate.setColumns(40); - // startDatePanel.add(startDate); - - JPanel simYearPanel = new JPanel(); - NumberFormat enf = NumberFormat.getNumberInstance(); - enf.setGroupingUsed(false); - simYear = new JFormattedTextField(enf); - simYear.setColumns(20); - simYearPanel.add(simYear); - simYear.setEditable(false); - - // layout.addLabelWidgetPair("Grid Description:", - // getGridDescPanel(false), panel); - layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); - layout.addLabelWidgetPair("BELD4 NetCDF File: ", beld4DirPanel, panel); - layout.addLabelWidgetPair("Met dep File:", weatherPanel, panel); - layout.addLabelWidgetPair("HUC8 Delivery Ratio File:", ratioPanel, panel); - layout.addLabelWidgetPair("Simulation Year:", simYearPanel, panel); - - layout.addLabelWidgetPair("Daily Average N Deposition: ", nDepSel, panel); - layout.addLabelWidgetPair("Area Selection: ", hucSel, panel); - // layout.addLabelWidgetPair("EPIC extraction Prefix:", - // filesPrefixPanel, panel); - - layout.makeCompactGrid(panel, 7, 2, // number of rows and cols - 10, 10, // initial X and Y - 5, 5); // x and y pading - - return panel; - } - - private Action runDailyAction() { - return new AbstractAction("EPIC") { - private static final long serialVersionUID = 5806383737068197305L; - - public void actionPerformed(ActionEvent e) { - try { - validateFields(); - final String file = writeEpicScript(); - ; - - Thread populateThread = new Thread(new Runnable() { - public void run() { - runScript(file); - } - }); - populateThread.start(); - } catch (Exception exc) { - app.showMessage("Run script", exc.getMessage()); - } - } - }; - } - - private Action runNDepAction() { - return new AbstractAction("NDEP") { - private static final long serialVersionUID = 5806383737068197305L; - - public void actionPerformed(ActionEvent e) { - try { - validateFields(); - final String file = writeNDepScript(); - - Thread populateThread = new Thread(new Runnable() { - public void run() { - runScript(file); - } - }); - populateThread.start(); - } catch (Exception exc) { - app.showMessage("Run script", exc.getMessage()); - } - } - }; - } - - private Action runWeatAction() { - return new AbstractAction("DailyWETH") { - private static final long serialVersionUID = 5806383737068197305L; - - public void actionPerformed(ActionEvent e) { - try { - validateFields(); - final String file = writeWeatScript(); - - Thread populateThread = new Thread(new Runnable() { - public void run() { - runScript(file); - } - }); - populateThread.start(); - } catch (Exception exc) { - app.showMessage("Run script", exc.getMessage()); - } - } - }; - } - - private Action runSWATAction() { - return new AbstractAction("SWAT INPUTS") { - private static final long serialVersionUID = 5806383737068197305L; - - public void actionPerformed(ActionEvent e) { - try { - validateFields(); - final String file = writeSWATScript(); - - Thread populateThread = new Thread(new Runnable() { - public void run() { - runScript(file); - } - }); - populateThread.start(); - } catch (Exception exc) { - app.showMessage("Run script", exc.getMessage()); - } - } - }; - } - - private void validateFields() throws Exception { - - String sahome = Constants.getProperty(Constants.SA_HOME, msg); - if (sahome == null || sahome.trim().isEmpty() || !(new File(sahome).exists())) - throw new Exception("Error loading spacial allocator home:" + sahome + " doesn't exist"); - - String scenarioDir = this.scenarioDir.getText(); - if (scenarioDir == null || scenarioDir.isEmpty()) - throw new Exception("Please select scenario dir first!"); - - String sYear = simYear.getText(); - if (sYear == null || sYear.trim().isEmpty()) - throw new Exception("Simulation Year field is empty."); - } - - private String writeEpicScript() throws Exception { - Date now = new Date(); // java.util.Date, NOT java.sql.Date or - // java.sql.Timestamp! - String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - - String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - String scenarioDir = this.scenarioDir.getText(); - File beld4F = new File(this.beld4Dir.getText()); - if (beld4F == null || beld4F.isDirectory() || !beld4F.exists()) - throw new Exception("Beld4 file is not existing!"); - - outMessages += "Epic base: " + baseDir + ls; - - String file = scenarioDir.trim() + "/scripts"; - - file = file.trim() + "/epic2swat_extract_dailyEpic_" + timeStamp + ".csh"; - // outMessages += file + ls; - - StringBuilder sb = new StringBuilder(); - sb.append(getEpicScriptHeader()); - String ls = "\n"; - - sb.append("#" + ls); - sb.append("# Set up runtime environment" + ls); - sb.append("#" + ls); - - sb.append("setenv EPIC_DIR " + baseDir + ls); - sb.append("setenv SCEN_DIR " + scenarioDir + ls); - sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls); - sb.append("setenv SIM_YEAR " + simYear.getText() + ls + ls); - - sb.append("# Get site infomation" + ls); - sb.append("setenv SITE_FILE ${SHARE_DIR}/EPICSites_Info.csv" + ls + ls); - sb.append("# Define BELD4 input file, get crop fractions " + ls); - sb.append("setenv DOMAIN_BELD4_NETCDF " + beld4Dir.getText() + ls + ls); - - sb.append("# EPIC input location" + ls); - sb.append("setenv DAY_DIR $SCEN_DIR/output4CMAQ/app/daily" + ls + ls); - sb.append("# SWAT output location" + ls); - sb.append("setenv OUTDIR $SCEN_DIR/output4SWAT/dailyEPIC" + ls); - sb.append("if ( ! -e $OUTDIR/county ) mkdir -p $OUTDIR/county" + ls); - sb.append("if ( ! -e $OUTDIR/state ) mkdir -p $OUTDIR/state" + ls); - sb.append("if ( ! -e $OUTDIR/domain ) mkdir -p $OUTDIR/domain" + ls); - sb.append("if ( ! -e $OUTDIR/HUC8 ) mkdir -p $OUTDIR/HUC8" + ls); - sb.append("if ( ! -e $OUTDIR/HUC6 ) mkdir -p $OUTDIR/HUC6" + ls); - sb.append("if ( ! -e $OUTDIR/HUC2 ) mkdir -p $OUTDIR/HUC2" + ls + ls); - - // sb.append("setenv OUTFILE_PREFIX $OUTDIR/" + filesPrefix.getText() + - // ls + ls); - sb.append("setenv REGION " + hucSel.getSelectedItem() + ls + ls); - - // sb.append("cd $EPIC_DIR/util/swat/" + ls ); - sb.append("echo 'Run EPIC daily summary for swat: ' " + scenarioDir + ls); - - sb.append("R CMD BATCH --no-save --slave " + "$EPIC_DIR/util/swat/epic2swat_extract_dailyEPIC.R " - + "${SCEN_DIR}/scripts/epic2swat_extract_dailyEPIC.log" + ls + ls); - - String mesg = ""; - try { - File script = new File(file); - Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - mesg += "Created a script file: " + file + "\n"; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - } catch (IOException e) { - throw new Exception(e.getMessage()); - } - app.showMessage("Write script", mesg); - return file; - } - - private String writeNDepScript() throws Exception { - Date now = new Date(); // java.util.Date, NOT java.sql.Date or - // java.sql.Timestamp! - String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - - String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - String scenarioDir = this.scenarioDir.getText(); - - String ndepSelection = (String) nDepSel.getSelectedItem(); - String ndepType = ndepSelection; - if (ndepSelection.contains("2002")) - ndepType = "dailyNDep_2004"; - else if (ndepSelection.contains("2010")) - ndepType = "dailyNDep_2008"; - - File beld4F = new File(this.beld4Dir.getText()); - if (beld4F == null || beld4F.isDirectory() || !beld4F.exists()) - throw new Exception("Beld4 file is not existing!"); - - outMessages += "Epic base: " + baseDir + ls; - - String file = scenarioDir.trim() + "/scripts"; - // String year = domain.getSimYear(); - - file = file.trim() + "/epic2swat_extract_NDEP_" + timeStamp + ".csh"; - // outMessages += file + ls; - - StringBuilder sb = new StringBuilder(); - sb.append(getNdepScriptHeader()); - String ls = "\n"; - - sb.append("#" + ls); - sb.append("# Set up runtime environment" + ls); - sb.append("#" + ls); - - sb.append("setenv EPIC_DIR " + baseDir + ls); - sb.append("setenv SCEN_DIR " + scenarioDir + ls); - sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls + ls); - sb.append("# Get site infomation" + ls); - sb.append("setenv SITE_FILE ${SHARE_DIR}/allSites_Info.csv" + ls + ls); - - sb.append("# Define BELD4 input file" + ls); - sb.append("setenv DOMAIN_BELD4_NETCDF " + beld4Dir.getText() + ls + ls); - sb.append("# Location of deposition files " + ls); - - sb.append("setenv NDEP_TYPE " + ndepType + ls); - sb.append("setenv NDEP_FILE " + metdepFile.getText() + ls); - - sb.append("# output location" + ls); - sb.append("setenv OUTDIR $SCEN_DIR/output4SWAT/NDEP/" + ndepType + ls); - sb.append("if ( ! -e $OUTDIR) mkdir -p $OUTDIR" + ls); - sb.append("if ( ! -e $OUTDIR/county ) mkdir -p $OUTDIR/county" + ls); - sb.append("if ( ! -e $OUTDIR/state ) mkdir -p $OUTDIR/state" + ls); - sb.append("if ( ! -e $OUTDIR/domain ) mkdir -p $OUTDIR/domain" + ls); - sb.append("if ( ! -e $OUTDIR/HUC8 ) mkdir -p $OUTDIR/HUC8" + ls); - sb.append("if ( ! -e $OUTDIR/HUC6 ) mkdir -p $OUTDIR/HUC6" + ls); - sb.append("if ( ! -e $OUTDIR/HUC2 ) mkdir -p $OUTDIR/HUC2" + ls + ls); - - // sb.append("setenv REGION " + hucSel.getSelectedItem() + ls); - // sb.append("cd $EPIC_DIR/util/swat/" + ls ); - sb.append("echo 'Extract daily depositon from yearly CMAQ or 2004/2008 averaged ndep: '" + scenarioDir + ls); - sb.append("R CMD BATCH --no-save --slave " + "$EPIC_DIR/util/swat/epic2swat_extract_daily_ndepCMAQ.R " - + "${SCEN_DIR}/scripts/epic2swat_extract_daily_ndepCMAQ.log" + ls + ls); - - String mesg = ""; - try { - File script = new File(file); - Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - mesg += "Created a script file: " + file + "\n"; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - } catch (IOException e) { - throw new Exception(e.getMessage()); - } - app.showMessage("Write script", mesg); - return file; - } - - private String writeSWATScript() throws Exception { - Date now = new Date(); // java.util.Date, NOT java.sql.Date or - // java.sql.Timestamp! - String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - - String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - String scenarioDir = this.scenarioDir.getText(); - - String ndepSelection = (String) nDepSel.getSelectedItem(); - String ndepType = ndepSelection; - if (ndepSelection.contains("2002")) - ndepType = "dailyNDep_2004"; - else if (ndepSelection.contains("2010")) - ndepType = "dailyNDep_2008"; - - File ratioF = new File(this.ratioFile.getText()); - if (ratioF == null || ratioF.isDirectory() || !ratioF.exists()) - throw new Exception("Ratio file is not existing!"); - File beld4F = new File(this.beld4Dir.getText()); - if (beld4F == null || beld4F.isDirectory() || !beld4F.exists()) - throw new Exception("Beld4 file is not existing!"); - - outMessages += "Epic base: " + baseDir + ls; - - String file = scenarioDir.trim() + "/scripts"; - // String year = domain.getSimYear(); - - file = file.trim() + "/extract_swatInputs_" + timeStamp + ".csh"; - // outMessages += file + ls; - - StringBuilder sb = new StringBuilder(); - sb.append(getSWATScriptHeader()); - String ls = "\n"; - - sb.append("#" + ls); - sb.append("# Set up runtime environment" + ls); - sb.append("#" + ls); - - sb.append("setenv EPIC_DIR " + baseDir + ls); - sb.append("setenv SCEN_DIR " + scenarioDir + ls); - sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls + ls); - sb.append("setenv NDEP_TYPE " + ndepType + ls); - sb.append("setenv SIM_YEAR " + simYear.getText() + ls + ls); - sb.append("setenv RUN_dailyEPIC YES" + ls); - sb.append("setenv RUN_MET YES" + ls); - sb.append("setenv RUN_NDEP YES" + ls); - - sb.append("# Get site infomation" + ls); - sb.append("setenv SITE_FILE ${SHARE_DIR}/AllSites_Info.csv" + ls + ls); - sb.append("# Define ratio input file" + ls); - sb.append("setenv RATIO_FILE " + ratioF + ls + ls); - - sb.append("# output location" + ls); - sb.append("setenv OUTDIR $SCEN_DIR/output4SWAT" + ls); - sb.append("setenv SWAT_OUTDIR $SCEN_DIR/output4SWAT/swat_inputs" + ls); - sb.append("if ( ! -e $OUTDIR) mkdir -p $OUTDIR" + ls); - sb.append("if ( ! -e $SWAT_OUTDIR ) mkdir -p $SWAT_OUTDIR" + ls); - sb.append("if ( ! -e $SWAT_OUTDIR/dailydep ) mkdir -p $SWAT_OUTDIR/dailydep" + ls); - sb.append("if ( ! -e $SWAT_OUTDIR/dailyweath ) mkdir -p $SWAT_OUTDIR/dailyweath" + ls); - sb.append("if ( ! -e $SWAT_OUTDIR/EPICinputPoint ) mkdir -p $SWAT_OUTDIR/EPICinputPoint" + ls); - - sb.append("echo 'Extract swat inputs: ' $SCEN_DIR" + ls); - sb.append("R CMD BATCH --no-save --slave " + "$EPIC_DIR/util/swat/extract_swatInputs.R " - + "${SCEN_DIR}/scripts/extract_swatInputs_"+ ndepType + ".log" + ls + ls); - - String mesg = ""; - try { - File script = new File(file); - Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - mesg += "Created a script file: " + file + "\n"; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - } catch (IOException e) { - throw new Exception(e.getMessage()); - } - app.showMessage("Write script", mesg); - return file; - } - - private String writeWeatScript() throws Exception { - Date now = new Date(); // java.util.Date, NOT java.sql.Date or - // java.sql.Timestamp! - String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - - String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - String scenarioDir = this.scenarioDir.getText(); - File beld4F = new File(this.beld4Dir.getText()); - if (beld4F == null || beld4F.isDirectory() || !beld4F.exists()) - throw new Exception("Beld4 file is not existing!"); - - String ndepSelection = (String) nDepSel.getSelectedItem(); - String ndepType = ndepSelection; - if (ndepSelection.contains("2002")) - ndepType = "dailyNDep_2004"; - else if (ndepSelection.contains("2010")) - ndepType = "dailyNDep_2008"; - - outMessages += "Epic base: " + baseDir + ls; - - String file = scenarioDir.trim() + "/scripts"; - // String year = domain.getSimYear(); - - file = file.trim() + "/epic2swat_daily_metCMAQ_" + timeStamp + ".csh"; - // outMessages += file + ls; - - StringBuilder sb = new StringBuilder(); - sb.append(getWeatScriptHeader()); - String ls = "\n"; - - sb.append("#" + ls); - sb.append("# Set up runtime environment" + ls); - sb.append("#" + ls); - - sb.append("setenv EPIC_DIR " + baseDir + ls); - sb.append("setenv SCEN_DIR " + scenarioDir + ls); - sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls + ls); - sb.append("# Get site infomation" + ls); - sb.append("setenv SITE_FILE ${SHARE_DIR}/allSites_Info.csv" + ls + ls); - sb.append("# Define BELD4 input file, get crop fractions " + ls); - sb.append("setenv DOMAIN_BELD4_NETCDF " + beld4Dir.getText() + ls + ls); - - sb.append("# met yearly file location" + ls); - sb.append("setenv NDEP_TYPE " + ndepType + ls); - sb.append("setenv DEPMET_FILE " + metdepFile.getText() + ls + ls); - - sb.append("# output location" + ls); - sb.append("setenv OUTDIR $SCEN_DIR/output4SWAT/dailyWETH/" + ndepType + ls); - sb.append("if ( ! -e $OUTDIR) mkdir -p $OUTDIR" + ls); - sb.append("if ( ! -e $OUTDIR/county ) mkdir -p $OUTDIR/county" + ls); - sb.append("if ( ! -e $OUTDIR/state ) mkdir -p $OUTDIR/state" + ls); - sb.append("if ( ! -e $OUTDIR/domain ) mkdir -p $OUTDIR/domain" + ls); - sb.append("if ( ! -e $OUTDIR/HUC8 ) mkdir -p $OUTDIR/HUC8" + ls); - sb.append("if ( ! -e $OUTDIR/HUC6 ) mkdir -p $OUTDIR/HUC6" + ls); - sb.append("if ( ! -e $OUTDIR/HUC2 ) mkdir -p $OUTDIR/HUC2" + ls + ls); - - sb.append("setenv REGION " + hucSel.getSelectedItem() + ls + ls); - // sb.append("cd $EPIC_DIR/util/swat/" + ls ); - sb.append("echo 'Extract daily met/dep for SWAT from ' " + scenarioDir + ls); - sb.append("R CMD BATCH --no-save --slave " + "$EPIC_DIR/util/swat/epic2swat_extract_daily_metCMAQ.R " - + "${SCEN_DIR}/scripts/epic2swat_extract_daily_metCMAQ.log" + ls + ls); - - String mesg = ""; - try { - File script = new File(file); - Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - mesg += "Created a script file: " + file + "\n"; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - } catch (IOException e) { - throw new Exception(e.getMessage()); - } - app.showMessage("Write script", mesg); - return file; - } - - private String getEpicScriptHeader() { - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: Prepare runoff inputs for SWAT by extracting " + ls); - sb.append("# EPIC daily output files output4CMAQ/app/daily/*NCD " + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("# Developed by: UNC Institute for the Environment" + ls); - sb.append("# Date: 10/30/2018" + ls); - sb.append("#" + ls); - sb.append("# Program: $EPIC_DIR/util/swat/epic2swat_extract_daily_epic.R" + ls); - sb.append("#" + ls); - sb.append("#***************************************************************************************" + ls + ls); - - return sb.toString(); - } - - private String getNdepScriptHeader() { - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: repare N Deposition inputs for SWAT by summarizing met data, " + ls); - sb.append("# netcdf weather data under ${SHAREDIR}/ " + ls); - sb.append("# $COMMON_data/EPIC_model/dailyNDep_200? " + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("# Developed by: UNC Institute for the Environment" + ls); - sb.append("# Date: 10/30/2017" + ls); - sb.append("#" + ls); - sb.append("# Program: $EPIC_DIR/util/swat/epic2swat_extract_daily_ndep.R" + ls); - sb.append("#" + ls); - sb.append("#***************************************************************************************" + ls + ls); - - return sb.toString(); - } - - private String getWeatScriptHeader() { - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: Prepare N Deposition and weather inputs for SWAT by summarizing " + ls); - sb.append("# netcdf weather data under ${SHAREDIR}/ " + ls); - sb.append("# $COMMON_data/EPIC_model/dailyNDep_200?/ " + ls); - sb.append("#" + ls); - sb.append("#" + ls); - sb.append("# Developed by: UNC Institute for the Environment" + ls); - sb.append("# Date: 10/30/2017" + ls); - sb.append("#" + ls); - sb.append("# Program: $EPIC_DIR/util/swat/epic2swat_daily_depWETHnc.R" + ls); - sb.append("#" + ls); - sb.append("#***************************************************************************************" + ls + ls); - - return sb.toString(); - } - - private String getSWATScriptHeader() { - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: Prepare swat inputs: dailyEPIC, NDEP, and weather" + ls); - sb.append("#" + ls); - sb.append("# Developed by: UNC Institute for the Environment" + ls); - sb.append("# Date: 10/30/2017" + ls); - sb.append("#" + ls); - sb.append("# Program: $EPIC_DIR/util/swat/extract_swatInputs.R" + ls); - sb.append("#" + ls); - sb.append("#***************************************************************************************" + ls + ls); - - return sb.toString(); - } - - private void runScript(final String file) { - String log = file + ".log"; - outMessages += "Script file: " + file + ls; - outMessages += "Log file: " + log + ls; - runMessages.setText(outMessages); - runMessages.validate(); - FileRunner.runScript(file, log, msg); - } - - @Override - public void projectLoaded() { - fields = (Epic2SWATFields)app.getProject().getPage(fields.getName()); - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - if (fields != null) { - fields = (Epic2SWATFields) app.getProject().getPage(fields.getName()); - String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length() > 0) - this.scenarioDir.setText(scenloc); - else - this.scenarioDir.setText(fields.getScenarioDir()); - // - try { - simYear.setValue( - NumberFormat.getNumberInstance().parse(domain.getSimYear() == null ? "" : domain.getSimYear())); - - } catch (ParseException e) { - simYear.setValue(0); - } - String year = simYear.getText(); - if (fields.getMetdep() == null) { - String depmet = domain.getScenarioDir().trim() + "/share_data/site_weather_dep_" + year + "0101" - + "_to_" + year + "1231" + ".nc"; - this.metdepFile.setText(depmet); - } else - this.metdepFile.setText(fields.getMetdep()); - beld4Dir.setText(fields.getBeld4ncf()); - hucSel.setSelectedItem(fields.getHucSelection()); - nDepSel.setSelectedItem(fields.getNDepSelection() ); - ratioFile.setText(fields.getRatioFile()); - // filesPrefix.setText(fields.getOutfileprefix()); - runMessages.setText(fields.getMessage()); - } else { - newProjectCreated(); - } - } - - @Override - public void saveProjectRequested() { - fields.setBeld4ncf(beld4Dir.getText()); - fields.setMetdep(metdepFile.getText()); - fields.setHucSelection((String) hucSel.getSelectedItem()); - fields.setNDepSelection((String) nDepSel.getSelectedItem()); - fields.setScenarioDir(scenarioDir.getText()); - if (ratioFile != null) - fields.setRatioFile(ratioFile.getText() == null ? "" : ratioFile.getText()); - if (runMessages != null) - fields.setMessage(runMessages.getText()); - } - - @Override - public void newProjectCreated() { - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - String scenDir = domain.getScenarioDir().trim(); - scenarioDir.setText(domain.getScenarioDir()); - String year = domain.getNlcdYear().trim(); - // simYear.setValue(year); - // filesPrefix.setText(""); - // String beld4file = fields.getBeld4ncf(); - // if ( beld4file == null || beld4file.trim().isEmpty() ) - String beld4file = scenDir + "/share_data/beld4_" + domain.getGridName() + "_" + year + ".nc"; - this.beld4Dir.setText(beld4file); - String depmet = scenDir + "/share_data/site_weather_dep_" + year + "0101" + "_to_" + year + "1231" + ".nc"; - this.metdepFile.setText(depmet); - nDepSel.setSelectedIndex(0); - hucSel.setSelectedIndex(0); - - runMessages.setText(""); - ratioFile.setText(""); - // filesPrefix.setText(""); - try { - simYear.setValue(NumberFormat.getNumberInstance().parse(year == null ? "" : domain.getSimYear())); - } catch (ParseException e) { - simYear.setValue(0); - } - - // if ( fields == null ) { - // fields = new Epic2SWATFields(); - app.getProject().addPage(fields); - // } - } - -} +package gov.epa.festc.gui; + +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.NumberFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFormattedTextField; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SpringLayout; +import javax.swing.SwingConstants; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.core.proj.DomainFields; +import gov.epa.festc.core.proj.Epic2SWATFields; +import gov.epa.festc.util.BrowseAction; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.FileRunner; +import gov.epa.festc.util.SpringLayoutGenerator; +import simphony.util.messages.MessageCenter; + +public class Epic2SWATPanel extends UtilFieldsPanel implements PlotEventListener { + private static final long serialVersionUID = 4247819754945274135L; + private JTextField beld4Dir; + private JButton beld4FileBrowser; + private JButton ratioFileBrowser; + private JButton weathFileBrowser; + + // private JTextField filesPrefix; + private MessageCenter msg; + private JTextField metdepFile; + private JTextField depFile; + private JTextField ratioFile; + private JComboBox nDepSel; + private JComboBox hucSel; + private JFormattedTextField simYear; + + private FestcApplication app; + private Epic2SWATFields fields; + + public Epic2SWATPanel(FestcApplication application) { + app = application; + msg = app.getMessageCenter(); + fields = new Epic2SWATFields(); + app.getProject().addPage(fields); + app.addPlotListener(this); + add(createPanel()); + } + + private JPanel createPanel() { + init(); + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + mainPanel.add(getNorthPanel()); + mainPanel.add(getCenterPanel()); + mainPanel.add(getSouthPanel()); + mainPanel.add(messageBox()); + return mainPanel; + } + + private JPanel getNorthPanel() { + JPanel panel = new JPanel(); + JLabel title = new JLabel(Constants.EPIC2SWAT, SwingConstants.CENTER); + title.setFont(new Font("Default", Font.BOLD, 20)); + + panel.add(title); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); + + return panel; + } + + private JPanel getSouthPanel() { + JPanel panel = new JPanel(); + JButton runDaily = new JButton(runDailyAction()); + panel.add(runDaily); + JButton runNDep = new JButton(runNDepAction()); + panel.add(runNDep); + JButton runWeather = new JButton(runWeatAction()); + panel.add(runWeather); + JButton runSWATin = new JButton(runSWATAction()); + panel.add(runSWATin); + + panel.setBorder(BorderFactory.createEmptyBorder(30, 0, 10, 0)); + + return panel; + } + + private JPanel getCenterPanel() { + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + + JPanel beld4DirPanel = new JPanel(); + beld4Dir = new JTextField(40); + beld4Dir.setToolTipText("I.E. share_data/beld4_cmaq12km_2001.nc"); + beld4FileBrowser = new JButton(BrowseAction.browseAction(this, app.getCurrentDir(), "BELD4 file", beld4Dir)); + beld4DirPanel.add(beld4Dir); + beld4DirPanel.add(beld4FileBrowser); + + JPanel weatherPanel = new JPanel(); + metdepFile = new JTextField(40); + metdepFile.setToolTipText("Select Site_weather_dep* file"); + weathFileBrowser = new JButton(BrowseAction.browseAction(this, app.getCurrentDir(), "WETDEP file", metdepFile)); + weatherPanel.add(metdepFile); + weatherPanel.add(weathFileBrowser); + + JPanel ratioPanel = new JPanel(); + ratioFile = new JTextField(40); + ratioFile.setToolTipText("Huc8 Delivery Ratio file"); + ratioFileBrowser = new JButton( + BrowseAction.browseAction(this, app.getCurrentDir(), "HUC8 Ratio file", ratioFile)); + ratioPanel.add(ratioFile); + ratioPanel.add(ratioFileBrowser); + + nDepSel = new JComboBox(Constants.SWAT_NDEPS); + nDepSel.setSelectedIndex(1); + nDepSel.setToolTipText("Select CMAQ deposition. "); + hucSel = new JComboBox(Constants.AREAS); + hucSel.setSelectedIndex(1); + hucSel.setToolTipText("Select HUC. "); + + JPanel filesPrefixPanel = new JPanel(); + // filesPrefix = new JTextField(40); + // filesPrefixPanel.add(filesPrefix); + // + + // JPanel depField = new JPanel(); + // depFile = new JTextField(40); + // depField.add(depFile); + // + // JPanel ratioField = new JPanel(); + // ratioFile = new JTextField(40); + // ratioField.add(ratioFile); + + // JPanel startDatePanel = new JPanel(); + // NumberFormat snf = NumberFormat.getNumberInstance(); + // snf.setGroupingUsed(false); + // startDate = new JFormattedTextField(snf); + // startDate.setColumns(40); + // startDatePanel.add(startDate); + + JPanel simYearPanel = new JPanel(); + NumberFormat enf = NumberFormat.getNumberInstance(); + enf.setGroupingUsed(false); + simYear = new JFormattedTextField(enf); + simYear.setColumns(20); + simYearPanel.add(simYear); + simYear.setEditable(false); + + // layout.addLabelWidgetPair("Grid Description:", + // getGridDescPanel(false), panel); + layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); + layout.addLabelWidgetPair("BELD4 NetCDF File: ", beld4DirPanel, panel); + layout.addLabelWidgetPair("Met dep File:", weatherPanel, panel); + layout.addLabelWidgetPair("HUC8 Delivery Ratio File:", ratioPanel, panel); + layout.addLabelWidgetPair("Simulation Year:", simYearPanel, panel); + + layout.addLabelWidgetPair("Daily Average N Deposition: ", nDepSel, panel); + layout.addLabelWidgetPair("Area Selection: ", hucSel, panel); + // layout.addLabelWidgetPair("EPIC extraction Prefix:", + // filesPrefixPanel, panel); + + layout.makeCompactGrid(panel, 7, 2, // number of rows and cols + 10, 10, // initial X and Y + 5, 5); // x and y pading + + return panel; + } + + private Action runDailyAction() { + return new AbstractAction("EPIC") { + private static final long serialVersionUID = 5806383737068197305L; + + public void actionPerformed(ActionEvent e) { + try { + validateFields(); + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + final String jobFile = writeEpicScript(); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir.getText(), "EPIC"); + } else { + batchFile = null; + } + + Thread populateThread = new Thread(new Runnable() { + public void run() { + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile); + } + } + }); + populateThread.start(); + } catch (Exception exc) { + app.showMessage("Run script", exc.getMessage()); + } + } + }; + } + + private Action runNDepAction() { + return new AbstractAction("NDEP") { + private static final long serialVersionUID = 5806383737068197305L; + + public void actionPerformed(ActionEvent e) { + try { + validateFields(); + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + final String jobFile = writeNDepScript(); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir.getText(), "NDEP"); + } else { + batchFile = null; + } + + Thread populateThread = new Thread(new Runnable() { + public void run() { + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile); + } + } + }); + populateThread.start(); + } catch (Exception exc) { + app.showMessage("Run script", exc.getMessage()); + } + } + }; + } + + private Action runWeatAction() { + return new AbstractAction("DailyWETH") { + private static final long serialVersionUID = 5806383737068197305L; + + public void actionPerformed(ActionEvent e) { + try { + validateFields(); + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + final String jobFile = writeWeatScript(); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir.getText(), "WETH"); + } else { + batchFile = null; + } + + Thread populateThread = new Thread(new Runnable() { + public void run() { + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile); + } + } + }); + populateThread.start(); + } catch (Exception exc) { + app.showMessage("Run script", exc.getMessage()); + } + } + }; + } + + private Action runSWATAction() { + return new AbstractAction("SWAT INPUTS") { + private static final long serialVersionUID = 5806383737068197305L; + + public void actionPerformed(ActionEvent e) { + try { + validateFields(); + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + final String jobFile = writeSWATScript(); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir.getText(), "SWAT"); + } else { + batchFile = null; + } + + Thread populateThread = new Thread(new Runnable() { + public void run() { + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile); + } + } + }); + populateThread.start(); + } catch (Exception exc) { + app.showMessage("Run script", exc.getMessage()); + } + } + }; + } + + private void validateFields() throws Exception { + + String sahome = Constants.getProperty(Constants.SA_HOME, msg); + if (sahome == null || sahome.trim().isEmpty() || !(new File(sahome).exists())) + throw new Exception("Error loading spacial allocator home:" + sahome + " doesn't exist"); + + String scenarioDir = this.scenarioDir.getText(); + if (scenarioDir == null || scenarioDir.isEmpty()) + throw new Exception("Please select scenario dir first!"); + + String sYear = simYear.getText(); + if (sYear == null || sYear.trim().isEmpty()) + throw new Exception("Simulation Year field is empty."); + } + + // This is legacy code that has been moved to it's own method + protected void writeScriptFile(String file, String content) { + + String mesg = ""; + + try { + File script = new File(file); + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(content); + out.close(); + + mesg += "Script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + + } catch (IOException e) { + // printStackTrace(); + // g.error("Error generating EPIC script file", e); + app.showMessage("Write script", e.getMessage()); + } + + app.showMessage("Write script", mesg); + } + + protected String writeBatchFile(String jobFile, String scenarioDir, String desc) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String batchFile = scenarioDir.trim() + "/scripts"; + if (!batchFile.endsWith(System.getProperty("file.separator"))) + batchFile += System.getProperty("file.separator"); + batchFile += "submitEpic2CMAQ_" + desc + "_" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh" + ls + ls); + + // TODO - add #SBATCH options here + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage == null || qSingModule.trim().isEmpty()) { + throw new Exception("Singularity image path must be specified"); + } + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + jobFile); + } else { + sb.append(jobFile); + } + + writeScriptFile(batchFile, sb.toString()); + + return batchFile; + } + + private String writeEpicScript() throws Exception { + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + + String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + String scenarioDir = this.scenarioDir.getText(); + File beld4F = new File(this.beld4Dir.getText()); + if (beld4F == null || beld4F.isDirectory() || !beld4F.exists()) + throw new Exception("Beld4 file is not existing!"); + + outMessages += "Epic base: " + baseDir + ls; + + String file = scenarioDir.trim() + "/scripts"; + + file = file.trim() + "/epic2swat_extract_dailyEpic_" + timeStamp + ".csh"; + // outMessages += file + ls; + + StringBuilder sb = new StringBuilder(); + sb.append(getEpicScriptHeader()); + String ls = "\n"; + + sb.append("#" + ls); + sb.append("# Set up runtime environment" + ls); + sb.append("#" + ls); + + String rModules = Constants.getProperty(Constants.QUEUE_R_MODULE, msg); + sb.append("module load " + rModules + ls); + + sb.append("setenv EPIC_DIR " + baseDir + ls); + sb.append("setenv SCEN_DIR " + scenarioDir + ls); + sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls); + sb.append("setenv SIM_YEAR " + simYear.getText() + ls + ls); + + sb.append("# Get site infomation" + ls); + sb.append("setenv SITE_FILE ${SHARE_DIR}/EPICSites_Info.csv" + ls + ls); + sb.append("# Define BELD4 input file, get crop fractions " + ls); + sb.append("setenv DOMAIN_BELD4_NETCDF " + beld4Dir.getText() + ls); + sb.append("setenv REGION " + hucSel.getSelectedItem() + ls + ls); + + sb.append("# Process multiple years" + ls); + sb.append("set SIM_YEAR=\"$SCEN_DIR/output4CMAQ/app/[1-2][0-9][0-9][0-9]\"" + ls); + sb.append("foreach MULTI_YEAR_DIR ($SIM_YEAR)" + ls); + sb.append(" set MULTI_YEAR=`basename $MULTI_YEAR_DIR`" + ls); + sb.append(" setenv SIM_YEAR $MULTI_YEAR" + ls + ls); + + sb.append("# EPIC input location" + ls); + sb.append(" setenv DAY_DIR $SCEN_DIR/output4CMAQ/app/${MULTI_YEAR}/daily" + ls + ls); + //sb.append("# SWAT output location" + ls); + sb.append(" setenv OUTDIR $SCEN_DIR/output4SWAT/${MULTI_YEAR}/dailyEPIC" + ls); + sb.append(" if ( ! -e $OUTDIR/county ) mkdir -p $OUTDIR/county" + ls); + sb.append(" if ( ! -e $OUTDIR/state ) mkdir -p $OUTDIR/state" + ls); + sb.append(" if ( ! -e $OUTDIR/domain ) mkdir -p $OUTDIR/domain" + ls); + sb.append(" if ( ! -e $OUTDIR/HUC8 ) mkdir -p $OUTDIR/HUC8" + ls); + sb.append(" if ( ! -e $OUTDIR/HUC6 ) mkdir -p $OUTDIR/HUC6" + ls); + sb.append(" if ( ! -e $OUTDIR/HUC2 ) mkdir -p $OUTDIR/HUC2" + ls + ls); + + // sb.append("setenv OUTFILE_PREFIX $OUTDIR/" + filesPrefix.getText() + + // ls + ls); + + + // sb.append("cd $EPIC_DIR/util/swat/" + ls ); + sb.append(" echo 'Run EPIC daily summary for swat: ' $MULTI_YEAR_DIR" + ls); + + sb.append(" R CMD BATCH --no-save --slave " + "$EPIC_DIR/util/swat/epic2swat_extract_dailyEPIC.R " + + "${SCEN_DIR}/scripts/epic2swat_extract_dailyEPIC_${MULTI_YEAR}.log" + ls); + sb.append("end" + ls + ls); + + String mesg = ""; + try { + File script = new File(file); + Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + mesg += "Created a script file: " + file + "\n"; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + } catch (IOException e) { + throw new Exception(e.getMessage()); + } + app.showMessage("Write script", mesg); + return file; + } + + private String writeNDepScript() throws Exception { + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + + String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + String scenarioDir = this.scenarioDir.getText(); + + String ndepSelection = (String) nDepSel.getSelectedItem(); + String ndepType = ndepSelection; + if (ndepSelection.contains("2002")) + ndepType = "dailyNDep_2004"; + else if (ndepSelection.contains("2010")) + ndepType = "dailyNDep_2008"; + + File beld4F = new File(this.beld4Dir.getText()); + if (beld4F == null || beld4F.isDirectory() || !beld4F.exists()) + throw new Exception("Beld4 file is not existing!"); + + outMessages += "Epic base: " + baseDir + ls; + + String file = scenarioDir.trim() + "/scripts"; + // String year = domain.getSimYear(); + + file = file.trim() + "/epic2swat_extract_NDEP_" + timeStamp + ".csh"; + // outMessages += file + ls; + + StringBuilder sb = new StringBuilder(); + sb.append(getNdepScriptHeader()); + String ls = "\n"; + + sb.append("#" + ls); + sb.append("# Set up runtime environment" + ls); + sb.append("#" + ls); + + String rModules = Constants.getProperty(Constants.QUEUE_R_MODULE, msg); + sb.append("module load " + rModules + ls); + + sb.append("setenv EPIC_DIR " + baseDir + ls); + sb.append("setenv SCEN_DIR " + scenarioDir + ls); + sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls + ls); + sb.append("# Get site infomation" + ls); + sb.append("setenv SITE_FILE ${SHARE_DIR}/allSites_Info.csv" + ls + ls); + + sb.append("# Define BELD4 input file" + ls); + sb.append("setenv DOMAIN_BELD4_NETCDF " + beld4Dir.getText() + ls + ls); + + sb.append("# Location of deposition files " + ls); + sb.append("setenv NDEP_TYPE " + ndepType + ls); + sb.append("setenv NDEP_FILE " + metdepFile.getText() + ls); + + sb.append("# Process multiple years" + ls); + sb.append("set SIM_YEAR=\"$SCEN_DIR/output4CMAQ/app/[1-2][0-9][0-9][0-9]\"" + ls); + sb.append("foreach MULTI_YEAR_DIR ($SIM_YEAR)" + ls); + sb.append(" set MULTI_YEAR=`basename $MULTI_YEAR_DIR`" + ls); + sb.append(" setenv SIM_YEAR $MULTI_YEAR" + ls + ls); + + sb.append("# output location" + ls); + sb.append(" setenv OUTDIR $SCEN_DIR/output4SWAT/${MULTI_YEAR}/NDEP/" + ndepType + ls); + sb.append(" if ( ! -e $OUTDIR) mkdir -p $OUTDIR" + ls); + sb.append(" if ( ! -e $OUTDIR/county ) mkdir -p $OUTDIR/county" + ls); + sb.append(" if ( ! -e $OUTDIR/state ) mkdir -p $OUTDIR/state" + ls); + sb.append(" if ( ! -e $OUTDIR/domain ) mkdir -p $OUTDIR/domain" + ls); + sb.append(" if ( ! -e $OUTDIR/HUC8 ) mkdir -p $OUTDIR/HUC8" + ls); + sb.append(" if ( ! -e $OUTDIR/HUC6 ) mkdir -p $OUTDIR/HUC6" + ls); + sb.append(" if ( ! -e $OUTDIR/HUC2 ) mkdir -p $OUTDIR/HUC2" + ls + ls); + + // sb.append("setenv REGION " + hucSel.getSelectedItem() + ls); + // sb.append("cd $EPIC_DIR/util/swat/" + ls ); + sb.append(" echo 'Extract daily depositon from yearly CMAQ or 2004/2008 averaged ndep: ' $MULTI_YEAR_DIR" + ls); + sb.append(" R CMD BATCH --no-save --slave " + "$EPIC_DIR/util/swat/epic2swat_extract_daily_ndepCMAQ.R " + + "${SCEN_DIR}/scripts/epic2swat_extract_daily_ndepCMAQ_${MULTI_YEAR}.log" + ls); + sb.append("end" + ls + ls); + + String mesg = ""; + try { + File script = new File(file); + Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + mesg += "Created a script file: " + file + "\n"; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + } catch (IOException e) { + throw new Exception(e.getMessage()); + } + app.showMessage("Write script", mesg); + return file; + } + + private String writeSWATScript() throws Exception { + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + + String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + String scenarioDir = this.scenarioDir.getText(); + + String ndepSelection = (String) nDepSel.getSelectedItem(); + String ndepType = ndepSelection; + if (ndepSelection.contains("2002")) + ndepType = "dailyNDep_2004"; + else if (ndepSelection.contains("2010")) + ndepType = "dailyNDep_2008"; + + File ratioF = new File(this.ratioFile.getText()); + if (ratioF == null || ratioF.isDirectory() || !ratioF.exists()) + throw new Exception("Ratio file is not existing!"); + File beld4F = new File(this.beld4Dir.getText()); + if (beld4F == null || beld4F.isDirectory() || !beld4F.exists()) + throw new Exception("Beld4 file is not existing!"); + + outMessages += "Epic base: " + baseDir + ls; + + String file = scenarioDir.trim() + "/scripts"; + // String year = domain.getSimYear(); + + file = file.trim() + "/extract_swatInputs_" + timeStamp + ".csh"; + // outMessages += file + ls; + + StringBuilder sb = new StringBuilder(); + sb.append(getSWATScriptHeader()); + String ls = "\n"; + + sb.append("#" + ls); + sb.append("# Set up runtime environment" + ls); + sb.append("#" + ls); + + String rModules = Constants.getProperty(Constants.QUEUE_R_MODULE, msg); + sb.append("module load " + rModules + ls); + + sb.append("setenv EPIC_DIR " + baseDir + ls); + sb.append("setenv SCEN_DIR " + scenarioDir + ls); + sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls + ls); + sb.append("setenv NDEP_TYPE " + ndepType + ls); + sb.append("setenv SIM_YEAR " + simYear.getText() + ls + ls); + sb.append("setenv RUN_dailyEPIC YES" + ls); + sb.append("setenv RUN_MET YES" + ls); + sb.append("setenv RUN_NDEP YES" + ls); + + sb.append("# Get site infomation" + ls); + sb.append("setenv SITE_FILE ${SHARE_DIR}/AllSites_Info.csv" + ls + ls); + sb.append("# Define ratio input file" + ls); + sb.append("setenv RATIO_FILE " + ratioF + ls + ls); + + sb.append("# Process multiple years" + ls); + sb.append("set SIM_YEAR=\"$SCEN_DIR/output4CMAQ/app/[1-2][0-9][0-9][0-9]\"" + ls); + sb.append("foreach MULTI_YEAR_DIR ($SIM_YEAR)" + ls); + sb.append(" set MULTI_YEAR=`basename $MULTI_YEAR_DIR`" + ls); + sb.append(" setenv SIM_YEAR $MULTI_YEAR" + ls + ls); + + sb.append("# output location" + ls); + sb.append(" setenv OUTDIR $SCEN_DIR/output4SWAT/$MULTI_YEAR" + ls); + sb.append(" setenv SWAT_OUTDIR $SCEN_DIR/output4SWAT/${MULTI_YEAR}/swat_inputs" + ls); + sb.append(" if ( ! -e $OUTDIR) mkdir -p $OUTDIR" + ls); + sb.append(" if ( ! -e $SWAT_OUTDIR ) mkdir -p $SWAT_OUTDIR" + ls); + sb.append(" if ( ! -e $SWAT_OUTDIR/dailydep ) mkdir -p $SWAT_OUTDIR/dailydep" + ls); + sb.append(" if ( ! -e $SWAT_OUTDIR/dailyweath ) mkdir -p $SWAT_OUTDIR/dailyweath" + ls); + sb.append(" if ( ! -e $SWAT_OUTDIR/EPICinputPoint ) mkdir -p $SWAT_OUTDIR/EPICinputPoint" + ls); + + sb.append(" echo 'Extract swat inputs: ' $MULTI_YEAR_DIR" + ls); + sb.append(" R CMD BATCH --no-save --slave " + "$EPIC_DIR/util/swat/extract_swatInputs.R " + + "${SCEN_DIR}/scripts/extract_swatInputs_" + ndepType + "_${MULTI_YEAR}.log" + ls); + sb.append("end" + ls + ls); + + String mesg = ""; + try { + File script = new File(file); + Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + mesg += "Created a script file: " + file + "\n"; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + } catch (IOException e) { + throw new Exception(e.getMessage()); + } + app.showMessage("Write script", mesg); + return file; + } + + private String writeWeatScript() throws Exception { + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + + String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + String scenarioDir = this.scenarioDir.getText(); + File beld4F = new File(this.beld4Dir.getText()); + if (beld4F == null || beld4F.isDirectory() || !beld4F.exists()) + throw new Exception("Beld4 file is not existing!"); + + String ndepSelection = (String) nDepSel.getSelectedItem(); + String ndepType = ndepSelection; + if (ndepSelection.contains("2002")) + ndepType = "dailyNDep_2004"; + else if (ndepSelection.contains("2010")) + ndepType = "dailyNDep_2008"; + + outMessages += "Epic base: " + baseDir + ls; + + String file = scenarioDir.trim() + "/scripts"; + // String year = domain.getSimYear(); + + file = file.trim() + "/epic2swat_daily_metCMAQ_" + timeStamp + ".csh"; + // outMessages += file + ls; + + StringBuilder sb = new StringBuilder(); + sb.append(getWeatScriptHeader()); + String ls = "\n"; + + sb.append("#" + ls); + sb.append("# Set up runtime environment" + ls); + sb.append("#" + ls); + + String rModules = Constants.getProperty(Constants.QUEUE_R_MODULE, msg); + sb.append("module load " + rModules + ls); + + sb.append("setenv EPIC_DIR " + baseDir + ls); + sb.append("setenv SCEN_DIR " + scenarioDir + ls); + sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls + ls); + sb.append("# Get site infomation" + ls); + sb.append("setenv SITE_FILE ${SHARE_DIR}/allSites_Info.csv" + ls + ls); + sb.append("# Define BELD4 input file, get crop fractions " + ls); + sb.append("setenv DOMAIN_BELD4_NETCDF " + beld4Dir.getText() + ls + ls); + + sb.append("# met yearly file location" + ls); + sb.append("setenv NDEP_TYPE " + ndepType + ls); + sb.append("setenv DEPMET_FILE " + metdepFile.getText() + ls + ls); + sb.append("setenv REGION " + hucSel.getSelectedItem() + ls + ls); + + sb.append("# Process multiple years" + ls); + sb.append("set SIM_YEAR=\"$SCEN_DIR/output4CMAQ/app/[1-2][0-9][0-9][0-9]\"" + ls); + sb.append("foreach MULTI_YEAR_DIR ($SIM_YEAR)" + ls); + sb.append(" set MULTI_YEAR=`basename $MULTI_YEAR_DIR`" + ls); + sb.append(" setenv SIM_YEAR $MULTI_YEAR" + ls + ls); + + sb.append("# output location" + ls); + sb.append(" setenv OUTDIR $SCEN_DIR/output4SWAT/${MULTI_YEAR}/dailyWETH/" + ndepType + ls); + sb.append(" if ( ! -e $OUTDIR) mkdir -p $OUTDIR" + ls); + sb.append(" if ( ! -e $OUTDIR/county ) mkdir -p $OUTDIR/county" + ls); + sb.append(" if ( ! -e $OUTDIR/state ) mkdir -p $OUTDIR/state" + ls); + sb.append(" if ( ! -e $OUTDIR/domain ) mkdir -p $OUTDIR/domain" + ls); + sb.append(" if ( ! -e $OUTDIR/HUC8 ) mkdir -p $OUTDIR/HUC8" + ls); + sb.append(" if ( ! -e $OUTDIR/HUC6 ) mkdir -p $OUTDIR/HUC6" + ls); + sb.append(" if ( ! -e $OUTDIR/HUC2 ) mkdir -p $OUTDIR/HUC2" + ls + ls); + + // sb.append("cd $EPIC_DIR/util/swat/" + ls ); + sb.append(" echo 'Extract daily met/dep for SWAT from ' $MULTI_YEAR_DIR" + ls); + sb.append(" R CMD BATCH --no-save --slave " + "$EPIC_DIR/util/swat/epic2swat_extract_daily_metCMAQ.R " + + "${SCEN_DIR}/scripts/epic2swat_extract_daily_metCMAQ_${MULTI_YEAR}.log" + ls + ls); + sb.append("end" + ls + ls); + + String mesg = ""; + try { + File script = new File(file); + Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + mesg += "Created a script file: " + file + "\n"; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + } catch (IOException e) { + throw new Exception(e.getMessage()); + } + app.showMessage("Write script", mesg); + return file; + } + + private String getEpicScriptHeader() { + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append("#!/bin/csh" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: Prepare runoff inputs for SWAT by extracting " + ls); + sb.append("# EPIC daily output files output4CMAQ/app/daily/*NCD " + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("# Developed by: UNC Institute for the Environment" + ls); + sb.append("# Date: 10/30/2018" + ls); + sb.append("#" + ls); + sb.append("# Program: $EPIC_DIR/util/swat/epic2swat_extract_daily_epic.R" + ls); + sb.append("#" + ls); + sb.append("#***************************************************************************************" + ls + ls); + + return sb.toString(); + } + + private String getNdepScriptHeader() { + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append("#!/bin/csh" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: Prepare N Deposition inputs for SWAT by summarizing met data, " + ls); + sb.append("# netcdf weather data under ${SHAREDIR}/ " + ls); + sb.append("# $COMMON_data/EPIC_model/dailyNDep_200? " + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("# Developed by: UNC Institute for the Environment" + ls); + sb.append("# Date: 10/30/2017" + ls); + sb.append("#" + ls); + sb.append("# Program: $EPIC_DIR/util/swat/epic2swat_extract_daily_ndep.R" + ls); + sb.append("#" + ls); + sb.append("#***************************************************************************************" + ls + ls); + + return sb.toString(); + } + + private String getWeatScriptHeader() { + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append("#!/bin/csh" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: Prepare N Deposition and weather inputs for SWAT by summarizing " + ls); + sb.append("# netcdf weather data under ${SHAREDIR}/ " + ls); + sb.append("# $COMMON_data/EPIC_model/dailyNDep_200?/ " + ls); + sb.append("#" + ls); + sb.append("#" + ls); + sb.append("# Developed by: UNC Institute for the Environment" + ls); + sb.append("# Date: 10/30/2017" + ls); + sb.append("#" + ls); + sb.append("# Program: $EPIC_DIR/util/swat/epic2swat_daily_depWETHnc.R" + ls); + sb.append("#" + ls); + sb.append("#***************************************************************************************" + ls + ls); + + return sb.toString(); + } + + private String getSWATScriptHeader() { + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append("#!/bin/csh" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: Prepare swat inputs: dailyEPIC, NDEP, and weather" + ls); + sb.append("#" + ls); + sb.append("# Developed by: UNC Institute for the Environment" + ls); + sb.append("# Date: 10/30/2017" + ls); + sb.append("#" + ls); + sb.append("# Program: $EPIC_DIR/util/swat/extract_swatInputs.R" + ls); + sb.append("#" + ls); + sb.append("#***************************************************************************************" + ls + ls); + + return sb.toString(); + } + + private void runScript(final String file) { + String log = file + ".log"; + outMessages += "Script file: " + file + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + FileRunner.runScript(file, log, msg); + } + + private void runBatchScript(final String batchFile, final String jobFile) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qEpic2Swat = Constants.getProperty(Constants.QUEUE_EPIC2SWAT, msg); + + File script = new File(batchFile.replaceAll("\\\\", "\\\\\\\\")); + + sb.append(qcmd + " " + qEpic2Swat + " -o " + log + " " + script.getAbsolutePath()); + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } + + @Override + public void projectLoaded() { + fields = (Epic2SWATFields) app.getProject().getPage(fields.getName()); + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + if (fields != null) { + fields = (Epic2SWATFields) app.getProject().getPage(fields.getName()); + String scenloc = domain.getScenarioDir(); + if (scenloc != null && scenloc.trim().length() > 0) + this.scenarioDir.setText(scenloc); + else + this.scenarioDir.setText(fields.getScenarioDir()); + // + try { + simYear.setValue( + NumberFormat.getNumberInstance().parse(domain.getSimYear() == null ? "" : domain.getSimYear())); + + } catch (ParseException e) { + simYear.setValue(0); + } + String year = simYear.getText(); + if (fields.getMetdep() == null) { + String depmet = domain.getScenarioDir().trim() + "/share_data/site_weather_dep_" + year + "0101" + + "_to_" + year + "1231" + ".nc"; + this.metdepFile.setText(depmet); + } else + this.metdepFile.setText(fields.getMetdep()); + beld4Dir.setText(fields.getBeld4ncf()); + hucSel.setSelectedItem(fields.getHucSelection()); + nDepSel.setSelectedItem(fields.getNDepSelection()); + ratioFile.setText(fields.getRatioFile()); + // filesPrefix.setText(fields.getOutfileprefix()); + runMessages.setText(fields.getMessage()); + } else { + newProjectCreated(); + } + } + + @Override + public void saveProjectRequested() { + fields.setBeld4ncf(beld4Dir.getText()); + fields.setMetdep(metdepFile.getText()); + fields.setHucSelection((String) hucSel.getSelectedItem()); + fields.setNDepSelection((String) nDepSel.getSelectedItem()); + fields.setScenarioDir(scenarioDir.getText()); + if (ratioFile != null) + fields.setRatioFile(ratioFile.getText() == null ? "" : ratioFile.getText()); + if (runMessages != null) + fields.setMessage(runMessages.getText()); + } + + @Override + public void newProjectCreated() { + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + String scenDir = domain.getScenarioDir().trim(); + scenarioDir.setText(domain.getScenarioDir()); + String year = domain.getNlcdYear().trim(); + // simYear.setValue(year); + // filesPrefix.setText(""); + // String beld4file = fields.getBeld4ncf(); + // if ( beld4file == null || beld4file.trim().isEmpty() ) + String beld4file = scenDir + "/share_data/beld4_" + domain.getGridName() + "_" + year + ".nc"; + this.beld4Dir.setText(beld4file); + String depmet = scenDir + "/share_data/site_weather_dep_" + year + "0101" + "_to_" + year + "1231" + ".nc"; + this.metdepFile.setText(depmet); + nDepSel.setSelectedIndex(0); + hucSel.setSelectedIndex(0); + + runMessages.setText(""); + ratioFile.setText(""); + // filesPrefix.setText(""); + try { + simYear.setValue(NumberFormat.getNumberInstance().parse(year == null ? "" : domain.getSimYear())); + } catch (ParseException e) { + simYear.setValue(0); + } + + // if ( fields == null ) { + // fields = new Epic2SWATFields(); + app.getProject().addPage(fields); + // } + } + +} diff --git a/festc_core/src/gov/epa/festc/gui/EpicRunAppPanel.java b/festc_core/src/gov/epa/festc/gui/EpicRunAppPanel.java index b2c409a..02bd125 100644 --- a/festc_core/src/gov/epa/festc/gui/EpicRunAppPanel.java +++ b/festc_core/src/gov/epa/festc/gui/EpicRunAppPanel.java @@ -41,16 +41,19 @@ public class EpicRunAppPanel extends UtilFieldsPanel implements PlotEventListene //private JComboBox comboCrops; private JTextField simYear; + private JTextField simEndYear; private MessageCenter msg; String baseDir = null; + String epicVer = null; private EpicAppFields fields; //private DomainFields domain; private JComboBox nDepSel; private JComboBox runTiledrain; + private JComboBox outputFormat; private JTextField co2Factor; public EpicRunAppPanel(FestcApplication application) { @@ -59,6 +62,7 @@ public EpicRunAppPanel(FestcApplication application) { app.getProject().addPage(fields); msg = app.getMessageCenter(); baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + epicVer = Constants.getProperty(Constants.EPIC_VER, msg).trim(); app.addPlotListener(this); add(createPanel()); } @@ -108,15 +112,21 @@ private JPanel getCenterPanel() { runTiledrain = new JComboBox(new String[] {"YES", "NO"}); runTiledrain.setSelectedIndex(1); + + outputFormat = new JComboBox(new String[] {"Text & NetCDF", "NetCDF only", "Text only"}); + outputFormat.setSelectedIndex(2); this.simYear = new JTextField(20); + this.simEndYear = new JTextField(20); layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDir, panel); layout.addLabelWidgetPair("Simulation Year: ", simYear, panel); + layout.addLabelWidgetPair("Simulation End Year: ", simEndYear, panel); layout.addLabelWidgetPair("CO2 Level (ppm):",co2Factor, panel); layout.addLabelWidgetPair("Daily Average N Deposition: ", nDepSel, panel); layout.addLabelWidgetPair("Run Tiledrain : ", runTiledrain, panel); + layout.addLabelWidgetPair("Output Format : ", outputFormat, panel); - layout.makeCompactGrid(panel, 5,2, // number of rows and cols + layout.makeCompactGrid(panel, 7,2, // number of rows and cols 10, 10, // initial X and Y 5, 5); // x and y pading @@ -188,6 +198,16 @@ private void generateRunScript() throws Exception { throw new Exception( "Simulation year is not an integer!"); } + String simEndY = this.simEndYear.getText(); + if (simEndY == null || simEndY.isEmpty()) + throw new Exception( "Please select simulation end year. "); + + try { + Integer.parseInt(simEndY); + }catch(NumberFormatException e) { + throw new Exception( "Simulation end year is not an integer!"); + } + String ndepValue = (String) this.nDepSel.getSelectedItem(); if ( ndepValue == null || ndepValue.isEmpty()) throw new Exception( "Deposition dir is empty, please specify it!"); @@ -215,18 +235,34 @@ private void generateRunScript() throws Exception { outMessages += "Epic base: " + baseDir + ls; outMessages += "Scen directory: " + scenarioDir + ls; - final String file = writeRunScript(baseDir, scenarioDir, seCropsString, cropIDs, - simY, ndepValue); + final String jobFile = writeRunScript(baseDir, scenarioDir, seCropsString, cropIDs, + simY, simEndY, ndepValue); + + String cropNums = getChosenCropNums(); + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir); + } else { + batchFile = null; + } + Thread populateThread = new Thread(new Runnable() { public void run() { - runScript(file); + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile, cropNums); + } } }); populateThread.start(); } protected String writeRunScript( String baseDir, String scenarioDir, - String cropNames, String cropIDs, String simY, String ndepValue) throws Exception { + String cropNames, String cropIDs, String simY, String simEndY, String ndepValue) throws Exception { + Date now = new Date(); // java.util.Date, NOT java.sql.Date or java.sql.Timestamp! String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); @@ -235,18 +271,41 @@ protected String writeRunScript( String baseDir, String scenarioDir, file += System.getProperty("file.separator"); file += "runEpicApp_" + timeStamp + ".csh"; + int numY = Integer.parseInt(simEndY) - Integer.parseInt(simY) + 2; +// boolean multiYear = numY>2; + String simNY = Integer.toString(numY); + StringBuilder sb = new StringBuilder(); - sb.append(getScirptHeader()); - sb.append(getEnvironmentDef(baseDir, scenarioDir, simY,ndepValue)); - sb.append(getRunDef(cropNames, cropIDs)); + String scriptContent = null; + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + if (qcmd == null || qcmd.trim().isEmpty()){ + //no batch system + sb.append(getScirptHeader()); + sb.append(getEnvironmentDef(baseDir, scenarioDir, simY, simEndY, simNY, ndepValue)); + sb.append(getRunDef(cropNames, cropIDs)); + scriptContent = sb.toString(); + } else { + //assume batch system that supports job arrays (SLURM, PBS, LSF, etc) + //create job array script + scriptContent = createArrayTaskScript(baseDir, scenarioDir, simY, simEndY, simNY, ndepValue, + cropNames, cropIDs); + } - String mesg = ""; + // create submit script + writeScriptFile(file, scriptContent); + + return file; + } + + //This is legacy code that has been moved to it's own method + protected void writeScriptFile( String file, String content){ + String mesg = ""; try { File script = new File(file); BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); + out.write(content); out.close(); mesg += "Created a script file: " + file + "\n"; @@ -257,12 +316,173 @@ protected String writeRunScript( String baseDir, String scenarioDir, } catch (IOException e) { //printStackTrace(); //g.error("Error generating EPIC script file", e); - throw new Exception(e.getMessage()); +// throw new Exception(e.getMessage()); + app.showMessage("Write script", e.getMessage()); } app.showMessage("Write script", mesg); - - return file; + } + + protected String writeBatchFile(String jobFile, String scenarioDir) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String batchFile = scenarioDir.trim() + "/scripts"; + if (!batchFile.endsWith(System.getProperty("file.separator"))) + batchFile += System.getProperty("file.separator"); + batchFile += "submitEpicApp" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh" + ls + ls); + + // TODO - add #SBATCH options here + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage == null || qSingModule.trim().isEmpty()) { + throw new Exception("Singularity image path must be specified"); + } + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + jobFile); + } else { + sb.append(jobFile); + } + + writeScriptFile(batchFile, sb.toString()); + + return batchFile; + } + + // returns comma separated list of chosen crop numbers to run + private String getChosenCropNums() throws Exception{ + String[] seCrops = cropSelectionPanel.getSelectedCrops(); + if ( seCrops == null || seCrops.length == 0) + throw new Exception( "Please select crop(s) first!"); + String crop = null; + String cropIDs = ""; + for (int i=0; i0 ) - this.scenarioDir.setText(scenloc); - else - this.scenarioDir.setText(fields.getScenarioDir()); - runMessages.setText(fields.getMessage()); - nDepSel.setSelectedItem(fields.getNDepDir()); - co2Factor.setText(fields.getCO2Fac()==null? "380.00":fields.getCO2Fac()); - runTiledrain.setSelectedItem(fields.getRunTiledrain()==null?"NO":fields.getRunTiledrain()); - }else{ - newProjectCreated(); - } - - } - - public void saveProjectRequested() { - if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); - if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); - if ( runMessages != null ) fields.setMessage(runMessages.getText()); - if ( nDepSel != null ) fields.setNDepDir( (String) nDepSel.getSelectedItem()); - if ( co2Factor != null) fields.setCO2Fac(co2Factor.getText()); - if ( runTiledrain != null ) fields.setRunTiledrain((String) runTiledrain.getSelectedItem()); - if ( runMessages != null ) fields.setMessage(runMessages.getText().trim()); - } - - @Override - public void newProjectCreated() { - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - scenarioDir.setText(domain.getScenarioDir()); - nDepSel.setSelectedIndex(1); - runMessages.setText(""); - co2Factor.setText("380.00"); - runTiledrain.setSelectedIndex(1); - if ( fields == null ) { - fields = new EpicSpinupFields(); - app.getProject().addPage(fields); - } - } - -} +package gov.epa.festc.gui; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.core.proj.DomainFields; +import gov.epa.festc.core.proj.EpicSpinupFields; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.FileRunner; +import gov.epa.festc.util.SpringLayoutGenerator; + +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SpringLayout; +import javax.swing.SwingConstants; + +import simphony.util.messages.MessageCenter; + +public class EpicSpinupPanel extends UtilFieldsPanel implements PlotEventListener { + + private static final long serialVersionUID = -625272283986456313L; + private JTextField scenarioDir; + private FestcApplication app; + + private CropSelectionPanel cropSelectionPanel; + + private MessageCenter msg; + + private String baseDir = null; + private String epicVer = null; + + private EpicSpinupFields fields; + //private DomainFields domain; + + private JComboBox nDepSel; + private JComboBox runTiledrain; + private JComboBox outputFormat; + private JTextField co2Factor; + + public EpicSpinupPanel(FestcApplication application) { + app = application; + fields = new EpicSpinupFields(); + app.getProject().addPage(fields); + msg = app.getMessageCenter(); + baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + epicVer = Constants.getProperty(Constants.EPIC_VER, msg).trim(); + app.addPlotListener(this); + add(createPanel()); + } + + public void setMessageCenter(MessageCenter msgCtr) { + msg = msgCtr; + } + + private JPanel createPanel() { + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + mainPanel.add(getNorthPanel()); + mainPanel.add(getCenterPanel()); + + mainPanel.add(cropsPanel()); + mainPanel.add(messageBox()); + return mainPanel; + } + + private JPanel getNorthPanel() { + JPanel panel = new JPanel(); + JLabel title = new JLabel(Constants.EPIC_SPINUP, SwingConstants.CENTER); + title.setFont(new Font("Default", Font.BOLD, 20)); + + panel.add(title); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + + return panel; + } + + private JPanel getCenterPanel() { + //JPanel centerPanel = new JPanel(); + + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + + this.scenarioDir = new JTextField(40); + + nDepSel = new JComboBox(Constants.SU_NDEPS); + nDepSel.setSelectedIndex(2); + nDepSel.setToolTipText("RFN0: get NDep value from EPICCONT.DAT. "); + + co2Factor = new JTextField(20); + //co2Factor.setToolTipText("Default value is 413.00"); + + runTiledrain = new JComboBox(new String[] {"YES", "NO"}); + runTiledrain.setSelectedIndex(1); + + outputFormat = new JComboBox(new String[] {"Text & NetCDF", "NetCDF only", "Text only"}); + outputFormat.setSelectedIndex(2); + + layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDir, panel); + layout.addLabelWidgetPair("CO2 Level (ppm): ", co2Factor, panel); + layout.addLabelWidgetPair("Daily Average N Deposition: ", nDepSel, panel); + layout.addLabelWidgetPair("Run Tiledrain : ", runTiledrain, panel); + layout.addLabelWidgetPair("Output Format : ", outputFormat, panel); + layout.makeCompactGrid(panel, 5, 2, // number of rows and cols + 10, 10, // initial X and Y + 5, 5); // x and y pading + + return panel; + } + + + private JPanel cropsPanel(){ + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + JPanel buttonPanel = new JPanel(); + JButton btn = new JButton(runAction()); + btn.setPreferredSize(new Dimension(100,50)); + buttonPanel.add(btn); + buttonPanel.setBorder(BorderFactory.createEmptyBorder(70, 30, 70, 30)); + + this.cropSelectionPanel = new CropSelectionPanel(app); + layout.addWidgetPair(cropSelectionPanel, buttonPanel, panel); + layout.makeCompactGrid(panel, 1, 2, // number of rows and cols + 10, 10, // initial X and Y + 5, 5); // x and y pading + return panel; + } + + + private Action runAction() { + return new AbstractAction("Run") { + private static final long serialVersionUID = 5558465823154735475L; + + public void actionPerformed(ActionEvent e) { + try { + + generateRunScript(); + + } catch (Exception exc) { + //msg.error("ERROR", exc); + app.showMessage("Run script", exc.getMessage()); + } + } + }; + } + + private void generateRunScript() throws Exception { + + String baseDir = this.baseDir; + if ( baseDir == null || baseDir.isEmpty()) + throw new Exception( "Base dir is empty, please specify in the configuration file!"); + + String scenarioDir = this.scenarioDir.getText(); + if ( scenarioDir == null || scenarioDir.isEmpty()) + throw new Exception( "Please select scenario dir first!"); + + String co2Fac = co2Factor.getText(); + if (co2Fac == null || co2Fac.isEmpty()) + throw new Exception("co2 Level is not specified!"); + + String ndepValue = (String) this.nDepSel.getSelectedItem(); + if ( ndepValue == null || ndepValue.isEmpty()) + throw new Exception( "Deposition dir is empty, please specify it!"); + + try { + Float.parseFloat(co2Fac); + }catch(NumberFormatException e) { + throw new Exception("CO2 Level is not a number!"); + } + + String seCropsString = cropSelectionPanel.selectedItemTostring(); + String[] seCrops = cropSelectionPanel.getSelectedCrops(); + if ( seCrops == null || seCrops.length == 0) + throw new Exception( "Please select crop(s) first!"); + + + String crop = null; + String cropIDs = "("; + for (int i=0; i0 ) + this.scenarioDir.setText(scenloc); + else + this.scenarioDir.setText(fields.getScenarioDir()); + runMessages.setText(fields.getMessage()); + nDepSel.setSelectedItem(fields.getNDepDir()); + co2Factor.setText(fields.getCO2Fac()==null? "380.00":fields.getCO2Fac()); + runTiledrain.setSelectedItem(fields.getRunTiledrain()==null?"NO":fields.getRunTiledrain()); + }else{ + newProjectCreated(); + } + + } + + public void saveProjectRequested() { + if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); + if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); + if ( runMessages != null ) fields.setMessage(runMessages.getText()); + if ( nDepSel != null ) fields.setNDepDir( (String) nDepSel.getSelectedItem()); + if ( co2Factor != null) fields.setCO2Fac(co2Factor.getText()); + if ( runTiledrain != null ) fields.setRunTiledrain((String) runTiledrain.getSelectedItem()); + if ( runMessages != null ) fields.setMessage(runMessages.getText().trim()); + } + + @Override + public void newProjectCreated() { + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + scenarioDir.setText(domain.getScenarioDir()); + nDepSel.setSelectedIndex(1); + runMessages.setText(""); + co2Factor.setText("380.00"); + runTiledrain.setSelectedIndex(1); + if ( fields == null ) { + fields = new EpicSpinupFields(); + app.getProject().addPage(fields); + } + } + +} diff --git a/festc_core/src/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel.java b/festc_core/src/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel.java index e967444..03ed5f0 100644 --- a/festc_core/src/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel.java +++ b/festc_core/src/gov/epa/festc/gui/EpicYearlyAverage2CMAQPanel.java @@ -44,14 +44,14 @@ public class EpicYearlyAverage2CMAQPanel extends UtilFieldsPanel implements Plot private FestcApplication app; private static final String indent = " "; private EpicYearlyAverage2CMAQFields fields; - + private JRadioButton applicationBtn, spinupBtn; private boolean spinup = false; private JTextField beld4Dir; private JButton beld4DirBrowser; private String ls = "\n"; - //private JCheckBox swatDayBox; - + // private JCheckBox swatDayBox; + public EpicYearlyAverage2CMAQPanel(FestcApplication festcApp) { app = festcApp; msg = app.getMessageCenter(); @@ -60,7 +60,7 @@ public EpicYearlyAverage2CMAQPanel(FestcApplication festcApp) { app.addPlotListener(this); add(createPanel()); } - + private JPanel createPanel() { init(); JPanel mainPanel = new JPanel(); @@ -71,10 +71,11 @@ private JPanel createPanel() { mainPanel.add(messageBox()); return mainPanel; } - + private JPanel getNorthPanel() { JPanel panel = new JPanel(); - JLabel title = new JLabel(Constants.EPIC_YEAR, // Yearly Average for CMAQ", + JLabel title = new JLabel(Constants.EPIC_YEAR, // Yearly Average for + // CMAQ", SwingConstants.CENTER); title.setFont(new Font("Default", Font.BOLD, 20)); @@ -83,43 +84,43 @@ private JPanel getNorthPanel() { return panel; } - + private JPanel getCenterPanel() { JPanel spinupPanel = new JPanel(); - this.applicationBtn = new JRadioButton(applicationSelection()); - this.spinupBtn = new JRadioButton(spinupSelection()); + this.applicationBtn = new JRadioButton(applicationSelection()); + this.spinupBtn = new JRadioButton(spinupSelection()); this.applicationBtn.setSelected(true); this.spinupBtn.setSelected(false); spinupPanel.add(this.spinupBtn); spinupPanel.add(this.applicationBtn); - + ButtonGroup btnGroup = new ButtonGroup(); btnGroup.add(this.spinupBtn); btnGroup.add(this.applicationBtn); - + JPanel beld4DirPanel = new JPanel(); beld4Dir = new JTextField(40); beld4Dir.setToolTipText("I.E. share_data/beld4_cmaq12km_2001.nc"); - + beld4DirBrowser = new JButton(BrowseAction.browseAction(this, app.getCurrentDir(), "BELD4 file", beld4Dir)); beld4DirPanel.add(beld4Dir); - beld4DirPanel.add(beld4DirBrowser); - + beld4DirPanel.add(beld4DirBrowser); + JPanel panel = new JPanel(new SpringLayout()); SpringLayoutGenerator layout = new SpringLayoutGenerator(); - -// JPanel swatPanel = new JPanel(); -// this.swatDayBox = new JCheckBox("Daily", true); -// swatPanel.add(this.swatDayBox); - + + // JPanel swatPanel = new JPanel(); + // this.swatDayBox = new JCheckBox("Daily", true); + // swatPanel.add(this.swatDayBox); + layout.addLabelWidgetPair("Grid Description:", getGridDescPanel(false), panel); layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); layout.addLabelWidgetPair("BELD4 NetCDF File: ", beld4DirPanel, panel); - //layout.addLabelWidgetPair(" ", new JLabel(" "), panel); + // layout.addLabelWidgetPair(" ", new JLabel(" "), panel); layout.addLabelWidgetPair(indent + "Output Type:", spinupPanel, panel); - //layout.addLabelWidgetPair(" ", new JLabel(" "), panel); - //layout.addLabelWidgetPair(" For Swat Inputs:", swatPanel, panel); - //layout.addLabelWidgetPair(" ", new JLabel(" "), panel); + // layout.addLabelWidgetPair(" ", new JLabel(" "), panel); + // layout.addLabelWidgetPair(" For Swat Inputs:", swatPanel, panel); + // layout.addLabelWidgetPair(" ", new JLabel(" "), panel); layout.makeCompactGrid(panel, 4, 2, // number of rows and cols 10, 10, // initial X and Y @@ -127,35 +128,33 @@ private JPanel getCenterPanel() { return panel; } - + private Action applicationSelection() { return new AbstractAction("EPIC APP") { public void actionPerformed(ActionEvent e) { processSelec(); } - + }; } - + private Action spinupSelection() { return new AbstractAction("EPIC SPINUP") { public void actionPerformed(ActionEvent e) { processSelec(); } - + }; } - + private void processSelec() { - if ( applicationBtn.isSelected()) { + if (applicationBtn.isSelected()) { spinup = false; } else { spinup = true; } } - - private JPanel getSouthPanel() { JPanel panel = new JPanel(); JButton display = new JButton(runAction()); @@ -165,7 +164,7 @@ private JPanel getSouthPanel() { return panel; } - + private Action runAction() { return new AbstractAction("Run") { private static final long serialVersionUID = 8573618661168062193L; @@ -180,133 +179,215 @@ public void actionPerformed(ActionEvent e) { } }; } - + private void generateRunScript() throws Exception { String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - if (baseDir == null || baseDir.isEmpty()) + if (baseDir == null || baseDir.isEmpty()) throw new Exception("Base dir is empty, please specify it in the configuration file!"); - + String scenarioDir = this.scenarioDir.getText(); - if ( scenarioDir == null || scenarioDir.isEmpty()) + if (scenarioDir == null || scenarioDir.isEmpty()) throw new Exception("Please select scenario dir first!"); - + File beld4F = new File(this.beld4Dir.getText()); - if (beld4F == null || beld4F.isDirectory() || ! beld4F.exists()) - throw new Exception("Beld4 file is not existing!"); - + if (beld4F == null || beld4F.isDirectory() || !beld4F.exists()) + throw new Exception("Beld4 file is not existing!"); + validateGrids(); - + String sahome = Constants.getProperty(Constants.SA_HOME, msg); - if (sahome == null || sahome.trim().isEmpty() || !(new File(sahome).exists())) - throw new Exception("SA dir is empty, please specify it in the configuration file!"); - - outMessages += "Epic base: " + baseDir + ls; + // if (sahome == null || sahome.trim().isEmpty() || !(new + // File(sahome).exists())) + if (sahome == null) + throw new Exception("SA dir is empty, please specify it in the configuration file!"); + + outMessages += "Epic base: " + baseDir + ls; outMessages += "SA home: " + sahome + ls; - - final String file = writeRunScript(baseDir, scenarioDir, sahome); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + + final String jobFile = writeRunScript(baseDir, scenarioDir, sahome); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir); + } else { + batchFile = null; + } Thread populateThread = new Thread(new Runnable() { public void run() { - runScript(file); + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile); + } } }); populateThread.start(); } - protected String writeRunScript( - String baseDir, - String scenarioDir, - String sahome ) throws Exception { - - Date now = new Date(); // java.util.Date, NOT java.sql.Date or java.sql.Timestamp! - String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - String file = scenarioDir.trim() + "/scripts"; - - if (spinup) - file = file.trim() + "/epicYearlyAverage2CMAQ_spinup" + timeStamp + ".csh"; + // This is legacy code that has been moved to it's own method + protected void writeScriptFile(String file, String content) { + + String mesg = ""; + + try { + File script = new File(file); + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(content); + out.close(); + + mesg += "Script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + + } catch (IOException e) { + // printStackTrace(); + // g.error("Error generating EPIC script file", e); + app.showMessage("Write script", e.getMessage()); + } + + app.showMessage("Write script", mesg); + } + + protected String writeRunScript(String baseDir, String scenarioDir, String sahome) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String file = scenarioDir.trim() + "/scripts"; + + if (spinup) + file = file.trim() + "/epicYearlyAverage2CMAQ_spinup" + timeStamp + ".csh"; else file = file.trim() + "/epicYearlyAverage2CMAQ_app" + timeStamp + ".csh"; - + StringBuilder sb = new StringBuilder(); - + sb.append(getScriptHeader() + ls); sb.append("#" + ls + "# Set up runtime environment" + ls + "#" + ls); sb.append("setenv EPIC_DIR " + baseDir + ls); sb.append("setenv SCEN_DIR " + scenarioDir + ls); - sb.append("setenv SA_HOME " + sahome +ls); - sb.append("source $SA_HOME/"+ Constants.SA_SETUP_FILE + ls + ls); + sb.append("setenv SA_HOME " + sahome + ls); + sb.append("source $SA_HOME/" + Constants.SA_SETUP_FILE + ls + ls); sb.append("#" + ls + "# Define domain grids" + ls + "#" + ls); sb.append("setenv GRID_PROJ \"" + proj4proj.getText().trim() + "\"" + ls + ls); - sb.append("setenv GRID_ROWS " + ((Number)rows.getValue()).intValue() + ls); - sb.append("setenv GRID_COLUMNS " + ((Number)cols.getValue()).intValue() + ls + ls); - sb.append("setenv GRID_XMIN " + ((Number)xmin.getValue()).doubleValue() + ls); - sb.append("setenv GRID_YMIN " + ((Number)ymin.getValue()).doubleValue() + ls + ls); - sb.append("setenv GRID_XCELLSIZE " + ((Number)xSize.getValue()).doubleValue() + ls); - sb.append("setenv GRID_YCELLSIZE " + ((Number)ySize.getValue()).doubleValue() + ls + ls); - sb.append("setenv GRID_NAME \"" + (gridName.getText() == null ? "" : gridName.getText().trim()) + "\"" + ls + ls); - sb.append("#" + ls - + "# set EPIC output file directory which containts each day data" + ls - + "#" + ls); - - if (spinup) - sb.append("setenv DATA_DIR $SCEN_DIR/output4CMAQ/spinup/5years/" + ls + ls); - else - sb.append("setenv DATA_DIR $SCEN_DIR/output4CMAQ/app/year/" + ls + ls); - - sb.append("# Define BELD4 input file" + ls ); + sb.append("setenv GRID_ROWS " + ((Number) rows.getValue()).intValue() + ls); + sb.append("setenv GRID_COLUMNS " + ((Number) cols.getValue()).intValue() + ls + ls); + sb.append("setenv GRID_XMIN " + ((Number) xmin.getValue()).doubleValue() + ls); + sb.append("setenv GRID_YMIN " + ((Number) ymin.getValue()).doubleValue() + ls + ls); + sb.append("setenv GRID_XCELLSIZE " + ((Number) xSize.getValue()).doubleValue() + ls); + sb.append("setenv GRID_YCELLSIZE " + ((Number) ySize.getValue()).doubleValue() + ls + ls); + sb.append("setenv GRID_NAME \"" + (gridName.getText() == null ? "" : gridName.getText().trim()) + "\"" + ls + + ls); + + sb.append("# Define BELD4 input file" + ls); sb.append("setenv DOMAIN_BELD4_NETCDF " + beld4Dir.getText() + ls + ls); - sb.append("#" + ls - + "# Output file:" + ls - + "#" + ls); + sb.append("# Process multiple years" + ls); + sb.append("set SIM_YEAR=\"$SCEN_DIR/output4CMAQ/app/[1-2][0-9][0-9][0-9]\"" +ls); + sb.append("foreach MULTI_YEAR_DIR ($SIM_YEAR)" + ls); + sb.append(" set MULTI_YEAR=`basename $MULTI_YEAR_DIR`" + ls); + sb.append(" setenv SIM_YEAR $MULTI_YEAR" + ls); + sb.append(" #" + ls + " # set EPIC output file directory which containts each day data" + ls + " #" + ls); if (spinup) - sb.append("setenv OUTPUT_NETCDF_FILE $SCEN_DIR/output4CMAQ/spinup/toCMAQ/epic2cmaq_year.nc" + ls + ls); + sb.append(" setenv DATA_DIR $SCEN_DIR/output4CMAQ/spinup/${MULTI_YEAR}/year/" + ls); + else + sb.append(" setenv DATA_DIR $SCEN_DIR/output4CMAQ/app/${MULTI_YEAR}/year/" + ls + ls); + + sb.append(" #" + ls + " # Output file:" + ls + " #" + ls); + if (spinup) + sb.append(" setenv OUTPUT_NETCDF_FILE $SCEN_DIR/output4CMAQ/spinup/toCMAQ/epic2cmaq_year.nc" + ls + ls); else - sb.append("setenv OUTPUT_NETCDF_FILE $SCEN_DIR/output4CMAQ/app/toCMAQ/epic2cmaq_year.nc" + ls + ls); - - sb.append("#Total from all crops" + ls ); + sb.append(" setenv OUTPUT_NETCDF_FILE $SCEN_DIR/output4CMAQ/app/${MULTI_YEAR}/toCMAQ/epic2cmaq_year.nc" + ls + ls); + + sb.append(" #Total from all crops" + ls); if (spinup) - sb.append("setenv OUTPUT_NETCDF_FILE_TOTAL " + - "$SCEN_DIR/output4CMAQ/spinup/toCMAQ/epic2cmaq_year_total.nc" + ls + ls); + sb.append(" setenv OUTPUT_NETCDF_FILE_TOTAL " + "$SCEN_DIR/output4CMAQ/spinup/toCMAQ/epic2cmaq_year_total.nc" + + ls + ls); else - sb.append("setenv OUTPUT_NETCDF_FILE_TOTAL " + - "$SCEN_DIR/output4CMAQ/app/toCMAQ/epic2cmaq_year_total.nc" + ls + ls); - - - sb.append("#" + ls - + "# run the EPIC output processing program:" + ls - + "#" + ls); - sb.append("$SA_HOME/bin/64bits/extractEPICYearlyAverage2CMAQ.exe" + ls + ls); - -// Boolean swatDayYN = swatDayBox.isSelected()? true : false; -// System.out.println(swatDayYN); -// if (swatDayYN) sb.append(getScriptDaySwat()); - + sb.append(" setenv OUTPUT_NETCDF_FILE_TOTAL " + "$SCEN_DIR/output4CMAQ/app/${MULTI_YEAR}/toCMAQ/epic2cmaq_year_total.nc" + + ls + ls); + + sb.append(" #" + ls + " # run the EPIC output processing program:" + ls + " #" + ls); + sb.append(" $SA_HOME/bin/64bits/extractEPICYearlyAverage2CMAQ.exe" + ls); + sb.append("end"+ls); + + // Boolean swatDayYN = swatDayBox.isSelected()? true : false; + // System.out.println(swatDayYN); + // if (swatDayYN) sb.append(getScriptDaySwat()); + sb.append("#===================================================================" + ls); String mesg = ""; try { File script = new File(file); Runtime.getRuntime().exec("chmod 755 " + script.getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - mesg += "Created a script file: " + file + ls; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - } catch (IOException e) { - throw new Exception( e.getMessage()); - } + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + mesg += "Created a script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + } catch (IOException e) { + throw new Exception(e.getMessage()); + } app.showMessage("Write script", mesg); return file; } + protected String writeBatchFile(String jobFile, String scenarioDir) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String batchFile = scenarioDir.trim() + "/scripts"; + if (!batchFile.endsWith(System.getProperty("file.separator"))) + batchFile += System.getProperty("file.separator"); + batchFile += "submitEpicYearlyAverage2CMAQ"; + if (spinup) + batchFile += "submitEpicYearlyAverage2CMAQ_spinup" + timeStamp + ".csh"; + else + batchFile += "submitEpicYearlyAverage2CMAQ_app" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh" + ls + ls); + + // TODO - add #SBATCH options here + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage == null || qSingModule.trim().isEmpty()) { + throw new Exception("Singularity image path must be specified"); + } + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + jobFile); + } else { + sb.append(jobFile); + } + + writeScriptFile(batchFile, sb.toString()); + + return batchFile; + } + + private String getScriptHeader() { StringBuilder sb = new StringBuilder(); String ls = "\n"; sb.append("#!/bin/csh -f" + ls); sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to process EPIC modeling yearly average output for CMAQ bi-directional" + ls); - sb.append("# ammonia surface flux modeling" + ls); + sb.append("# Purpose: to process EPIC modeling yearly average output for CMAQ bi-directional" + ls); + sb.append("# ammonia surface flux modeling" + ls); sb.append("#" + ls); sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); sb.append("# in support of the EPA CMAS project, 2010." + ls); @@ -314,74 +395,93 @@ private String getScriptHeader() { sb.append("# Written by: L. R., NOV. 2010" + ls); sb.append("#" + ls); sb.append("# Call program: epicYearlyAverage2CMAQ.exe" + ls); - sb.append("# Needed environment variables included in the script file to run." + ls); - sb.append("#" + ls); + sb.append("# Needed environment variables included in the script file to run." + ls); + sb.append("#" + ls); sb.append("#***************************************************************************************" + ls + ls); - + return sb.toString(); } - + private String getScriptDaySwat() { StringBuilder sb = new StringBuilder(); String ls = "\n"; sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: Prepare inputs for SWAT by summarizing data to regions" + ls); - sb.append("# from the extracted EPIC *NCD output file:" + ls); - sb.append("#" + ls); + sb.append("# Purpose: Prepare inputs for SWAT by summarizing data to regions" + ls); + sb.append("# from the extracted EPIC *NCD output file:" + ls); + sb.append("#" + ls); sb.append("#***************************************************************************************" + ls + ls); - + sb.append("#" + ls); sb.append("# Define output type and simulation year" + ls); sb.append("#" + ls); - - String year = domain.getSimYear(); - if ( spinup ) - sb.append("setenv TYPE \"spinup\"" +ls ); + + String year = domain.getSimYear(); + if (spinup) + sb.append("setenv TYPE \"spinup\"" + ls); else - sb.append("setenv TYPE \"app\"" +ls); - sb.append("setenv YEAR "+ year +ls +ls); - - sb.append("setenv DATA_DIR $SCEN_DIR/output4CMAQ/$TYPE/daily/" + ls +ls ); - - sb.append("# Crop fraction data" +ls ); - sb.append("setenv SITEFILE ${SCEN_DIR}/share_data/EPICSites_Info.csv" +ls ); - - sb.append("# set crops in the summary" +ls ); - sb.append("#setenv CROPS \"BARLEY\"" +ls ); - sb.append("setenv CROPS \"ALL\"" +ls +ls); - - sb.append("# set output file" +ls ); - sb.append("if ( ! -e $DATA_DIR/swat ) mkdir -p $DATA_DIR/swat" +ls ); - sb.append("setenv OUTFILE $DATA_DIR/swat/HUC8_" +ls +ls); - - sb.append("echo \"Run daily summary for swat: \" ${SCEN_DIR}" +ls ); - - sb.append("R CMD BATCH --no-save --slave " - + "$EPIC_DIR/util/misc/swat/epic2swat_daily_HUC8.R " - + "${SCEN_DIR}/scripts/epic2swat_daily_HUC8.log" +ls +ls); + sb.append("setenv TYPE \"app\"" + ls); + sb.append("setenv YEAR " + year + ls + ls); + + sb.append("setenv DATA_DIR $SCEN_DIR/output4CMAQ/$TYPE/daily/" + ls + ls); + + sb.append("# Crop fraction data" + ls); + sb.append("setenv SITEFILE ${SCEN_DIR}/share_data/EPICSites_Info.csv" + ls); + + sb.append("# set crops in the summary" + ls); + sb.append("#setenv CROPS \"BARLEY\"" + ls); + sb.append("setenv CROPS \"ALL\"" + ls + ls); + + sb.append("# set output file" + ls); + sb.append("if ( ! -e $DATA_DIR/swat ) mkdir -p $DATA_DIR/swat" + ls); + sb.append("setenv OUTFILE $DATA_DIR/swat/HUC8_" + ls + ls); + + sb.append("echo \"Run daily summary for swat: \" ${SCEN_DIR}" + ls); + + sb.append("R CMD BATCH --no-save --slave " + "$EPIC_DIR/util/misc/swat/epic2swat_daily_HUC8.R " + + "${SCEN_DIR}/scripts/epic2swat_daily_HUC8.log" + ls + ls); return sb.toString(); } - + private void runScript(final String file) { String log = file + ".log"; - + outMessages += "Script file: " + file + ls; outMessages += "Log file: " + log + ls; runMessages.setText(outMessages); runMessages.validate(); FileRunner.runScript(file, log, msg); - } + } + + private void runBatchScript(final String batchFile, final String jobFile) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qYearlyExt = Constants.getProperty(Constants.QUEUE_YEARLY_EXT, msg); + + File script = new File(batchFile.replaceAll("\\\\", "\\\\\\\\")); + + sb.append(qcmd + " " + qYearlyExt + " -o " + log + " " + script.getAbsolutePath()); + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } @Override public void projectLoaded() { - fields = (EpicYearlyAverage2CMAQFields)app.getProject().getPage(fields.getName()); + fields = (EpicYearlyAverage2CMAQFields) app.getProject().getPage(fields.getName()); domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - if ( fields != null ){ + if (fields != null) { String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length()>0 ) + if (scenloc != null && scenloc.trim().length() > 0) this.scenarioDir.setText(scenloc); - else + else this.scenarioDir.setText(fields.getScenarioDir()); rows.setValue(fields.getRows()); cols.setValue(fields.getCols()); @@ -393,52 +493,63 @@ public void projectLoaded() { gridName.setText(fields.getGridName()); runMessages.setText(fields.getMessage()); - if ((fields.getBeld4ncf()==null || fields.getBeld4ncf().trim().isEmpty() )) { + if ((fields.getBeld4ncf() == null || fields.getBeld4ncf().trim().isEmpty())) { String scenDir = fields.getScenarioDir().trim(); - String gridName = fields.getGridName().trim(); + String gridName = fields.getGridName().trim(); String year = fields.getNlcdYear().trim(); - String beld4file = scenDir + "/share_data/beld4_" + gridName + "_" + year +".nc"; - //System.out.println(beld4file); -// File f = new File(beld4file); -// if(f.exists()){ - this.beld4Dir.setText(beld4file); -// } -// else -// this.beld4Dir.setText(scenDir); - } - else - this.beld4Dir.setText( fields.getBeld4ncf()); + String beld4file = scenDir + "/share_data/beld4_" + gridName + "_" + year + ".nc"; + // System.out.println(beld4file); + // File f = new File(beld4file); + // if(f.exists()){ + this.beld4Dir.setText(beld4file); + // } + // else + // this.beld4Dir.setText(scenDir); + } else + this.beld4Dir.setText(fields.getBeld4ncf()); - }else { + } else { newProjectCreated(); } } @Override public void saveProjectRequested() { - if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); - if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); - if ( rows != null ) fields.setRows(Integer.parseInt(rows.getText() == null? "" : rows.getValue()+"")); - if ( cols != null ) fields.setCols(Integer.parseInt(cols.getText() == null? "" : cols.getValue()+"")); - if ( xSize != null ) fields.setXcellSize(Float.parseFloat(xSize.getText() == null? "" : xSize.getValue()+"")); - if ( ySize != null ) fields.setYcellSize(Float.parseFloat(ySize.getText() == null? "" : ySize.getValue()+"")); - if ( xmin != null ) fields.setXmin(Float.parseFloat(xmin.getText() == null? "" : xmin.getValue()+"")); - if ( ymin != null ) fields.setYmin(Float.parseFloat(ymin.getText() == null? "" : ymin.getValue()+"")); - if ( proj4proj != null ) fields.setProj(proj4proj.getText() == null? "" : proj4proj.getText()); - if ( gridName != null ) fields.setGridName(gridName.getText()== null? "" : gridName.getText()); - - if ( runMessages != null ) fields.setMessage(runMessages.getText()); - if ( beld4Dir != null ) fields.setBeld4ncf(beld4Dir.getText()== null? "" : beld4Dir.getText()); + if (scenarioDir != null) + domain.setScenarioDir(scenarioDir.getText()); + if (scenarioDir != null) + fields.setScenarioDir(scenarioDir.getText()); + if (rows != null) + fields.setRows(Integer.parseInt(rows.getText() == null ? "" : rows.getValue() + "")); + if (cols != null) + fields.setCols(Integer.parseInt(cols.getText() == null ? "" : cols.getValue() + "")); + if (xSize != null) + fields.setXcellSize(Float.parseFloat(xSize.getText() == null ? "" : xSize.getValue() + "")); + if (ySize != null) + fields.setYcellSize(Float.parseFloat(ySize.getText() == null ? "" : ySize.getValue() + "")); + if (xmin != null) + fields.setXmin(Float.parseFloat(xmin.getText() == null ? "" : xmin.getValue() + "")); + if (ymin != null) + fields.setYmin(Float.parseFloat(ymin.getText() == null ? "" : ymin.getValue() + "")); + if (proj4proj != null) + fields.setProj(proj4proj.getText() == null ? "" : proj4proj.getText()); + if (gridName != null) + fields.setGridName(gridName.getText() == null ? "" : gridName.getText()); + + if (runMessages != null) + fields.setMessage(runMessages.getText()); + if (beld4Dir != null) + fields.setBeld4ncf(beld4Dir.getText() == null ? "" : beld4Dir.getText()); } @Override public void newProjectCreated() { domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - + String scenDir = domain.getScenarioDir().trim(); - String gName = domain.getGridName().trim(); + String gName = domain.getGridName().trim(); String nlcdY = domain.getNlcdYear().trim(); - scenarioDir.setText(scenDir); + scenarioDir.setText(scenDir); rows.setValue(domain.getRows()); cols.setValue(domain.getCols()); xmin.setValue(domain.getXmin()); @@ -447,17 +558,17 @@ public void newProjectCreated() { ySize.setValue(domain.getYcellSize()); proj4proj.setText(domain.getProj()); gridName.setText(domain.getGridName()); - - String beld4file = scenDir + "/share_data/beld4_" + gName + "_" + nlcdY +".nc"; -// File f = new File(beld4file); -// if(f.exists()){ - this.beld4Dir.setText(beld4file); -// } -// else -// this.beld4Dir.setText(scenDir); - + + String beld4file = scenDir + "/share_data/beld4_" + gName + "_" + nlcdY + ".nc"; + // File f = new File(beld4file); + // if(f.exists()){ + this.beld4Dir.setText(beld4file); + // } + // else + // this.beld4Dir.setText(scenDir); + runMessages.setText(""); - if ( fields == null ) { + if (fields == null) { fields = new EpicYearlyAverage2CMAQFields(); app.getProject().addPage(fields); } diff --git a/festc_core/src/gov/epa/festc/gui/HelpWindowWithContents.java b/festc_core/src/gov/epa/festc/gui/HelpWindowWithContents.java index 02f066c..82a2b7d 100644 --- a/festc_core/src/gov/epa/festc/gui/HelpWindowWithContents.java +++ b/festc_core/src/gov/epa/festc/gui/HelpWindowWithContents.java @@ -1,156 +1,156 @@ -package gov.epa.festc.gui; - -import anl.gui.window.dialog.OKWindow; - -import javax.swing.*; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; -import java.awt.*; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.IOException; -import java.net.URL; - -public class HelpWindowWithContents extends OKWindow { - private static final long serialVersionUID = -3954828275072932197L; - - JEditorPane editorPaneLeft, editorPaneRight; - - public HelpWindowWithContents(Dialog dialog, String title, String doc, - String doc2) { - super(dialog, title, false); - inits(doc, doc2); - } - - public HelpWindowWithContents(Frame frame, String title, String doc, - String doc2) { - // super(fr.getFrame(),title,state); - super(frame, title, false); - inits(doc, doc2); - } - - public void inits(String doc, String doc2) { - Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); - - JSplitPane splitPanel = new JSplitPane(); - splitPanel.setBorder(new javax.swing.border.EtchedBorder()); - - editorPaneLeft = new JEditorPane(); - editorPaneLeft.setEditable(false); - editorPaneLeft.addHyperlinkListener(new HyperlinkListener() { - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - - if (e.getDescription().startsWith("#")) { - // move to the link - editorPaneRight.scrollToReference(e.getDescription() - .substring(1)); - - } - } - } - }); - // JPanel leftPanel = new JPanel(new BorderLayout()); - // leftPanel.add(editorPaneLeft,BorderLayout.CENTER); - - editorPaneRight = new JEditorPane(); - editorPaneRight.setEditable(false); - editorPaneRight.addHyperlinkListener(new HyperlinkListener() { - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - JEditorPane src = (JEditorPane) e.getSource(); - if (e.getDescription().startsWith("#")) { - // move to the link - src.scrollToReference(e.getDescription().substring(1)); - - } - } - } - }); - // JPanel rightPanel = new JPanel(new BorderLayout()); - // rightPanel.add(editorPaneRight,BorderLayout.CENTER); - - JScrollPane editorScrollPaneLeft = new JScrollPane(editorPaneLeft); - editorScrollPaneLeft - .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); - editorScrollPaneLeft.setPreferredSize(new Dimension(200, 300)); - editorScrollPaneLeft.setMinimumSize(new Dimension(200, 300)); - - JScrollPane editorScrollPaneRight = new JScrollPane(editorPaneRight); - editorScrollPaneRight - .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); - editorScrollPaneRight.setPreferredSize(new Dimension(500, 300)); - editorScrollPaneRight.setMinimumSize(new Dimension(300, 100)); - - // setDoc(editorPaneLeft,doc); - setDoc(editorPaneRight, doc2); - setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); - WindowAdapter catchclose = new WindowAdapter() { - public void windowClosing(WindowEvent we) { - dispose(); - } - - // remove this if fixed in JDK 1.3.1 - public void windowActivated(WindowEvent ev) { - ev.getWindow().repaint(); - } - }; - this.addWindowListener(catchclose); - // splitPanel.setLeftComponent(editorScrollPaneLeft); - // splitPanel.setRightComponent(editorScrollPaneRight); - - // getContentPane().add("Center", splitPanel); - getContentPane().add("Center", editorScrollPaneRight); - pack(); - setLocation(100, 100); - setSize(dim.width - 200, dim.height - 200); - validate(); - - // splitPanel.setDividerLocation(0.5); - setVisible(true); - } - - void setDoc(JEditorPane pane, String doc) { - if (doc != null) { - try { - File file = new File(doc); - URL url = file.toURI().toURL(); - pane.setPage(url); - } catch (IOException e) { - e.printStackTrace(); - System.err.println("Attempted to read a bad file: " + doc); - } - } else { - System.err.println("Couldn't find file: " + doc); - } - } - - public boolean doAction() { - return true; - } - - public void dispose() { - window = null; - super.dispose(); - } - - static HelpWindowWithContents window; - - public static void showContents(Window frame, String title, String doc, - String doc2) { - if (window == null) { - if (frame instanceof Dialog) - window = new HelpWindowWithContents((Dialog) frame, title, doc, - doc2); - else - window = new HelpWindowWithContents((Frame) frame, title, doc, - doc2); - } else { - window.setTitle(title); - //window.setDoc(window.editorPaneLeft, doc); - window.setDoc(window.editorPaneRight, doc2); - } - } - -} +package gov.epa.festc.gui; + +import anl.gui.window.dialog.OKWindow; + +import javax.swing.*; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.IOException; +import java.net.URL; + +public class HelpWindowWithContents extends OKWindow { + private static final long serialVersionUID = -3954828275072932197L; + + JEditorPane editorPaneLeft, editorPaneRight; + + public HelpWindowWithContents(Dialog dialog, String title, String doc, + String doc2) { + super(dialog, title, false); + inits(doc, doc2); + } + + public HelpWindowWithContents(Frame frame, String title, String doc, + String doc2) { + // super(fr.getFrame(),title,state); + super(frame, title, false); + inits(doc, doc2); + } + + public void inits(String doc, String doc2) { + Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); + + JSplitPane splitPanel = new JSplitPane(); + splitPanel.setBorder(new javax.swing.border.EtchedBorder()); + + editorPaneLeft = new JEditorPane(); + editorPaneLeft.setEditable(false); + editorPaneLeft.addHyperlinkListener(new HyperlinkListener() { + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + + if (e.getDescription().startsWith("#")) { + // move to the link + editorPaneRight.scrollToReference(e.getDescription() + .substring(1)); + + } + } + } + }); + // JPanel leftPanel = new JPanel(new BorderLayout()); + // leftPanel.add(editorPaneLeft,BorderLayout.CENTER); + + editorPaneRight = new JEditorPane(); + editorPaneRight.setEditable(false); + editorPaneRight.addHyperlinkListener(new HyperlinkListener() { + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + JEditorPane src = (JEditorPane) e.getSource(); + if (e.getDescription().startsWith("#")) { + // move to the link + src.scrollToReference(e.getDescription().substring(1)); + + } + } + } + }); + // JPanel rightPanel = new JPanel(new BorderLayout()); + // rightPanel.add(editorPaneRight,BorderLayout.CENTER); + + JScrollPane editorScrollPaneLeft = new JScrollPane(editorPaneLeft); + editorScrollPaneLeft + .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + editorScrollPaneLeft.setPreferredSize(new Dimension(200, 300)); + editorScrollPaneLeft.setMinimumSize(new Dimension(200, 300)); + + JScrollPane editorScrollPaneRight = new JScrollPane(editorPaneRight); + editorScrollPaneRight + .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + editorScrollPaneRight.setPreferredSize(new Dimension(500, 300)); + editorScrollPaneRight.setMinimumSize(new Dimension(300, 100)); + + // setDoc(editorPaneLeft,doc); + setDoc(editorPaneRight, doc2); + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + WindowAdapter catchclose = new WindowAdapter() { + public void windowClosing(WindowEvent we) { + dispose(); + } + + // remove this if fixed in JDK 1.3.1 + public void windowActivated(WindowEvent ev) { + ev.getWindow().repaint(); + } + }; + this.addWindowListener(catchclose); + // splitPanel.setLeftComponent(editorScrollPaneLeft); + // splitPanel.setRightComponent(editorScrollPaneRight); + + // getContentPane().add("Center", splitPanel); + getContentPane().add("Center", editorScrollPaneRight); + pack(); + setLocation(100, 100); + setSize(dim.width - 200, dim.height - 200); + validate(); + + // splitPanel.setDividerLocation(0.5); + setVisible(true); + } + + void setDoc(JEditorPane pane, String doc) { + if (doc != null) { + try { + File file = new File(doc); + URL url = file.toURI().toURL(); + pane.setPage(url); + } catch (IOException e) { + e.printStackTrace(); + System.err.println("Attempted to read a bad file: " + doc); + } + } else { + System.err.println("Couldn't find file: " + doc); + } + } + + public boolean doAction() { + return true; + } + + public void dispose() { + window = null; + super.dispose(); + } + + static HelpWindowWithContents window; + + public static void showContents(Window frame, String title, String doc, + String doc2) { + if (window == null) { + if (frame instanceof Dialog) + window = new HelpWindowWithContents((Dialog) frame, title, doc, + doc2); + else + window = new HelpWindowWithContents((Frame) frame, title, doc, + doc2); + } else { + window.setTitle(title); + //window.setDoc(window.editorPaneLeft, doc); + window.setDoc(window.editorPaneRight, doc2); + } + } + +} diff --git a/festc_core/src/gov/epa/festc/gui/ListWidget.java b/festc_core/src/gov/epa/festc/gui/ListWidget.java index f10e2d8..7e7f827 100644 --- a/festc_core/src/gov/epa/festc/gui/ListWidget.java +++ b/festc_core/src/gov/epa/festc/gui/ListWidget.java @@ -1,126 +1,126 @@ -package gov.epa.festc.gui; - -import java.util.ArrayList; -import java.util.List; - -import javax.swing.DefaultListModel; -import javax.swing.JList; - - -public class ListWidget extends JList { - - private boolean changed; - - private DefaultListModel model; - - private List indexes; - - public ListWidget(Object[] items) { - model = model(items); - this.setModel(model); - changed = false; - } - - public ListWidget(Object[] items, Object[] selected) { - this(items); - setSelected(selected); - } - - private DefaultListModel model(Object[] items) { - DefaultListModel model = new DefaultListModel(); - if (items != null && items.length >0){ - for (int i = 0; i < items.length; i++) { - model.addElement(items[i]); - } - } - return model; - } - - public void setElements(Object[] items) { - model.removeAllElements(); - if (items != null && items.length >0){ - for (int i = 0; i < items.length; i++) { - model.addElement(items[i]); - } - } - } - - - public void setSelected(Object[] selected) { - indexes = new ArrayList(); - for (int i = 0; i < selected.length; i++) - indexes.add(model.indexOf(selected[i])); - //super.setSelectedIndex(indexes.toArray(new Integer[0])); - } - - public List getSelected() { - return indexes; - } - - public boolean hasChanges() { - return changed; - } - - public void clear() { - changed = false; - } - - public boolean contains(Object obj) { - return model.contains(obj); - } - - public void addElement(Object obj) { - model.addElement(obj); - } - - public void add(int index, Object obj) { - model.add(index, obj); - } - - public void removeElements(Object[] removeValues) { - for (int i = 0; i < removeValues.length; i++) { - model.removeElement(removeValues[i]); - } - } - - public void removeAllElements() { - model.removeAllElements(); -// for (int i = 0; i < model.size(); i++) { -// model.removeElement(model.get(i)); -// } - } - - public String getElement(int index) { - return model.elementAt(index).toString(); -// for (int i = 0; i < model.size(); i++) { -// model.removeElement(model.get(i)); -// } - } - - public void removeSelectedElements() { - - Object [] selectedValues = this.getSelectedValues(); - for (int i = 0; i < selectedValues.length; i++) { - model.removeElement(selectedValues[i]); - } - } - - public String[] getAllElements() { - String[] obj = new String[model.getSize()]; - model.copyInto(obj); - return obj; - } - - //Swap two elements in the list. - public void swap(int a, int b) { - Object aObject = model.getElementAt(a); - Object bObject = model.getElementAt(b); - model.set(a, bObject); - model.set(b, aObject); - } - - public void setModelSize(int modelSize) { - this.model.setSize(modelSize); - this.model.trimToSize(); - } -} +package gov.epa.festc.gui; + +import java.util.ArrayList; +import java.util.List; + +import javax.swing.DefaultListModel; +import javax.swing.JList; + + +public class ListWidget extends JList { + + private boolean changed; + + private DefaultListModel model; + + private List indexes; + + public ListWidget(Object[] items) { + model = model(items); + this.setModel(model); + changed = false; + } + + public ListWidget(Object[] items, Object[] selected) { + this(items); + setSelected(selected); + } + + private DefaultListModel model(Object[] items) { + DefaultListModel model = new DefaultListModel(); + if (items != null && items.length >0){ + for (int i = 0; i < items.length; i++) { + model.addElement(items[i]); + } + } + return model; + } + + public void setElements(Object[] items) { + model.removeAllElements(); + if (items != null && items.length >0){ + for (int i = 0; i < items.length; i++) { + model.addElement(items[i]); + } + } + } + + + public void setSelected(Object[] selected) { + indexes = new ArrayList(); + for (int i = 0; i < selected.length; i++) + indexes.add(model.indexOf(selected[i])); + //super.setSelectedIndex(indexes.toArray(new Integer[0])); + } + + public List getSelected() { + return indexes; + } + + public boolean hasChanges() { + return changed; + } + + public void clear() { + changed = false; + } + + public boolean contains(Object obj) { + return model.contains(obj); + } + + public void addElement(Object obj) { + model.addElement(obj); + } + + public void add(int index, Object obj) { + model.add(index, obj); + } + + public void removeElements(Object[] removeValues) { + for (int i = 0; i < removeValues.length; i++) { + model.removeElement(removeValues[i]); + } + } + + public void removeAllElements() { + model.removeAllElements(); +// for (int i = 0; i < model.size(); i++) { +// model.removeElement(model.get(i)); +// } + } + + public String getElement(int index) { + return model.elementAt(index).toString(); +// for (int i = 0; i < model.size(); i++) { +// model.removeElement(model.get(i)); +// } + } + + public void removeSelectedElements() { + + Object [] selectedValues = this.getSelectedValues(); + for (int i = 0; i < selectedValues.length; i++) { + model.removeElement(selectedValues[i]); + } + } + + public String[] getAllElements() { + String[] obj = new String[model.getSize()]; + model.copyInto(obj); + return obj; + } + + //Swap two elements in the list. + public void swap(int a, int b) { + Object aObject = model.getElementAt(a); + Object bObject = model.getElementAt(b); + model.set(a, bObject); + model.set(b, aObject); + } + + public void setModelSize(int modelSize) { + this.model.setSize(modelSize); + this.model.trimToSize(); + } +} diff --git a/festc_core/src/gov/epa/festc/gui/ManFileModPanel.java b/festc_core/src/gov/epa/festc/gui/ManFileModPanel.java index d8e4ccf..18fa7fc 100644 --- a/festc_core/src/gov/epa/festc/gui/ManFileModPanel.java +++ b/festc_core/src/gov/epa/festc/gui/ManFileModPanel.java @@ -1,349 +1,357 @@ -package gov.epa.festc.gui; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.io.File; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JScrollPane; -import javax.swing.ListSelectionModel; -import javax.swing.SpringLayout; -import javax.swing.SwingConstants; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.core.FestcGUI; -import gov.epa.festc.core.proj.DomainFields; -import gov.epa.festc.core.proj.ManFileModFields; -import gov.epa.festc.util.Constants; -import gov.epa.festc.util.SpringLayoutGenerator; -import simphony.util.messages.MessageCenter; - -public class ManFileModPanel extends UtilFieldsPanel implements PlotEventListener { - private static final long serialVersionUID = 8617841823458370182L; - - private static final String indent = " "; - //private static final String LABEL_EPIC_SCENARIO = indent + "Select Scenario Direcotry:"; - - private JList lstCrops; - - private MessageCenter msg; - private String baseDir; - private String scenDir; - private String contFile; - private String paramFile; - private String fileFile; - private String irrFile; - private String rainFile; - - private FestcGUI parent; - private FestcApplication app; - private ManFileModFields fields; - - private JRadioButton applicationBtn, spinupBtn; - private boolean isSpinup = false; - - public ManFileModPanel(FestcApplication application) { - app = application; - msg = app.getMessageCenter(); - fields = new ManFileModFields(); - app.getProject().addPage(fields); - app.addPlotListener(this); - add(createPanel()); - } - - private JPanel createPanel() { - JPanel main = new JPanel(); - init(); - main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS)); - main.add(getNorthPanel() ); - main.add(getCenterPanel() ); - main.add(getSouthPanel() ); - main.add(messageBox()); - return main; - } - - private JPanel getNorthPanel() { - JPanel panel = new JPanel(); - JLabel title = new JLabel(Constants.EDIT_INFILES, SwingConstants.CENTER); - title.setFont(new Font("Default", Font.BOLD, 20)); - - panel.add(title); - panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); - - return panel; - } - - private JPanel getSouthPanel() { - return new JPanel(); - } - - private JPanel getCenterPanel() { - JPanel panel = new JPanel(new SpringLayout()); - SpringLayoutGenerator layout = new SpringLayoutGenerator(); - - //this.scenarioDir = new JTextField(40); - - JPanel spinupPanel = new JPanel(); - this.applicationBtn = new JRadioButton(applicationSelection()); - this.spinupBtn = new JRadioButton(spinupSelection()); - this.applicationBtn.setSelected(true); - this.spinupBtn.setSelected(false); - spinupPanel.add(this.spinupBtn); - spinupPanel.add(this.applicationBtn); - - ButtonGroup btnGroup = new ButtonGroup(); - btnGroup.add(this.spinupBtn); - btnGroup.add(this.applicationBtn); - - JPanel cropsPanel = new JPanel(new BorderLayout()); - cropsPanel.add(new JLabel("Crops/Grasses"), BorderLayout.NORTH); - lstCrops = new JList(Constants.CROPS.keySet().toArray()); - lstCrops.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - lstCrops.setVisibleRowCount(20); - JScrollPane scrollCropList = new JScrollPane(lstCrops); - scrollCropList.setPreferredSize(new Dimension(120, 220)); - cropsPanel.add(scrollCropList, BorderLayout.SOUTH); - - JPanel leftPanel = new JPanel(); - leftPanel.add(cropsPanel); - - layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); - layout.addLabelWidgetPair(indent + "Simulation Type:", spinupPanel, panel); - layout.addLabelWidgetPair(" ", new JLabel(" "), panel); - layout.addWidgetPair(leftPanel, rightPanel(), panel); - - layout.makeCompactGrid(panel, 4, 2, // number of rows and cols - 10, 10, // initial X and Y - 5, 5); // x and y pading - - return panel; - } - - private JPanel rightPanel(){ - JPanel rightPanel = new JPanel(new SpringLayout()); - SpringLayoutGenerator layout = new SpringLayoutGenerator(); - - JPanel contPanel = new JPanel(); - JButton vcontButton = new JButton(viewAction("cont")); - JButton econtButton = new JButton(editAction("cont")); - contPanel.add(vcontButton); - contPanel.add(econtButton); - JPanel paramPanel = new JPanel(); - JButton vparamButton = new JButton(viewAction("param")); - JButton eparamButton = new JButton(editAction("param")); - paramPanel.add(vparamButton); - paramPanel.add(eparamButton); - JPanel filePanel = new JPanel(); - JButton vfileButton = new JButton(viewAction("file")); - JButton efileButton = new JButton(editAction("file")); - filePanel.add(vfileButton); - filePanel.add(efileButton); - JPanel irrPanel = new JPanel(); - JButton virrButton = new JButton(viewAction("irr")); - JButton eirrButton = new JButton(editAction("irr")); - irrPanel.add(virrButton); - irrPanel.add(eirrButton); - JPanel rainPanel = new JPanel(); - JButton vrainButton = new JButton(viewAction("rain")); - JButton erainButton = new JButton(editAction("rain")); - rainPanel.add(vrainButton); - rainPanel.add(erainButton); - - layout.addLabelWidgetPair("EPICCONT.DAT", contPanel, rightPanel); - layout.addLabelWidgetPair("PARM0509.DAT", paramPanel, rightPanel); - layout.addLabelWidgetPair("EPICFILE.DAT", filePanel, rightPanel); - - layout.addLabelWidgetPair("RAINFED EPICRUNFILE", rainPanel, rightPanel); - layout.addLabelWidgetPair("IRRIGATED EPICRUNFILE", irrPanel, rightPanel); - - layout.makeCompactGrid(rightPanel, 5, 2, // number of rows and cols - 10, 10, // initial X and Y - 50, 12); // x and y pading - - return rightPanel; - } - - public void setParent(FestcGUI parent) { - this.parent = parent; - } - - public Action viewAction(final String name){ - return new AbstractAction("View"){ - /** - * - */ - private static final long serialVersionUID = 1L; - - public void actionPerformed(ActionEvent e) { - if (validateFields()){ - - String file = getFile(name); - String title = "View: " + file; - - ViewFileDialog dialog = new ViewFileDialog(parent.getFrame(), title, new File(file), false); - dialog.setVisible(true); - } - - } - }; - } - - public Action editAction(final String name){ - return new AbstractAction("Edit"){ - public void actionPerformed(ActionEvent e) { - if ( validateFields()) { - String file = getFile(name); - String title = "Edit: " + file; - ViewFileDialog dialog = new ViewFileDialog(parent.getFrame(), title, new File(file), true); - dialog.setVisible(true); - } - } - }; - } - - - private String getFile(String name){ - String file=""; - if ( name.equalsIgnoreCase("cont")) - file = contFile; - else if ( name.equalsIgnoreCase("param")) - file = paramFile; - else if ( name.equalsIgnoreCase("file")) - file = fileFile; - else if ( name.equalsIgnoreCase("irr")) - file = irrFile; - else if ( name.equalsIgnoreCase("rain")) - file = rainFile; - return file; - } - - private boolean validateFields(){ - String type = ""; - if ( isSpinup ) - type = "spinup"; - else - type = "app"; - - baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - baseDir = baseDir.trim(); - if (baseDir == null || baseDir.isEmpty()) { - app.showMessage("Utilities", "Base dir is empty, please specify it in the configuration file!"); - return false; - } - - scenDir = this.scenarioDir.getText(); - if (scenDir == null || scenDir.isEmpty()) { - app.showMessage("Utilities", "Scenario dir is empty!"); - return false; - } - - String selCrop = (String) lstCrops.getSelectedValue(); - if ( selCrop == null || selCrop.trim().length() == 0) { - app.showMessage("View/Edit Files: ", "Please select a crop first!"); - return false; - } - if ( selCrop.equalsIgnoreCase("POTATOES") && type.equalsIgnoreCase("spinup")) - contFile = baseDir + "/common_data/EPIC_model/" + type + "/EPICCONT_POTATOES.DAT"; - else if ( type.equalsIgnoreCase("spinup")) - contFile = baseDir + "/common_data/EPIC_model/" + type + "/EPICCONT.DAT"; - else - contFile = scenDir + "/share_data/EPICCONT.DAT"; - - - paramFile = baseDir + "/common_data/EPIC_model/" + type + "/PARM0509.DAT"; - fileFile = baseDir + "/common_data/EPIC_model/" + type + "/EPICFILE.DAT"; - if (type.equalsIgnoreCase("spinup")) { - irrFile = scenDir + "/" + selCrop + "/" + type + "/manage/EPICRUNFILEIRR.DAT"; - rainFile = scenDir + "/" + selCrop + "/" + type + "/manage/EPICRUNFILERAIN.DAT"; - } - else { - irrFile = scenDir + "/" + selCrop + "/" + type + "/manage/EPICRUNFILEIRRDW.DAT"; - rainFile = scenDir + "/" + selCrop + "/" + type + "/manage/EPICRUNFILERAINDW.DAT"; - } - outMessages += "Epic base: " + baseDir + ls +ls; - outMessages += "Files: " + ls; - outMessages += contFile + ls; - outMessages += paramFile + ls; - outMessages += fileFile + ls; - outMessages += irrFile + ls; - outMessages += rainFile + ls; - - runMessages.setText(outMessages); - return true; - } - - - private Action spinupSelection() { - return new AbstractAction("EPIC SPINUP") { - public void actionPerformed(ActionEvent e) { - processSpinup(); - } - - }; - } - - private Action applicationSelection() { - return new AbstractAction("EPIC APP") { - public void actionPerformed(ActionEvent e) { - processSpinup(); - } - - }; - } - - private void processSpinup() { - if ( applicationBtn.isSelected()) { - isSpinup = false; - } else { - isSpinup = true; - } - validateFields(); - } - - @Override - public void newProjectCreated() { - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - scenarioDir.setText(domain.getScenarioDir()); - runMessages.setText(""); - if ( fields == null ) { - fields = new ManFileModFields(); - app.getProject().addPage(fields); - } - } - - public void projectLoaded() { - fields = (ManFileModFields) app.getProject().getPage(fields.getName()); - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - if ( fields != null ){ - String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length()>0 ) - this.scenarioDir.setText(scenloc); - else - this.scenarioDir.setText(fields.getScenarioDir()); - if ( fields.getMessage() != null ) - runMessages.setText(fields.getMessage()); - else - runMessages.setText(""); - } - else{ - newProjectCreated(); - } - } - - public void saveProjectRequested() { - if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); - if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); - if ( runMessages != null ) fields.setMessage(runMessages.getText().trim()); - } -} +package gov.epa.festc.gui; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.io.File; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.ListSelectionModel; +import javax.swing.SpringLayout; +import javax.swing.SwingConstants; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.core.FestcGUI; +import gov.epa.festc.core.proj.DomainFields; +import gov.epa.festc.core.proj.ManFileModFields; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.SpringLayoutGenerator; +import simphony.util.messages.MessageCenter; + +public class ManFileModPanel extends UtilFieldsPanel implements PlotEventListener { + private static final long serialVersionUID = 8617841823458370182L; + + private static final String indent = " "; + //private static final String LABEL_EPIC_SCENARIO = indent + "Select Scenario Direcotry:"; + + private JList lstCrops; + + private MessageCenter msg; + private String baseDir; + private String scenDir; + private String contFile; + private String paramFile; + private String fileFile; + private String irrFile; + private String rainFile; + private String epicVer; + + private FestcGUI parent; + private FestcApplication app; + private ManFileModFields fields; + + private JRadioButton applicationBtn, spinupBtn; + private boolean isSpinup = false; + + public ManFileModPanel(FestcApplication application) { + app = application; + msg = app.getMessageCenter(); + epicVer = Constants.getProperty(Constants.EPIC_VER, msg).trim(); + fields = new ManFileModFields(); + app.getProject().addPage(fields); + app.addPlotListener(this); + add(createPanel()); + } + + private JPanel createPanel() { + JPanel main = new JPanel(); + init(); + main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS)); + main.add(getNorthPanel() ); + main.add(getCenterPanel() ); + main.add(getSouthPanel() ); + main.add(messageBox()); + return main; + } + + private JPanel getNorthPanel() { + JPanel panel = new JPanel(); + JLabel title = new JLabel(Constants.EDIT_INFILES, SwingConstants.CENTER); + title.setFont(new Font("Default", Font.BOLD, 20)); + + panel.add(title); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + + return panel; + } + + private JPanel getSouthPanel() { + return new JPanel(); + } + + private JPanel getCenterPanel() { + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + + //this.scenarioDir = new JTextField(40); + + JPanel spinupPanel = new JPanel(); + this.applicationBtn = new JRadioButton(applicationSelection()); + this.spinupBtn = new JRadioButton(spinupSelection()); + this.applicationBtn.setSelected(true); + this.spinupBtn.setSelected(false); + spinupPanel.add(this.spinupBtn); + spinupPanel.add(this.applicationBtn); + + ButtonGroup btnGroup = new ButtonGroup(); + btnGroup.add(this.spinupBtn); + btnGroup.add(this.applicationBtn); + + JPanel cropsPanel = new JPanel(new BorderLayout()); + cropsPanel.add(new JLabel("Crops/Grasses"), BorderLayout.NORTH); + lstCrops = new JList(Constants.CROPS.keySet().toArray()); + lstCrops.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + lstCrops.setVisibleRowCount(20); + JScrollPane scrollCropList = new JScrollPane(lstCrops); + scrollCropList.setPreferredSize(new Dimension(120, 220)); + cropsPanel.add(scrollCropList, BorderLayout.SOUTH); + + JPanel leftPanel = new JPanel(); + leftPanel.add(cropsPanel); + + layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); + layout.addLabelWidgetPair(indent + "Simulation Type:", spinupPanel, panel); + layout.addLabelWidgetPair(" ", new JLabel(" "), panel); + layout.addWidgetPair(leftPanel, rightPanel(), panel); + + layout.makeCompactGrid(panel, 4, 2, // number of rows and cols + 10, 10, // initial X and Y + 5, 5); // x and y pading + + return panel; + } + + private JPanel rightPanel(){ + JPanel rightPanel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + + JPanel contPanel = new JPanel(); + JButton vcontButton = new JButton(viewAction("cont")); + JButton econtButton = new JButton(editAction("cont")); + contPanel.add(vcontButton); + contPanel.add(econtButton); + JPanel paramPanel = new JPanel(); + JButton vparamButton = new JButton(viewAction("param")); + JButton eparamButton = new JButton(editAction("param")); + paramPanel.add(vparamButton); + paramPanel.add(eparamButton); + JPanel filePanel = new JPanel(); + JButton vfileButton = new JButton(viewAction("file")); + JButton efileButton = new JButton(editAction("file")); + filePanel.add(vfileButton); + filePanel.add(efileButton); + JPanel irrPanel = new JPanel(); + JButton virrButton = new JButton(viewAction("irr")); + JButton eirrButton = new JButton(editAction("irr")); + irrPanel.add(virrButton); + irrPanel.add(eirrButton); + JPanel rainPanel = new JPanel(); + JButton vrainButton = new JButton(viewAction("rain")); + JButton erainButton = new JButton(editAction("rain")); + rainPanel.add(vrainButton); + rainPanel.add(erainButton); + + layout.addLabelWidgetPair("EPICCONT.DAT", contPanel, rightPanel); + if ( epicVer.equalsIgnoreCase("1102") ) + layout.addLabelWidgetPair("PARM1102.DAT", paramPanel, rightPanel); + else + layout.addLabelWidgetPair("PARM0509.DAT", paramPanel, rightPanel); + layout.addLabelWidgetPair("EPICFILE.DAT", filePanel, rightPanel); + + layout.addLabelWidgetPair("RAINFED EPICRUNFILE", rainPanel, rightPanel); + layout.addLabelWidgetPair("IRRIGATED EPICRUNFILE", irrPanel, rightPanel); + + layout.makeCompactGrid(rightPanel, 5, 2, // number of rows and cols + 10, 10, // initial X and Y + 50, 12); // x and y pading + + return rightPanel; + } + + public void setParent(FestcGUI parent) { + this.parent = parent; + } + + public Action viewAction(final String name){ + return new AbstractAction("View"){ + /** + * + */ + private static final long serialVersionUID = 1L; + + public void actionPerformed(ActionEvent e) { + if (validateFields()){ + + String file = getFile(name); + String title = "View: " + file; + + ViewFileDialog dialog = new ViewFileDialog(parent.getFrame(), title, new File(file), false); + dialog.setVisible(true); + } + + } + }; + } + + public Action editAction(final String name){ + return new AbstractAction("Edit"){ + public void actionPerformed(ActionEvent e) { + if ( validateFields()) { + String file = getFile(name); + String title = "Edit: " + file; + ViewFileDialog dialog = new ViewFileDialog(parent.getFrame(), title, new File(file), true); + dialog.setVisible(true); + } + } + }; + } + + + private String getFile(String name){ + String file=""; + if ( name.equalsIgnoreCase("cont")) + file = contFile; + else if ( name.equalsIgnoreCase("param")) + file = paramFile; + else if ( name.equalsIgnoreCase("file")) + file = fileFile; + else if ( name.equalsIgnoreCase("irr")) + file = irrFile; + else if ( name.equalsIgnoreCase("rain")) + file = rainFile; + return file; + } + + private boolean validateFields(){ + String type = ""; + if ( isSpinup ) + type = "spinup"; + else + type = "app"; + + baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + baseDir = baseDir.trim(); + if (baseDir == null || baseDir.isEmpty()) { + app.showMessage("Utilities", "Base dir is empty, please specify it in the configuration file!"); + return false; + } + + scenDir = this.scenarioDir.getText(); + if (scenDir == null || scenDir.isEmpty()) { + app.showMessage("Utilities", "Scenario dir is empty!"); + return false; + } + + String selCrop = (String) lstCrops.getSelectedValue(); + if ( selCrop == null || selCrop.trim().length() == 0) { + app.showMessage("View/Edit Files: ", "Please select a crop first!"); + return false; + } + if ( selCrop.equalsIgnoreCase("POTATOES") && type.equalsIgnoreCase("spinup")) + contFile = baseDir + "/common_data/EPIC_model/" + type + "/EPICCONT_POTATOES.DAT"; + else if ( type.equalsIgnoreCase("spinup")) + contFile = baseDir + "/common_data/EPIC_model/" + type + "/EPICCONT.DAT"; + else + contFile = scenDir + "/share_data/EPICCONT.DAT"; + + if ( epicVer.equalsIgnoreCase("1102")) + paramFile = baseDir + "/compmon_data/EPIC_model/" + type + "/PARM1102.DAT"; + else + paramFile = baseDir + "/compmon_data/EPIC_model/" + type + "/PARM0509.DAT"; + + fileFile = baseDir + "/common_data/EPIC_model/" + type + "/EPICFILE.DAT"; + if (type.equalsIgnoreCase("spinup")) { + irrFile = scenDir + "/" + selCrop + "/" + type + "/manage/EPICRUNFILEIRR.DAT"; + rainFile = scenDir + "/" + selCrop + "/" + type + "/manage/EPICRUNFILERAIN.DAT"; + } + else { + irrFile = scenDir + "/" + selCrop + "/" + type + "/manage/EPICRUNFILEIRRDW.DAT"; + rainFile = scenDir + "/" + selCrop + "/" + type + "/manage/EPICRUNFILERAINDW.DAT"; + } + outMessages += "Epic base: " + baseDir + ls +ls; + outMessages += "Files: " + ls; + outMessages += contFile + ls; + outMessages += paramFile + ls; + outMessages += fileFile + ls; + outMessages += irrFile + ls; + outMessages += rainFile + ls; + + runMessages.setText(outMessages); + return true; + } + + + private Action spinupSelection() { + return new AbstractAction("EPIC SPINUP") { + public void actionPerformed(ActionEvent e) { + processSpinup(); + } + + }; + } + + private Action applicationSelection() { + return new AbstractAction("EPIC APP") { + public void actionPerformed(ActionEvent e) { + processSpinup(); + } + + }; + } + + private void processSpinup() { + if ( applicationBtn.isSelected()) { + isSpinup = false; + } else { + isSpinup = true; + } + validateFields(); + } + + @Override + public void newProjectCreated() { + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + scenarioDir.setText(domain.getScenarioDir()); + runMessages.setText(""); + if ( fields == null ) { + fields = new ManFileModFields(); + app.getProject().addPage(fields); + } + } + + public void projectLoaded() { + fields = (ManFileModFields) app.getProject().getPage(fields.getName()); + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + if ( fields != null ){ + String scenloc = domain.getScenarioDir(); + if (scenloc != null && scenloc.trim().length()>0 ) + this.scenarioDir.setText(scenloc); + else + this.scenarioDir.setText(fields.getScenarioDir()); + if ( fields.getMessage() != null ) + runMessages.setText(fields.getMessage()); + else + runMessages.setText(""); + } + else{ + newProjectCreated(); + } + } + + public void saveProjectRequested() { + if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); + if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); + if ( runMessages != null ) fields.setMessage(runMessages.getText().trim()); + } +} diff --git a/festc_core/src/gov/epa/festc/gui/Mcip2EpicPanel.java b/festc_core/src/gov/epa/festc/gui/Mcip2EpicPanel.java index 9c7bd71..146ac68 100644 --- a/festc_core/src/gov/epa/festc/gui/Mcip2EpicPanel.java +++ b/festc_core/src/gov/epa/festc/gui/Mcip2EpicPanel.java @@ -1,496 +1,641 @@ -package gov.epa.festc.gui; - -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.text.NumberFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JFormattedTextField; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SpringLayout; -import javax.swing.SwingConstants; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.core.proj.DomainFields; -import gov.epa.festc.core.proj.Mcip2EpicFields; -import gov.epa.festc.util.Constants; -import gov.epa.festc.util.FileRunner; -import gov.epa.festc.util.SpringLayoutGenerator; -import simphony.util.messages.MessageCenter; - -public class Mcip2EpicPanel extends UtilFieldsPanel implements PlotEventListener { - private static final long serialVersionUID = -1426530506543484237L; - private JTextField mdataDir; - private JButton dataDirBrowser; - - private MessageCenter msg; - private JFormattedTextField startDate; - private JFormattedTextField endDate; - - private JComboBox depositionSel; - private JTextField depositionDir; - private JButton depositionDirBrowser; - - private FestcApplication app; - private Mcip2EpicFields fields; - - public Mcip2EpicPanel(FestcApplication festcApp) { - app = festcApp; - msg = app.getMessageCenter(); - fields = new Mcip2EpicFields(); - app.getProject().addPage(fields); - app.addPlotListener(this); - add(createPanel()); - } - - private JPanel createPanel() { - init(); - JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - mainPanel.add(getNorthPanel()); - mainPanel.add(getCenterPanel()); - mainPanel.add(getSouthPanel()); - mainPanel.add(messageBox()); - return mainPanel; - } - - private JPanel getNorthPanel() { - JPanel panel = new JPanel(); - JLabel title = new JLabel(Constants.MC2EPIC, SwingConstants.CENTER); - title.setFont(new Font("Default", Font.BOLD, 20)); - - panel.add(title); - panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); - - return panel; - } - - private JPanel getSouthPanel() { - JPanel panel = new JPanel(); - JButton display = new JButton(runAction()); - panel.add(display); - - panel.setBorder(BorderFactory.createEmptyBorder(30, 0, 10, 0)); - - return panel; - } - - private JPanel getCenterPanel() { - JPanel panel = new JPanel(new SpringLayout()); - SpringLayoutGenerator layout = new SpringLayoutGenerator(); - - JPanel dataDirPanel = new JPanel(); - mdataDir = new JTextField(40); - dataDirBrowser = new JButton(browseDirAction("MCIP data dir", mdataDir)); - dataDirPanel.add(mdataDir); - dataDirPanel.add(dataDirBrowser); - - JPanel deposSPanel = new JPanel(); - depositionSel = new JComboBox(Constants.DEPSELECTIONS); - depositionSel.setSelectedIndex(0); - depositionSel.addActionListener(selectAction()); - deposSPanel.add(depositionSel); - - JPanel deposDirPanel = new JPanel(); - depositionDir = new JTextField(40); - depositionDirBrowser = new JButton(browseDirAction("CMAQ deposition dir", depositionDir)); - deposDirPanel.add(depositionDir); - deposDirPanel.add(depositionDirBrowser); - - JPanel startDatePanel = new JPanel(); - NumberFormat snf = NumberFormat.getNumberInstance(); - snf.setGroupingUsed(false); - startDate = new JFormattedTextField(snf); - startDate.setColumns(40); - startDatePanel.add(startDate); - - JPanel endDatePanel = new JPanel(); - NumberFormat enf = NumberFormat.getNumberInstance(); - enf.setGroupingUsed(false); - endDate = new JFormattedTextField(enf); - endDate.setColumns(40); - endDatePanel.add(endDate); - - layout.addLabelWidgetPair("Grid Description:", getGridDescPanel(false), panel); - layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); - layout.addLabelWidgetPair("Start Date (YYYYMMDD):", startDatePanel, panel); - layout.addLabelWidgetPair("End Date (YYYYMMDD):", endDatePanel, panel); - layout.addLabelWidgetPair("MCIP Data Directory:", dataDirPanel, panel); - layout.addLabelWidgetPair("Deposition Selection: ", deposSPanel, panel); - layout.addLabelWidgetPair("CMAQ Deposition Directory:", deposDirPanel, panel); - - layout.makeCompactGrid(panel, 7, 2, // number of rows and cols - 10, 10, // initial X and Y - 5, 5); // x and y pading - - return panel; - } - - private AbstractAction selectAction() { - return new AbstractAction() { - public void actionPerformed( ActionEvent arg0) { - if ( depositionSel.getSelectedItem() != null ) { - if ( (depositionSel.getSelectedItem()).equals("CMAQ deposition directory")) { - depositionDirBrowser.setEnabled(true); - depositionDir.setEditable(true); - }else{ - depositionDirBrowser.setEnabled(false); - depositionDir.setEditable(false); - } - } - } - }; - } - - - private Action runAction() { - return new AbstractAction("Run") { - private static final long serialVersionUID = 8573618661168062193L; - - public void actionPerformed(ActionEvent e) { - try { - generateRunScript(); - } catch (Exception exc) { - app.showMessage("Write script", exc.getMessage()); - } - } - }; - } - - private Action browseDirAction(final String name, final JTextField text) { - return new AbstractAction("Browse...") { - private static final long serialVersionUID = 482845697751457179L; - - public void actionPerformed(ActionEvent e) { - JFileChooser chooser; - File file = new File(text.getText()); - - if (file != null && file.isFile()) { - chooser = new JFileChooser(file.getParentFile()); - } else if (file != null && file.isDirectory()) { - chooser = new JFileChooser(file); - } else - chooser = new JFileChooser(app.getCurrentDir()); - - chooser.setDialogTitle("Please select the " + name); - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - - int option = chooser.showDialog(Mcip2EpicPanel.this, - "Select"); - if (option == JFileChooser.APPROVE_OPTION) { - File selected = chooser.getSelectedFile(); - text.setText("" + selected); - app.setCurrentDir(selected); - } - } - }; - } - - private void generateRunScript() throws Exception { - - String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - if (baseDir == null || baseDir.isEmpty()) - throw new Exception("Base dir is empty, please specify it in the configuration file!"); - - String scenarioDir = this.scenarioDir.getText(); - validateScen(scenarioDir); - validateGrids(); - - String sahome = Constants.getProperty(Constants.SA_HOME, msg); - if (sahome == null || sahome.trim().isEmpty() || !(new File(sahome).exists())) - throw new Exception("SA dir is empty, please specify it in the configuration file!"); - - if (!(new File(mdataDir.getText()).exists())) - throw new Exception("MCIP data directory is invalid."); - - if ( (depositionSel.getSelectedItem()).equals("CMAQ deposition directory")) { - if (!(new File(depositionDir.getText()).exists())) - throw new Exception("CMAQ deposition directory is invalid."); - - } - - String start = startDate.getText(); - if (start == null || start.trim().isEmpty()) - throw new Exception("Start date field is empty."); - - if (start.trim().length() != 8) - throw new Exception("Start date value is invalid."); - - if (start.trim().charAt(0) == '0') - throw new Exception("Start date value is invalid."); - - String end = endDate.getText(); - if (end == null || end.trim().isEmpty()) - throw new Exception("End date field is empty."); - - if (end.trim().length() != 8) - throw new Exception("End date value is invalid."); - - if (end.trim().charAt(0) == '0') - throw new Exception("End date value is invalid."); - - outMessages += "Epic base: " + baseDir + ls; - outMessages += "SA home: " + sahome + ls; - outMessages += "Scen directory: " + scenarioDir + ls; - - final String file = writeRunScriptScript(baseDir, scenarioDir, sahome); - Thread populateThread = new Thread(new Runnable() { - public void run() { - runScript(file); - } - }); - populateThread.start(); - } - - protected String writeRunScriptScript( - String baseDir, - String scenarioDir, - String sahome ) throws Exception { - Date now = new Date(); // java.util.Date, NOT java.sql.Date or java.sql.Timestamp! - - String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - - String file = scenarioDir.trim() + "/scripts"; - file += "/generateEPICsiteDailyWeatherfromMCIP_CAMQ_" + timeStamp + ".csh"; - - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - - sb.append(getScriptHeader() + ls); - sb.append("#" + ls + "# Set up runtime environment" + ls + "#" + ls); - sb.append("source " + sahome.trim() + Constants.SA_SETUP_FILE + ls + ls); - - sb.append("setenv EPIC_DIR " + baseDir + ls); - sb.append("setenv SCEN_DIR " + scenarioDir + ls); - sb.append("setenv SA_HOME " + sahome +ls); - sb.append("source $SA_HOME/"+ Constants.SA_SETUP_FILE + ls + ls); - - sb.append("#" + ls + "# Define MCIP domain grid information" + ls + "#" + ls); - sb.append("setenv GRID_PROJ \"" + proj4proj.getText().trim() + "\"" + ls + ls); - sb.append("setenv GRID_ROWS " + ((Number)rows.getValue()).intValue() + ls); - sb.append("setenv GRID_COLUMNS " + ((Number)cols.getValue()).intValue() + ls + ls); - sb.append("setenv GRID_XMIN " + ((Number)xmin.getValue()).doubleValue() + ls); - sb.append("setenv GRID_YMIN " + ((Number)ymin.getValue()).doubleValue() + ls + ls); - sb.append("setenv GRID_XCELLSIZE " + ((Number)xSize.getValue()).doubleValue() + ls); - sb.append("setenv GRID_YCELLSIZE " + ((Number)ySize.getValue()).doubleValue() + ls + ls); - sb.append("setenv GRID_NAME \"" + (gridName.getText() == null ? "" : gridName.getText().trim()) + "\"" + ls + ls); - sb.append("#" + ls - + "#Set MCIP data directory which containts daily MCIP files" + ls - + "#Daily MCIP data files have to have names with METCRO2D*\"date\"" + ls - + "#The \"date\" can be in one of the format: YYYYMMDD, YYMMDD, YYYYDDD, YYDDD" + ls - + "#" + ls); - - sb.append("setenv DATA_DIR \"" + mdataDir.getText() + "\"" + ls + ls); - sb.append("#" + ls - + "#Set CMAQ output dry/wet deposition data directory which containts daily CMAQ files" + ls - + "#" + ls); - - String dataDirCmaq = ""; - if ( depositionSel.getSelectedItem().equals("Zero") ) - dataDirCmaq = "Zero"; - else if ( depositionSel.getSelectedItem().equals("Default") ) - dataDirCmaq = "Default"; - else - dataDirCmaq = depositionDir.getText().trim(); - sb.append("setenv DATA_DIR_CMAQ \"" + dataDirCmaq + "\"" + ls + ls); - sb.append("#" + ls + "#Set date range: YYYYMMDD" + ls + "#" + ls); - sb.append("setenv START_DATE " + startDate.getText() + ls); - sb.append("setenv END_DATE " + endDate.getText() + ls + ls); - sb.append("#" + ls + "#Set input EPIC site data file in ascii csv format as: site_name,longitude,latitude" + ls + "#" + ls); - sb.append("setenv EPIC_SITE_FILE \"$SCEN_DIR/share_data/allSites_Info.csv" + "\"" + ls + ls); - sb.append("#" + ls + "# Set output directory which will store created EPIC site daily weather files:" + ls - + "# 1. \"site_name\".dly 2. WXPMRUN.DAT " + ls + "#" + ls); - - sb.append("setenv OUTPUT_DATA_DIR $SCEN_DIR/share_data/ " + ls + ls); - sb.append("#" + ls - + "# Set NetCDF output file to store computed EPIC site daily weather and N deposition data" + ls - + "# Only set this variable when EPIC grids are the same as MCIP/CMAQ grids." + ls - + "# Otherwise, set it to NONE for no NetCDF file output" + ls - + "#" + ls); - sb.append("setenv OUTPUT_NETCDF_FILE $SCEN_DIR/share_data/site_weather_dep_${START_DATE}_to_${END_DATE}.nc"+ ls + ls); - sb.append("$SA_HOME/bin/64bits/computeSiteDailyWeather.exe" + ls + ls); - - sb.append(" if ( $status == 0 ) then " + ls); - sb.append(" echo ==== Finished MCIP/CMAQ to EPIC run. " + ls); - sb.append(" else " + ls); - sb.append(" echo ==== Error in MCIP/CMAQ to EPIC runs." + ls + ls); - sb.append(" echo " + ls ); - sb.append(" endif " + ls); - sb.append("#===================================================================" + ls); - - String mesg = ""; - try { - File script = new File(file); - - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - - mesg += "Created a script file: " + file + "\n"; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - } catch (IOException e) { - throw new Exception(e.getMessage()); - } - app.showMessage("Write script", mesg); - return file; - } - - private String getScriptHeader() { - StringBuilder sb = new StringBuilder(); - String ls = "\n"; - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to extract six daily weather variable data from MCIP data for EPIC modeling" + ls); - sb.append("# sites and to create WXPMRUN.DAT run data file for WXPM3020 to compute" + ls); - sb.append("# monthly climate data." + ls); - sb.append("#" + ls); - sb.append("# 1. Radiation (MJ m^02, daily total)" + ls); - sb.append("# 2. Tmax (C, daily)" + ls); - sb.append("# 3. Tmin (C, daily)" + ls); - sb.append("# 4. Precipitation (mm, daily total)" + ls); - sb.append("# 5. Relative humidity (fraction, daily average)" + ls); - sb.append("# 6. Windspeed (m s^-1, daily average)" + ls); - sb.append("" + ls); - sb.append("# There are three steps involved in extraction:" + ls); - sb.append("# 1. read in EPIC site lat and long location data, project them into MCIP data projection and" + ls); - sb.append("# convert them into column and row in MCIP grids." + ls); - sb.append("# 2. loop through each day MCIP data to extract daily weather variables for each EPIC site" + ls); - sb.append("# and to write them into each EPIC site daily weather file." + ls); - sb.append("# 3. created WXPMRUN.DAT file for all generated EPIC daily weather files in order to run WXPM3020.DRB program." + ls); - sb.append("# The program computes monthly weather data to be named in monthly weather list file like WPM1US.DAT." + ls); - sb.append("#" + ls); - sb.append("# Output files:" + ls); - sb.append("# 1. \"site_name\".dly - EPIC daily weather input file " + ls); - sb.append("# 2. WXPMRUN.DAT - to WXPM3020.DRB for computing EPIC monthly weather" + ls); - sb.append("#" + ls); - sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); - sb.append("# in support of the EPA CMAS Modeling, 2009." + ls); - sb.append("#" + ls); - sb.append("# Written by: L. R., Aug. 2009" + ls); - sb.append("# Modified by:" + ls); - sb.append("#" + ls); - sb.append("# Call program: computeSiteDailyWeather.exe" + ls); - sb.append("# Needed environment variables listed in this run script file." + ls); - sb.append("#" + ls); - sb.append("# Usage: ./generateEPICsiteDailyWeatherfromMCIP.csh" + ls); - - sb.append("#***************************************************************************************" + ls + ls); - - return sb.toString(); - } - - private void runScript(final String file) { - String log = file + ".log"; - - outMessages += "Script file: " + file + ls; - outMessages += "Log file: " + log + ls; - runMessages.setText(outMessages); - runMessages.validate(); - FileRunner.runScript(file, log, msg); - } - - @Override - public void projectLoaded() { - fields = (Mcip2EpicFields) app.getProject().getPage(fields.getName()); - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - if ( fields != null ){ - String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length()>0 ) - this.scenarioDir.setText(scenloc); - else - this.scenarioDir.setText(fields.getScenarioDir()); - rows.setValue(fields.getRows()); - cols.setValue(fields.getCols()); - xSize.setValue(fields.getXcellSize()); - ySize.setValue(fields.getYcellSize()); - xmin.setValue(fields.getXmin()); - ymin.setValue(fields.getYmin()); - proj4proj.setText(fields.getProj()); - - if ( fields.getGridName() != null ) this.gridName.setText(fields.getGridName()); - try { - startDate.setValue(NumberFormat.getNumberInstance().parse(fields.getStartdate()==null? "":fields.getStartdate())); - endDate.setValue(NumberFormat.getNumberInstance().parse(fields.getEnddate()==null? "":fields.getEnddate())); - } catch (ParseException e) { - //NOTE: no-op; - } - mdataDir.setText(fields.getDatadir()); - depositionSel.setSelectedItem(fields.getDepSelection()); - depositionDir.setText(fields.getCmaqDepsDir()); - this.runMessages.setText(fields.getMessage()); - } else{ - newProjectCreated(); - } - - } - - @Override - public void saveProjectRequested() { - if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()== null? "" : scenarioDir.getText()); - if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); - if ( rows != null ) fields.setRows(Integer.parseInt(rows.getText() == null? "" : rows.getValue()+"")); - if ( cols != null ) fields.setCols(Integer.parseInt(cols.getText() == null? "" : cols.getValue()+"")); - if ( xSize != null ) fields.setXcellSize(Float.parseFloat(xSize.getText() == null? "" : xSize.getValue()+"")); - if ( ySize != null ) fields.setYcellSize(Float.parseFloat(ySize.getText() == null? "" : ySize.getValue()+"")); - if ( xmin != null ) fields.setXmin(Float.parseFloat(xmin.getText() == null? "" : xmin.getValue()+"")); - if ( ymin != null ) fields.setYmin(Float.parseFloat(ymin.getText() == null? "" : ymin.getValue()+"")); - if ( proj4proj != null ) fields.setProj(proj4proj.getText() == null? "" : proj4proj.getText()); - if ( gridName != null ) fields.setGridName(gridName.getText()== null? "" : gridName.getText()); - if (startDate != null) fields.setStartdate(startDate.getValue()== null? "" : startDate.getText()); - if (endDate != null) fields.setEnddate(endDate.getValue()== null? "" : endDate.getText()); - - if (depositionSel != null) fields.setDepSelection((String)depositionSel.getSelectedItem()); - if (depositionDir != null) fields.setCmaqDepsDir(depositionDir.getText()); - if (mdataDir != null) fields.setDatadir(mdataDir.getText()); - if ( runMessages != null ) fields.setMessage(runMessages.getText()); - } - - @Override - public void newProjectCreated() { - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - scenarioDir.setText(domain.getScenarioDir()); - rows.setValue(domain.getRows()); - cols.setValue(domain.getCols()); - xmin.setValue(domain.getXmin()); - ymin.setValue(domain.getYmin()); - xSize.setValue(domain.getXcellSize()); - ySize.setValue(domain.getYcellSize()); - proj4proj.setText(domain.getProj()); - - gridName.setText(domain.getGridName()); - mdataDir.setText(""); - depositionSel.setSelectedItem(0); - depositionDir.setText(""); - - this.runMessages.setText(""); - try { - startDate.setValue(NumberFormat.getNumberInstance().parse(domain.getSimYear().trim()+ "0101")); - endDate.setValue(NumberFormat.getNumberInstance().parse(domain.getSimYear().trim()+ "1231")); - } catch (ParseException e) { - startDate.setValue(0); - endDate.setValue(0); - } - if ( fields == null ) { - fields = new Mcip2EpicFields(); - app.getProject().addPage(fields); - } - } - -} +package gov.epa.festc.gui; + +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.NumberFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JFormattedTextField; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SpringLayout; +import javax.swing.SwingConstants; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.core.proj.DomainFields; +import gov.epa.festc.core.proj.Mcip2EpicFields; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.FileRunner; +import gov.epa.festc.util.SpringLayoutGenerator; +import simphony.util.messages.MessageCenter; + +public class Mcip2EpicPanel extends UtilFieldsPanel implements PlotEventListener { + private static final long serialVersionUID = -1426530506543484237L; + private JTextField mdataDir; + private JButton dataDirBrowser; + + private MessageCenter msg; + private JFormattedTextField startDate; + private JFormattedTextField endDate; + + private JComboBox depositionSel; + private JTextField depositionDir; + private JButton depositionDirBrowser; + + private JCheckBox dlyBox; + + private FestcApplication app; + private Mcip2EpicFields fields; + + public Mcip2EpicPanel(FestcApplication festcApp) { + app = festcApp; + msg = app.getMessageCenter(); + fields = new Mcip2EpicFields(); + app.getProject().addPage(fields); + app.addPlotListener(this); + add(createPanel()); + } + + private JPanel createPanel() { + init(); + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + mainPanel.add(getNorthPanel()); + mainPanel.add(getCenterPanel()); + mainPanel.add(getSouthPanel()); + mainPanel.add(messageBox()); + return mainPanel; + } + + private JPanel getNorthPanel() { + JPanel panel = new JPanel(); + JLabel title = new JLabel(Constants.MC2EPIC, SwingConstants.CENTER); + title.setFont(new Font("Default", Font.BOLD, 20)); + + panel.add(title); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); + + return panel; + } + + private JPanel getSouthPanel() { + JPanel panel = new JPanel(); + JButton display = new JButton(runAction()); + panel.add(display); + + panel.setBorder(BorderFactory.createEmptyBorder(30, 0, 10, 0)); + + return panel; + } + + private JPanel getCenterPanel() { + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + + JPanel dataDirPanel = new JPanel(); + mdataDir = new JTextField(40); + dataDirBrowser = new JButton(browseDirAction("MCIP data dir", mdataDir)); + dataDirPanel.add(mdataDir); + dataDirPanel.add(dataDirBrowser); + + JPanel deposSPanel = new JPanel(); + depositionSel = new JComboBox(Constants.DEPSELECTIONS); + depositionSel.setSelectedIndex(0); + depositionSel.addActionListener(selectAction()); + deposSPanel.add(depositionSel); + + JPanel deposDirPanel = new JPanel(); + depositionDir = new JTextField(40); + depositionDirBrowser = new JButton(browseDirAction("CMAQ deposition dir", depositionDir)); + deposDirPanel.add(depositionDir); + deposDirPanel.add(depositionDirBrowser); + + JPanel startDatePanel = new JPanel(); + NumberFormat snf = NumberFormat.getNumberInstance(); + snf.setGroupingUsed(false); + startDate = new JFormattedTextField(snf); + startDate.setColumns(40); + startDatePanel.add(startDate); + + JPanel endDatePanel = new JPanel(); + NumberFormat enf = NumberFormat.getNumberInstance(); + enf.setGroupingUsed(false); + endDate = new JFormattedTextField(enf); + endDate.setColumns(40); + endDatePanel.add(endDate); + + JPanel dlyPanel = new JPanel(); + this.dlyBox = new JCheckBox("", false); + dlyPanel.add(this.dlyBox); + + layout.addLabelWidgetPair("Grid Description:", getGridDescPanel(false), panel); + layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); + layout.addLabelWidgetPair("Start Date (YYYYMMDD):", startDatePanel, panel); + layout.addLabelWidgetPair("End Date (YYYYMMDD):", endDatePanel, panel); + layout.addLabelWidgetPair("MCIP Data Directory:", dataDirPanel, panel); + layout.addLabelWidgetPair("Deposition Selection: ", deposSPanel, panel); + layout.addLabelWidgetPair("CMAQ Deposition Directory:", deposDirPanel, panel); + layout.addLabelWidgetPair("Output DLY Files:", dlyPanel, panel); + + layout.makeCompactGrid(panel, 8, 2, // number of rows and cols + 10, 10, // initial X and Y + 5, 5); // x and y pading + + return panel; + } + + private AbstractAction selectAction() { + return new AbstractAction() { + public void actionPerformed(ActionEvent arg0) { + if (depositionSel.getSelectedItem() != null) { + if ((depositionSel.getSelectedItem()).equals("CMAQ deposition directory")) { + depositionDirBrowser.setEnabled(true); + depositionDir.setEditable(true); + } else { + depositionDirBrowser.setEnabled(false); + depositionDir.setEditable(false); + } + } + } + }; + } + + private Action runAction() { + return new AbstractAction("Run") { + private static final long serialVersionUID = 8573618661168062193L; + + public void actionPerformed(ActionEvent e) { + try { + generateRunScript(); + } catch (Exception exc) { + app.showMessage("Write script", exc.getMessage()); + } + } + }; + } + + private Action browseDirAction(final String name, final JTextField text) { + return new AbstractAction("Browse...") { + private static final long serialVersionUID = 482845697751457179L; + + public void actionPerformed(ActionEvent e) { + JFileChooser chooser; + File file = new File(text.getText()); + + if (file != null && file.isFile()) { + chooser = new JFileChooser(file.getParentFile()); + } else if (file != null && file.isDirectory()) { + chooser = new JFileChooser(file); + } else + chooser = new JFileChooser(app.getCurrentDir()); + + chooser.setDialogTitle("Please select the " + name); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + int option = chooser.showDialog(Mcip2EpicPanel.this, "Select"); + if (option == JFileChooser.APPROVE_OPTION) { + File selected = chooser.getSelectedFile(); + text.setText("" + selected); + app.setCurrentDir(selected); + } + } + }; + } + + private void generateRunScript() throws Exception { + + String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + if (baseDir == null || baseDir.isEmpty()) + throw new Exception("Base dir is empty, please specify it in the configuration file!"); + + String scenarioDir = this.scenarioDir.getText(); + validateScen(scenarioDir); + validateGrids(); + + String sahome = Constants.getProperty(Constants.SA_HOME, msg); + // if (sahome == null || sahome.trim().isEmpty() || !(new + // File(sahome).exists())) + if (sahome == null) + throw new Exception("SA dir is empty, please specify it in the configuration file!"); + + if (!(new File(mdataDir.getText()).exists())) + throw new Exception("MCIP data directory is invalid."); + + if ((depositionSel.getSelectedItem()).equals("CMAQ deposition directory")) { + if (!(new File(depositionDir.getText()).exists())) + throw new Exception("CMAQ deposition directory is invalid."); + + } + + String start = startDate.getText(); + if (start == null || start.trim().isEmpty()) + throw new Exception("Start date field is empty."); + + if (start.trim().length() != 8) + throw new Exception("Start date value is invalid."); + + if (start.trim().charAt(0) == '0') + throw new Exception("Start date value is invalid."); + + String end = endDate.getText(); + if (end == null || end.trim().isEmpty()) + throw new Exception("End date field is empty."); + + if (end.trim().length() != 8) + throw new Exception("End date value is invalid."); + + if (end.trim().charAt(0) == '0') + throw new Exception("End date value is invalid."); + + outMessages += "Epic base: " + baseDir + ls; + outMessages += "SA home: " + sahome + ls; + outMessages += "Scen directory: " + scenarioDir + ls; + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + + final String jobFile = writeRunScriptScript(baseDir, scenarioDir, sahome); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir); + } else { + batchFile = null; + } + Thread populateThread = new Thread(new Runnable() { + public void run() { + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + // final String batchFile = writeBatchFile(jobFile, + // scenarioDir); + runBatchScript(batchFile, jobFile); + } + + } + }); + populateThread.start(); + } + + // This is legacy code that has been moved to it's own method + protected void writeScriptFile(String file, String content) { + + String mesg = ""; + + try { + File script = new File(file); + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(content); + out.close(); + + mesg += "Script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + + } catch (IOException e) { + // printStackTrace(); + // g.error("Error generating EPIC script file", e); + app.showMessage("Write script", e.getMessage()); + } + + app.showMessage("Write script", mesg); + } + + protected String writeBatchFile(String jobFile, String scenarioDir) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String batchFile = scenarioDir.trim() + "/scripts"; + if (!batchFile.endsWith(System.getProperty("file.separator"))) + batchFile += System.getProperty("file.separator"); + batchFile += "submitSiteDailyWeather" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh" + ls + ls); + + // TODO - add #SBATCH options here + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage == null || qSingModule.trim().isEmpty()) { + throw new Exception("Singularity image path must be specified"); + } + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + jobFile); + } else { + sb.append(jobFile); + } + + writeScriptFile(batchFile, sb.toString()); + + return batchFile; + } + + + protected String writeRunScriptScript(String baseDir, String scenarioDir, String sahome) throws Exception { + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + + String file = scenarioDir.trim() + "/scripts"; + file += "/generateEPICsiteDailyWeatherfromMCIP_CAMQ_" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + + sb.append(getScriptHeader() + ls); + sb.append("#" + ls + "# Set up runtime environment" + ls + "#" + ls); + sb.append("source " + sahome.trim() + Constants.SA_SETUP_FILE + ls + ls); + + sb.append("setenv EPIC_DIR " + baseDir + ls); + sb.append("setenv SCEN_DIR " + scenarioDir + ls); + sb.append("setenv SA_HOME " + sahome + ls); + sb.append("source $SA_HOME/" + Constants.SA_SETUP_FILE + ls + ls); + + sb.append("#" + ls + "# Define MCIP domain grid information" + ls + "#" + ls); + sb.append("setenv GRID_PROJ \"" + proj4proj.getText().trim() + "\"" + ls + ls); + sb.append("setenv GRID_ROWS " + ((Number) rows.getValue()).intValue() + ls); + sb.append("setenv GRID_COLUMNS " + ((Number) cols.getValue()).intValue() + ls + ls); + sb.append("setenv GRID_XMIN " + ((Number) xmin.getValue()).doubleValue() + ls); + sb.append("setenv GRID_YMIN " + ((Number) ymin.getValue()).doubleValue() + ls + ls); + sb.append("setenv GRID_XCELLSIZE " + ((Number) xSize.getValue()).doubleValue() + ls); + sb.append("setenv GRID_YCELLSIZE " + ((Number) ySize.getValue()).doubleValue() + ls + ls); + sb.append("setenv GRID_NAME \"" + (gridName.getText() == null ? "" : gridName.getText().trim()) + "\"" + ls + + ls); + sb.append("#" + ls + "#Set MCIP data directory which containts daily MCIP files" + ls + + "#Daily MCIP data files have to have names with METCRO2D*\"date\"" + ls + + "#The \"date\" can be in one of the format: YYYYMMDD, YYMMDD, YYYYDDD, YYDDD" + ls + "#" + ls); + + sb.append("setenv DATA_DIR \"" + mdataDir.getText() + "\"" + ls + ls); + sb.append("#" + ls + "#Set CMAQ output dry/wet deposition data directory which containts daily CMAQ files" + ls + + "#" + ls); + + String dataDirCmaq = ""; + if (depositionSel.getSelectedItem().equals("Zero")) + dataDirCmaq = "Zero"; + else if (depositionSel.getSelectedItem().equals("Default")) + dataDirCmaq = "Default"; + else + dataDirCmaq = depositionDir.getText().trim(); + sb.append("setenv DATA_DIR_CMAQ \"" + dataDirCmaq + "\"" + ls + ls); + sb.append("#" + ls + "#Set date range: YYYYMMDD" + ls + "#" + ls); + sb.append("setenv START_DATE " + startDate.getText() + ls); + sb.append("setenv END_DATE " + endDate.getText() + ls + ls); + sb.append("#" + ls + "#Set input EPIC site data file in ascii csv format as: site_name,longitude,latitude" + ls + + "#" + ls); + sb.append("setenv EPIC_SITE_FILE \"$SCEN_DIR/share_data/allSites_Info.csv" + "\"" + ls + ls); + sb.append("#" + ls + "# Set output directory which will store created EPIC site daily weather files:" + ls + + "# 1. \"site_name\".dly 2. WXPMRUN.DAT " + ls + "#" + ls); + + sb.append("setenv OUTPUT_DATA_DIR $SCEN_DIR/share_data/ " + ls + ls); + sb.append("#" + ls + "# Set NetCDF output file to store computed EPIC site daily weather and N deposition data" + + ls + "# Only set this variable when EPIC grids are the same as MCIP/CMAQ grids." + ls + + "# Otherwise, set it to NONE for no NetCDF file output" + ls + "#" + ls); + sb.append("setenv OUTPUT_NETCDF_FILE $SCEN_DIR/share_data/site_weather_dep_${START_DATE}_to_${END_DATE}.nc" + + ls + ls); + + String dlyYN = dlyBox.isSelected() ? "YES" : "NO"; + sb.append("setenv WRITE_DLY " + dlyYN + ls); + + sb.append("$SA_HOME/bin/64bits/computeSiteDailyWeather.exe" + ls + ls); + + sb.append(" if ( $status == 0 ) then " + ls); + sb.append(" echo ==== Finished MCIP/CMAQ to EPIC run. " + ls); + + sb.append(" cp $OUTPUT_NETCDF_FILE $SCEN_DIR/share_data/site_weather_dep.nc" + ls); + + if (dlyBox.isSelected()) { + sb.append(" echo ==== Consolidating dly files. " + ls); + sb.append( + " (cd $SCEN_DIR/share_data/dailyWETH && tar -czf dly_${START_DATE}_to_${END_DATE}.tar.gz *.dly --remove-files)" + + ls); + } + // end if statement + + sb.append(" else " + ls); + sb.append(" echo ==== Error in MCIP/CMAQ to EPIC runs." + ls + ls); + sb.append(" echo " + ls); + sb.append(" endif " + ls); + sb.append("#===================================================================" + ls); + + String mesg = ""; + try { + File script = new File(file); + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + + mesg += "Created a script file: " + file + "\n"; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + } catch (IOException e) { + throw new Exception(e.getMessage()); + } + app.showMessage("Write script", mesg); + return file; + } + + private String getScriptHeader() { + StringBuilder sb = new StringBuilder(); + String ls = "\n"; + sb.append("#!/bin/csh -f" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: to extract six daily weather variable data from MCIP data for EPIC modeling" + ls); + sb.append("# sites and to create WXPMRUN.DAT run data file for WXPM3020 to compute" + ls); + sb.append("# monthly climate data." + ls); + sb.append("#" + ls); + sb.append("# 1. Radiation (MJ m^02, daily total)" + ls); + sb.append("# 2. Tmax (C, daily)" + ls); + sb.append("# 3. Tmin (C, daily)" + ls); + sb.append("# 4. Precipitation (mm, daily total)" + ls); + sb.append("# 5. Relative humidity (fraction, daily average)" + ls); + sb.append("# 6. Windspeed (m s^-1, daily average)" + ls); + sb.append("" + ls); + sb.append("# There are three steps involved in extraction:" + ls); + sb.append("# 1. read in EPIC site lat and long location data, project them into MCIP data projection and" + + ls); + sb.append("# convert them into column and row in MCIP grids." + ls); + sb.append( + "# 2. loop through each day MCIP data to extract daily weather variables for each EPIC site" + ls); + sb.append("# and to write them into each EPIC site daily weather file." + ls); + sb.append( + "# 3. created WXPMRUN.DAT file for all generated EPIC daily weather files in order to run WXPM3020.DRB program." + + ls); + sb.append( + "# The program computes monthly weather data to be named in monthly weather list file like WPM1US.DAT." + + ls); + sb.append("#" + ls); + sb.append("# Output files:" + ls); + sb.append("# 1. \"site_name\".dly - EPIC daily weather input file " + ls); + sb.append("# 2. WXPMRUN.DAT - to WXPM3020.DRB for computing EPIC monthly weather" + ls); + sb.append("#" + ls); + sb.append("# Written by the Institute for the Environment at UNC, Chapel Hill" + ls); + sb.append("# in support of the EPA CMAS Modeling, 2009." + ls); + sb.append("#" + ls); + sb.append("# Written by: L. R., Aug. 2009" + ls); + sb.append("# Modified by:" + ls); + sb.append("#" + ls); + sb.append("# Call program: computeSiteDailyWeather.exe" + ls); + sb.append("# Needed environment variables listed in this run script file." + ls); + sb.append("#" + ls); + sb.append("# Usage: ./generateEPICsiteDailyWeatherfromMCIP.csh" + ls); + + sb.append("#***************************************************************************************" + ls + ls); + + return sb.toString(); + } + + private void runScript(final String file) { + String log = file + ".log"; + + outMessages += "Script file: " + file + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + FileRunner.runScript(file, log, msg); + } + + private void runBatchScript(final String batchFile, final String jobFile) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qMc2Epic = Constants.getProperty(Constants.QUEUE_MC2EPIC, msg); + + File script = new File(batchFile.replaceAll("\\\\", "\\\\\\\\")); + + sb.append(qcmd + " " + qMc2Epic + " -o " + log + " " + script.getAbsolutePath()); + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } + + @Override + public void projectLoaded() { + fields = (Mcip2EpicFields) app.getProject().getPage(fields.getName()); + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + if (fields != null) { + String scenloc = domain.getScenarioDir(); + if (scenloc != null && scenloc.trim().length() > 0) + this.scenarioDir.setText(scenloc); + else + this.scenarioDir.setText(fields.getScenarioDir()); + rows.setValue(fields.getRows()); + cols.setValue(fields.getCols()); + xSize.setValue(fields.getXcellSize()); + ySize.setValue(fields.getYcellSize()); + xmin.setValue(fields.getXmin()); + ymin.setValue(fields.getYmin()); + proj4proj.setText(fields.getProj()); + + if (fields.getGridName() != null) + this.gridName.setText(fields.getGridName()); + try { + startDate.setValue(NumberFormat.getNumberInstance() + .parse(fields.getStartdate() == null ? "" : fields.getStartdate())); + endDate.setValue( + NumberFormat.getNumberInstance().parse(fields.getEnddate() == null ? "" : fields.getEnddate())); + } catch (ParseException e) { + // NOTE: no-op; + } + mdataDir.setText(fields.getDatadir()); + depositionSel.setSelectedItem(fields.getDepSelection()); + depositionDir.setText(fields.getCmaqDepsDir()); + this.runMessages.setText(fields.getMessage()); + } else { + newProjectCreated(); + } + + } + + @Override + public void saveProjectRequested() { + if (scenarioDir != null) + domain.setScenarioDir(scenarioDir.getText() == null ? "" : scenarioDir.getText()); + if (scenarioDir != null) + fields.setScenarioDir(scenarioDir.getText()); + if (rows != null) + fields.setRows(Integer.parseInt(rows.getText() == null ? "" : rows.getValue() + "")); + if (cols != null) + fields.setCols(Integer.parseInt(cols.getText() == null ? "" : cols.getValue() + "")); + if (xSize != null) + fields.setXcellSize(Float.parseFloat(xSize.getText() == null ? "" : xSize.getValue() + "")); + if (ySize != null) + fields.setYcellSize(Float.parseFloat(ySize.getText() == null ? "" : ySize.getValue() + "")); + if (xmin != null) + fields.setXmin(Float.parseFloat(xmin.getText() == null ? "" : xmin.getValue() + "")); + if (ymin != null) + fields.setYmin(Float.parseFloat(ymin.getText() == null ? "" : ymin.getValue() + "")); + if (proj4proj != null) + fields.setProj(proj4proj.getText() == null ? "" : proj4proj.getText()); + if (gridName != null) + fields.setGridName(gridName.getText() == null ? "" : gridName.getText()); + if (startDate != null) + fields.setStartdate(startDate.getValue() == null ? "" : startDate.getText()); + if (endDate != null) + fields.setEnddate(endDate.getValue() == null ? "" : endDate.getText()); + + if (depositionSel != null) + fields.setDepSelection((String) depositionSel.getSelectedItem()); + if (depositionDir != null) + fields.setCmaqDepsDir(depositionDir.getText()); + if (mdataDir != null) + fields.setDatadir(mdataDir.getText()); + if (runMessages != null) + fields.setMessage(runMessages.getText()); + } + + @Override + public void newProjectCreated() { + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + scenarioDir.setText(domain.getScenarioDir()); + rows.setValue(domain.getRows()); + cols.setValue(domain.getCols()); + xmin.setValue(domain.getXmin()); + ymin.setValue(domain.getYmin()); + xSize.setValue(domain.getXcellSize()); + ySize.setValue(domain.getYcellSize()); + proj4proj.setText(domain.getProj()); + + gridName.setText(domain.getGridName()); + mdataDir.setText(""); + depositionSel.setSelectedItem(0); + depositionDir.setText(""); + + this.runMessages.setText(""); + try { + startDate.setValue(NumberFormat.getNumberInstance().parse(domain.getSimYear().trim() + "0101")); + endDate.setValue(NumberFormat.getNumberInstance().parse(domain.getSimYear().trim() + "1231")); + } catch (ParseException e) { + startDate.setValue(0); + endDate.setValue(0); + } + if (fields == null) { + fields = new Mcip2EpicFields(); + app.getProject().addPage(fields); + } + } + +} diff --git a/festc_core/src/gov/epa/festc/gui/PlotEventListener.java b/festc_core/src/gov/epa/festc/gui/PlotEventListener.java index cfe1ecc..f6b07fc 100644 --- a/festc_core/src/gov/epa/festc/gui/PlotEventListener.java +++ b/festc_core/src/gov/epa/festc/gui/PlotEventListener.java @@ -1,9 +1,9 @@ -package gov.epa.festc.gui; - -public interface PlotEventListener { - void newProjectCreated(); - - void projectLoaded(); - - void saveProjectRequested(); -} +package gov.epa.festc.gui; + +public interface PlotEventListener { + void newProjectCreated(); + + void projectLoaded(); + + void saveProjectRequested(); +} diff --git a/festc_core/src/gov/epa/festc/gui/ScrollablePanel.java b/festc_core/src/gov/epa/festc/gui/ScrollablePanel.java index 8984bd5..bc488c7 100644 --- a/festc_core/src/gov/epa/festc/gui/ScrollablePanel.java +++ b/festc_core/src/gov/epa/festc/gui/ScrollablePanel.java @@ -1,376 +1,376 @@ -package gov.epa.festc.gui; - -import java.awt.*; - -import javax.swing.*; - -/** - * A panel that implements the Scrollable interface. This class allows you - * to customize the scrollable features by using newly provided setter methods - * so you don't have to extend this class every time. - * - * Scrollable amounts can be specifed as a percentage of the viewport size or - * as an actual pixel value. The amount can be changed for both unit and block - * scrolling for both horizontal and vertical scrollbars. - * - * The Scrollable interface only provides a boolean value for determining whether - * or not the viewport size (width or height) should be used by the scrollpane - * when determining if scrollbars should be made visible. This class supports the - * concept of dynamically changing this value based on the size of the viewport. - * In this case the viewport size will only be used when it is larger than the - * panels size. This has the effect of ensuring the viewport is always full as - * components added to the panel will be size to fill the area available, - * based on the rules of the applicable layout manager of course. - */ -public class ScrollablePanel extends JPanel - implements Scrollable, SwingConstants -{ - public enum ScrollableSizeHint - { - NONE, - FIT, - STRETCH; - } - - public enum IncrementType - { - PERCENT, - PIXELS; - } - - private ScrollableSizeHint scrollableHeight = ScrollableSizeHint.NONE; - private ScrollableSizeHint scrollableWidth = ScrollableSizeHint.NONE; - - private IncrementInfo horizontalBlock; - private IncrementInfo horizontalUnit; - private IncrementInfo verticalBlock; - private IncrementInfo verticalUnit; - - private Dimension maxSize; - private Dimension preferedSize; - - /** - * Default constructor that uses a FlowLayout - */ - public ScrollablePanel() - { - this( new FlowLayout() ); - } - - /** - * Constuctor for specifying the LayoutManager of the panel. - * - * @param layout the LayountManger for the panel - */ - public ScrollablePanel(LayoutManager layout) - { - super( layout ); - - IncrementInfo block = new IncrementInfo(IncrementType.PERCENT, 100); - IncrementInfo unit = new IncrementInfo(IncrementType.PERCENT, 10); - - setScrollableBlockIncrement(HORIZONTAL, block); - setScrollableBlockIncrement(VERTICAL, block); - setScrollableUnitIncrement(HORIZONTAL, unit); - setScrollableUnitIncrement(VERTICAL, unit); - - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - int maxWidth = (int) (screenSize.getWidth()*0.7); - int maxHeight = (int) (screenSize.getHeight()*0.7); - int preferedWidth = (int) (screenSize.getWidth()/3); - int preferedHeight = (int) (screenSize.getHeight()/2); - maxSize = new Dimension(maxWidth, maxHeight); - preferedSize = new Dimension(preferedWidth, preferedHeight); - } - - /** - * Get the height ScrollableSizeHint enum - * - * @return the ScrollableSizeHint enum for the height - */ - public ScrollableSizeHint getScrollableHeight() - { - return scrollableHeight; - } - - /** - * Set the ScrollableSizeHint enum for the height. The enum is used to - * determine the boolean value that is returned by the - * getScrollableTracksViewportHeight() method. The valid values are: - * - * ScrollableSizeHint.NONE - return "false", which causes the height - * of the panel to be used when laying out the children - * ScrollableSizeHint.FIT - return "true", which causes the height of - * the viewport to be used when laying out the children - * ScrollableSizeHint.STRETCH - return "true" when the viewport height - * is greater than the height of the panel, "false" otherwise. - * - * @param scrollableHeight as represented by the ScrollableSizeHint enum. - */ - public void setScrollableHeight(ScrollableSizeHint scrollableHeight) - { - this.scrollableHeight = scrollableHeight; - revalidate(); - } - - /** - * Get the width ScrollableSizeHint enum - * - * @return the ScrollableSizeHint enum for the width - */ - public ScrollableSizeHint getScrollableWidth() - { - return scrollableWidth; - } - - /** - * Set the ScrollableSizeHint enum for the width. The enum is used to - * determine the boolean value that is returned by the - * getScrollableTracksViewportWidth() method. The valid values are: - * - * ScrollableSizeHint.NONE - return "false", which causes the width - * of the panel to be used when laying out the children - * ScrollableSizeHint.FIT - return "true", which causes the width of - * the viewport to be used when laying out the children - * ScrollableSizeHint.STRETCH - return "true" when the viewport width - * is greater than the width of the panel, "false" otherwise. - * - * @param scrollableWidth as represented by the ScrollableSizeHint enum. - */ - public void setScrollableWidth(ScrollableSizeHint scrollableWidth) - { - this.scrollableWidth = scrollableWidth; - revalidate(); - } - - /** - * Get the block IncrementInfo for the specified orientation - * - * @return the block IncrementInfo for the specified orientation - */ - public IncrementInfo getScrollableBlockIncrement(int orientation) - { - return orientation == SwingConstants.HORIZONTAL ? horizontalBlock : verticalBlock; - } - - /** - * Specify the information needed to do block scrolling. - * - * @param orientation specify the scrolling orientation. Must be either: - * SwingContants.HORIZONTAL or SwingContants.VERTICAL. - * @paran type specify how the amount parameter in the calculation of - * the scrollable amount. Valid values are: - * IncrementType.PERCENT - treat the amount as a % of the viewport size - * IncrementType.PIXEL - treat the amount as the scrollable amount - * @param amount a value used with the IncrementType to determine the - * scrollable amount - */ - public void setScrollableBlockIncrement(int orientation, IncrementType type, int amount) - { - IncrementInfo info = new IncrementInfo(type, amount); - setScrollableBlockIncrement(orientation, info); - } - - /** - * Specify the information needed to do block scrolling. - * - * @param orientation specify the scrolling orientation. Must be either: - * SwingContants.HORIZONTAL or SwingContants.VERTICAL. - * @param info An IncrementInfo object containing information of how to - * calculate the scrollable amount. - */ - public void setScrollableBlockIncrement(int orientation, IncrementInfo info) - { - switch(orientation) - { - case SwingConstants.HORIZONTAL: - horizontalBlock = info; - break; - case SwingConstants.VERTICAL: - verticalBlock = info; - break; - default: - throw new IllegalArgumentException("Invalid orientation: " + orientation); - } - } - - /** - * Get the unit IncrementInfo for the specified orientation - * - * @return the unit IncrementInfo for the specified orientation - */ - public IncrementInfo getScrollableUnitIncrement(int orientation) - { - return orientation == SwingConstants.HORIZONTAL ? horizontalUnit : verticalUnit; - } - - /** - * Specify the information needed to do unit scrolling. - * - * @param orientation specify the scrolling orientation. Must be either: - * SwingContants.HORIZONTAL or SwingContants.VERTICAL. - * @paran type specify how the amount parameter in the calculation of - * the scrollable amount. Valid values are: - * IncrementType.PERCENT - treat the amount as a % of the viewport size - * IncrementType.PIXEL - treat the amount as the scrollable amount - * @param amount a value used with the IncrementType to determine the - * scrollable amount - */ - public void setScrollableUnitIncrement(int orientation, IncrementType type, int amount) - { - IncrementInfo info = new IncrementInfo(type, amount); - setScrollableUnitIncrement(orientation, info); - } - - /** - * Specify the information needed to do unit scrolling. - * - * @param orientation specify the scrolling orientation. Must be either: - * SwingContants.HORIZONTAL or SwingContants.VERTICAL. - * @param info An IncrementInfo object containing information of how to - * calculate the scrollable amount. - */ - public void setScrollableUnitIncrement(int orientation, IncrementInfo info) - { - switch(orientation) - { - case SwingConstants.HORIZONTAL: - horizontalUnit = info; - break; - case SwingConstants.VERTICAL: - verticalUnit = info; - break; - default: - throw new IllegalArgumentException("Invalid orientation: " + orientation); - } - } - -// Implement Scrollable interface - - public Dimension getPreferredScrollableViewportSize() - { - return preferedSize; //getPreferredSize(); - } - - public int getScrollableUnitIncrement( - Rectangle visible, int orientation, int direction) - { - switch(orientation) - { - case SwingConstants.HORIZONTAL: - return getScrollableIncrement(horizontalUnit, visible.width); - case SwingConstants.VERTICAL: - return getScrollableIncrement(verticalUnit, visible.height); - default: - throw new IllegalArgumentException("Invalid orientation: " + orientation); - } - } - - public int getScrollableBlockIncrement( - Rectangle visible, int orientation, int direction) - { - switch(orientation) - { - case SwingConstants.HORIZONTAL: - return getScrollableIncrement(horizontalBlock, visible.width); - case SwingConstants.VERTICAL: - return getScrollableIncrement(verticalBlock, visible.height); - default: - throw new IllegalArgumentException("Invalid orientation: " + orientation); - } - } - - protected int getScrollableIncrement(IncrementInfo info, int distance) - { - if (info.getIncrement() == IncrementType.PIXELS) - return info.getAmount(); - else - return distance * info.getAmount() / 100; - } - - public boolean getScrollableTracksViewportWidth() - { - if (scrollableWidth == ScrollableSizeHint.NONE) - return false; - - if (scrollableWidth == ScrollableSizeHint.FIT) - return true; - - // STRETCH sizing, use the greater of the panel or viewport width - - if (getParent() instanceof JViewport) - { - return (((JViewport)getParent()).getWidth() > getPreferredSize().width); - } - - return false; - } - - public boolean getScrollableTracksViewportHeight() - { - if (scrollableHeight == ScrollableSizeHint.NONE) - return false; - - if (scrollableHeight == ScrollableSizeHint.FIT) - return true; - - // STRETCH sizing, use the greater of the panel or viewport height - - - if (getParent() instanceof JViewport) - { - return (((JViewport)getParent()).getHeight() > getPreferredSize().height); - } - - return false; - } - - public void setMaxSize(Dimension maxSize) { - this.maxSize = maxSize; - } - - public Dimension getMaxSize() { - return maxSize; - } - - public void setPreferedSize(Dimension preferedSize) { - this.preferedSize = preferedSize; - } - - public Dimension getPreferedSize() { - return preferedSize; - } - - /** - * Helper class to hold the information required to calculate the scroll amount. - */ - static class IncrementInfo - { - private IncrementType type; - private int amount; - - public IncrementInfo(IncrementType type, int amount) - { - this.type = type; - this.amount = amount; - } - - public IncrementType getIncrement() - { - return type; - } - - public int getAmount() - { - return amount; - } - - public String toString() - { - return - "ScrollablePanel[" + - type + ", " + - amount + "]"; - } - } -} +package gov.epa.festc.gui; + +import java.awt.*; + +import javax.swing.*; + +/** + * A panel that implements the Scrollable interface. This class allows you + * to customize the scrollable features by using newly provided setter methods + * so you don't have to extend this class every time. + * + * Scrollable amounts can be specifed as a percentage of the viewport size or + * as an actual pixel value. The amount can be changed for both unit and block + * scrolling for both horizontal and vertical scrollbars. + * + * The Scrollable interface only provides a boolean value for determining whether + * or not the viewport size (width or height) should be used by the scrollpane + * when determining if scrollbars should be made visible. This class supports the + * concept of dynamically changing this value based on the size of the viewport. + * In this case the viewport size will only be used when it is larger than the + * panels size. This has the effect of ensuring the viewport is always full as + * components added to the panel will be size to fill the area available, + * based on the rules of the applicable layout manager of course. + */ +public class ScrollablePanel extends JPanel + implements Scrollable, SwingConstants +{ + public enum ScrollableSizeHint + { + NONE, + FIT, + STRETCH; + } + + public enum IncrementType + { + PERCENT, + PIXELS; + } + + private ScrollableSizeHint scrollableHeight = ScrollableSizeHint.NONE; + private ScrollableSizeHint scrollableWidth = ScrollableSizeHint.NONE; + + private IncrementInfo horizontalBlock; + private IncrementInfo horizontalUnit; + private IncrementInfo verticalBlock; + private IncrementInfo verticalUnit; + + private Dimension maxSize; + private Dimension preferedSize; + + /** + * Default constructor that uses a FlowLayout + */ + public ScrollablePanel() + { + this( new FlowLayout() ); + } + + /** + * Constuctor for specifying the LayoutManager of the panel. + * + * @param layout the LayountManger for the panel + */ + public ScrollablePanel(LayoutManager layout) + { + super( layout ); + + IncrementInfo block = new IncrementInfo(IncrementType.PERCENT, 100); + IncrementInfo unit = new IncrementInfo(IncrementType.PERCENT, 10); + + setScrollableBlockIncrement(HORIZONTAL, block); + setScrollableBlockIncrement(VERTICAL, block); + setScrollableUnitIncrement(HORIZONTAL, unit); + setScrollableUnitIncrement(VERTICAL, unit); + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + int maxWidth = (int) (screenSize.getWidth()*0.7); + int maxHeight = (int) (screenSize.getHeight()*0.7); + int preferedWidth = (int) (screenSize.getWidth()/3); + int preferedHeight = (int) (screenSize.getHeight()/2); + maxSize = new Dimension(maxWidth, maxHeight); + preferedSize = new Dimension(preferedWidth, preferedHeight); + } + + /** + * Get the height ScrollableSizeHint enum + * + * @return the ScrollableSizeHint enum for the height + */ + public ScrollableSizeHint getScrollableHeight() + { + return scrollableHeight; + } + + /** + * Set the ScrollableSizeHint enum for the height. The enum is used to + * determine the boolean value that is returned by the + * getScrollableTracksViewportHeight() method. The valid values are: + * + * ScrollableSizeHint.NONE - return "false", which causes the height + * of the panel to be used when laying out the children + * ScrollableSizeHint.FIT - return "true", which causes the height of + * the viewport to be used when laying out the children + * ScrollableSizeHint.STRETCH - return "true" when the viewport height + * is greater than the height of the panel, "false" otherwise. + * + * @param scrollableHeight as represented by the ScrollableSizeHint enum. + */ + public void setScrollableHeight(ScrollableSizeHint scrollableHeight) + { + this.scrollableHeight = scrollableHeight; + revalidate(); + } + + /** + * Get the width ScrollableSizeHint enum + * + * @return the ScrollableSizeHint enum for the width + */ + public ScrollableSizeHint getScrollableWidth() + { + return scrollableWidth; + } + + /** + * Set the ScrollableSizeHint enum for the width. The enum is used to + * determine the boolean value that is returned by the + * getScrollableTracksViewportWidth() method. The valid values are: + * + * ScrollableSizeHint.NONE - return "false", which causes the width + * of the panel to be used when laying out the children + * ScrollableSizeHint.FIT - return "true", which causes the width of + * the viewport to be used when laying out the children + * ScrollableSizeHint.STRETCH - return "true" when the viewport width + * is greater than the width of the panel, "false" otherwise. + * + * @param scrollableWidth as represented by the ScrollableSizeHint enum. + */ + public void setScrollableWidth(ScrollableSizeHint scrollableWidth) + { + this.scrollableWidth = scrollableWidth; + revalidate(); + } + + /** + * Get the block IncrementInfo for the specified orientation + * + * @return the block IncrementInfo for the specified orientation + */ + public IncrementInfo getScrollableBlockIncrement(int orientation) + { + return orientation == SwingConstants.HORIZONTAL ? horizontalBlock : verticalBlock; + } + + /** + * Specify the information needed to do block scrolling. + * + * @param orientation specify the scrolling orientation. Must be either: + * SwingContants.HORIZONTAL or SwingContants.VERTICAL. + * @paran type specify how the amount parameter in the calculation of + * the scrollable amount. Valid values are: + * IncrementType.PERCENT - treat the amount as a % of the viewport size + * IncrementType.PIXEL - treat the amount as the scrollable amount + * @param amount a value used with the IncrementType to determine the + * scrollable amount + */ + public void setScrollableBlockIncrement(int orientation, IncrementType type, int amount) + { + IncrementInfo info = new IncrementInfo(type, amount); + setScrollableBlockIncrement(orientation, info); + } + + /** + * Specify the information needed to do block scrolling. + * + * @param orientation specify the scrolling orientation. Must be either: + * SwingContants.HORIZONTAL or SwingContants.VERTICAL. + * @param info An IncrementInfo object containing information of how to + * calculate the scrollable amount. + */ + public void setScrollableBlockIncrement(int orientation, IncrementInfo info) + { + switch(orientation) + { + case SwingConstants.HORIZONTAL: + horizontalBlock = info; + break; + case SwingConstants.VERTICAL: + verticalBlock = info; + break; + default: + throw new IllegalArgumentException("Invalid orientation: " + orientation); + } + } + + /** + * Get the unit IncrementInfo for the specified orientation + * + * @return the unit IncrementInfo for the specified orientation + */ + public IncrementInfo getScrollableUnitIncrement(int orientation) + { + return orientation == SwingConstants.HORIZONTAL ? horizontalUnit : verticalUnit; + } + + /** + * Specify the information needed to do unit scrolling. + * + * @param orientation specify the scrolling orientation. Must be either: + * SwingContants.HORIZONTAL or SwingContants.VERTICAL. + * @paran type specify how the amount parameter in the calculation of + * the scrollable amount. Valid values are: + * IncrementType.PERCENT - treat the amount as a % of the viewport size + * IncrementType.PIXEL - treat the amount as the scrollable amount + * @param amount a value used with the IncrementType to determine the + * scrollable amount + */ + public void setScrollableUnitIncrement(int orientation, IncrementType type, int amount) + { + IncrementInfo info = new IncrementInfo(type, amount); + setScrollableUnitIncrement(orientation, info); + } + + /** + * Specify the information needed to do unit scrolling. + * + * @param orientation specify the scrolling orientation. Must be either: + * SwingContants.HORIZONTAL or SwingContants.VERTICAL. + * @param info An IncrementInfo object containing information of how to + * calculate the scrollable amount. + */ + public void setScrollableUnitIncrement(int orientation, IncrementInfo info) + { + switch(orientation) + { + case SwingConstants.HORIZONTAL: + horizontalUnit = info; + break; + case SwingConstants.VERTICAL: + verticalUnit = info; + break; + default: + throw new IllegalArgumentException("Invalid orientation: " + orientation); + } + } + +// Implement Scrollable interface + + public Dimension getPreferredScrollableViewportSize() + { + return preferedSize; //getPreferredSize(); + } + + public int getScrollableUnitIncrement( + Rectangle visible, int orientation, int direction) + { + switch(orientation) + { + case SwingConstants.HORIZONTAL: + return getScrollableIncrement(horizontalUnit, visible.width); + case SwingConstants.VERTICAL: + return getScrollableIncrement(verticalUnit, visible.height); + default: + throw new IllegalArgumentException("Invalid orientation: " + orientation); + } + } + + public int getScrollableBlockIncrement( + Rectangle visible, int orientation, int direction) + { + switch(orientation) + { + case SwingConstants.HORIZONTAL: + return getScrollableIncrement(horizontalBlock, visible.width); + case SwingConstants.VERTICAL: + return getScrollableIncrement(verticalBlock, visible.height); + default: + throw new IllegalArgumentException("Invalid orientation: " + orientation); + } + } + + protected int getScrollableIncrement(IncrementInfo info, int distance) + { + if (info.getIncrement() == IncrementType.PIXELS) + return info.getAmount(); + else + return distance * info.getAmount() / 100; + } + + public boolean getScrollableTracksViewportWidth() + { + if (scrollableWidth == ScrollableSizeHint.NONE) + return false; + + if (scrollableWidth == ScrollableSizeHint.FIT) + return true; + + // STRETCH sizing, use the greater of the panel or viewport width + + if (getParent() instanceof JViewport) + { + return (((JViewport)getParent()).getWidth() > getPreferredSize().width); + } + + return false; + } + + public boolean getScrollableTracksViewportHeight() + { + if (scrollableHeight == ScrollableSizeHint.NONE) + return false; + + if (scrollableHeight == ScrollableSizeHint.FIT) + return true; + + // STRETCH sizing, use the greater of the panel or viewport height + + + if (getParent() instanceof JViewport) + { + return (((JViewport)getParent()).getHeight() > getPreferredSize().height); + } + + return false; + } + + public void setMaxSize(Dimension maxSize) { + this.maxSize = maxSize; + } + + public Dimension getMaxSize() { + return maxSize; + } + + public void setPreferedSize(Dimension preferedSize) { + this.preferedSize = preferedSize; + } + + public Dimension getPreferedSize() { + return preferedSize; + } + + /** + * Helper class to hold the information required to calculate the scroll amount. + */ + static class IncrementInfo + { + private IncrementType type; + private int amount; + + public IncrementInfo(IncrementType type, int amount) + { + this.type = type; + this.amount = amount; + } + + public IncrementType getIncrement() + { + return type; + } + + public int getAmount() + { + return amount; + } + + public String toString() + { + return + "ScrollablePanel[" + + type + ", " + + amount + "]"; + } + } +} diff --git a/festc_core/src/gov/epa/festc/gui/ToolsPanel.java b/festc_core/src/gov/epa/festc/gui/ToolsPanel.java index 84a8d23..ef7ffbd 100644 --- a/festc_core/src/gov/epa/festc/gui/ToolsPanel.java +++ b/festc_core/src/gov/epa/festc/gui/ToolsPanel.java @@ -1,188 +1,188 @@ -package gov.epa.festc.gui; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.core.FestcConstants; -import gov.epa.festc.util.Constants; -import gov.epa.festc.util.SpringLayoutGenerator; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SpringLayout; -import javax.swing.SwingConstants; -import javax.swing.UIManager; - -public class ToolsPanel extends JPanel { - private static final long serialVersionUID = 8082261605112772487L; - private FestcApplication app; - - public ToolsPanel(FestcApplication festcApp) { - app = festcApp; - add(createPanel()); - super.requestFocusInWindow(); - } - - private JPanel createPanel() { - JPanel main = new JPanel(new BorderLayout()); - main.add(getNorthPanel(), BorderLayout.NORTH); - main.add(getCenterPanel(), BorderLayout.CENTER); - Dimension d = main.getMinimumSize(); - d.width = 120; - main.setMinimumSize(d); - d = main.getMaximumSize(); - d.width = 120; - main.setMaximumSize(d); - return main; - } - - private JPanel getNorthPanel() { - JPanel panel = new JPanel(); - JLabel title = new JLabel( - "FEST-C Tools", //"Fertilizer Emission Scenario Tool for CMAQ (FEST-C)", // Tools", - SwingConstants.CENTER); - title.setFont(new Font("Default", Font.BOLD, 20)); - - panel.add(title); - panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); - - return panel; - } - - private JPanel getCenterPanel() { - JPanel panel = new JPanel(new SpringLayout()); - SpringLayoutGenerator layout = new SpringLayoutGenerator(); - //hsb = Color.RGBtoHSB(r,g,b,hsb); - - JGradientButton landUsebutton = new JGradientButton(buttonAction(Constants.BELD4_GEN, FestcConstants.BELD4_VIEW), - Color.getHSBColor(210f / 360, 0.25f, 0.95f)); - JGradientButton sitegenbutton = new JGradientButton(buttonAction(Constants.SITE_INFO, FestcConstants.SITE_INFO_VIEW), - Color.getHSBColor(210f / 360, 0.25f, 0.95f)); - JGradientButton m2pbutton = new JGradientButton(buttonAction(Constants.MC2EPIC, FestcConstants.MCIP2EPIC_VIEW), - Color.getHSBColor(210f / 360, 0.25f, 0.95f)); - JGradientButton sitefilebutton = new JGradientButton(buttonAction(Constants.EPIC_SITE, FestcConstants.SITE_FILE_VIEW), - Color.getHSBColor(120f / 360, 0.25f, 0.95f)); - JGradientButton genbutton = new JGradientButton(buttonAction(Constants.SOIL_MATCH, FestcConstants.GEN_SOIL_MAN_FILES_VIEW), - Color.getHSBColor(120f / 360, 0.25f, 0.95f)); - JGradientButton manfilespinbutton = new JGradientButton(buttonAction(Constants.MAN_SPINUP, FestcConstants.MAN_FILE_SPINUP_VIEW), - Color.getHSBColor(120f / 360, 0.25f, 0.95f)); - JGradientButton modbutton = new JGradientButton(buttonAction(Constants.EDIT_INFILES, FestcConstants.MANAGE_VIEW), - Color.getHSBColor(50f / 360, 0.25f, 0.95f)); - JGradientButton epicbutton = new JGradientButton(buttonAction(Constants.EPIC_SPINUP, FestcConstants.EPIC_VIEW), - Color.getHSBColor(30f / 360, 0.25f, 0.95f)); - JGradientButton manfileappbutton = new JGradientButton(buttonAction(Constants.MAN_APP, FestcConstants.MAN_FILE_APP_VIEW), - Color.getHSBColor(30f / 360, 0.25f, 0.95f)); - JGradientButton epicappbutton = new JGradientButton(buttonAction(Constants.EPIC_APP, FestcConstants.EPIC4APP_VIEW), - Color.getHSBColor(30f / 360, 0.25f, 0.95f)); - JGradientButton eya2cbutton = new JGradientButton(buttonAction(Constants.EPIC_YEAR, FestcConstants.EPIC_YEARLY_AVERAGE2CMAQ_VIEW), - Color.getHSBColor(230f / 360, 0.40f, 0.95f)); - JGradientButton e2cbutton = new JGradientButton(buttonAction(Constants.EPIC2CMAQ, FestcConstants.EPIC2CMAQ_VIEW), - Color.getHSBColor(230f / 360, 0.40f, 0.95f)); - JGradientButton e2wbutton = new JGradientButton(buttonAction(Constants.EPIC2SWAT, FestcConstants.EPIC2SWAT_VIEW), - Color.getHSBColor(230f / 360, 0.40f, 0.95f)); - JButton visbutton = new JGradientButton(buttonAction(Constants.VISU, FestcConstants.VISUALIZE_VIEW), - Color.getHSBColor(230f / 360, 0.40f, 0.95f)); - - landUsebutton.setPreferredSize(new Dimension(340, 40)); - sitegenbutton.setPreferredSize(new Dimension(340, 40)); - m2pbutton.setPreferredSize(new Dimension(340, 40)); - sitefilebutton.setPreferredSize(new Dimension(340, 40)); - genbutton.setPreferredSize(new Dimension(340, 40)); - manfilespinbutton.setPreferredSize(new Dimension(340, 40)); - modbutton.setPreferredSize(new Dimension(340, 40)); - epicbutton.setPreferredSize(new Dimension(340, 40)); - eya2cbutton.setPreferredSize(new Dimension(340, 40)); - manfileappbutton.setPreferredSize(new Dimension(340, 40)); - epicappbutton.setPreferredSize(new Dimension(340, 40)); - e2cbutton.setPreferredSize(new Dimension(340, 40)); - e2wbutton.setPreferredSize(new Dimension(340, 40)); - visbutton.setPreferredSize(new Dimension(340, 40)); - - landUsebutton.setFont(new Font("Default", Font.BOLD, 14)); - sitegenbutton.setFont(new Font("Default", Font.BOLD, 14)); - m2pbutton.setFont(new Font("Default", Font.BOLD, 14)); - sitefilebutton.setFont(new Font("Default", Font.BOLD, 14)); - genbutton.setFont(new Font("Default", Font.BOLD, 14)); - manfilespinbutton.setFont(new Font("Default", Font.BOLD, 14)); - modbutton.setFont(new Font("Default", Font.BOLD, 14)); - epicbutton.setFont(new Font("Default", Font.BOLD, 14)); - eya2cbutton.setFont(new Font("Default", Font.BOLD, 14)); - manfileappbutton.setFont(new Font("Default", Font.BOLD, 14)); - epicappbutton.setFont(new Font("Default", Font.BOLD, 14)); - e2cbutton.setFont(new Font("Default", Font.BOLD, 14)); - e2wbutton.setFont(new Font("Default", Font.BOLD, 14)); - visbutton.setFont(new Font("Default", Font.BOLD, 14)); - - layout.addLabelWidgetPair("", landUsebutton, panel); - layout.addLabelWidgetPair("", sitegenbutton, panel); - layout.addLabelWidgetPair("", m2pbutton, panel); - layout.addLabelWidgetPair("", sitefilebutton, panel); - layout.addLabelWidgetPair("", genbutton, panel); - layout.addLabelWidgetPair("", manfilespinbutton, panel); - layout.addLabelWidgetPair("", modbutton, panel); - layout.addLabelWidgetPair("", epicbutton, panel); - layout.addLabelWidgetPair("", manfileappbutton, panel); - layout.addLabelWidgetPair("", epicappbutton, panel); - layout.addLabelWidgetPair("", eya2cbutton, panel); - layout.addLabelWidgetPair("", e2cbutton, panel); - layout.addLabelWidgetPair("", e2wbutton, panel); - layout.addLabelWidgetPair("", visbutton, panel); - - layout.makeCompactGrid(panel, 14, 2, // number of rows and cols - 1, 1, // initial X and Y - 1, 1); // x and y pading - - return panel; - } - - private Action buttonAction(final String name, final String viewId) { - return new AbstractAction(name) { - private static final long serialVersionUID = -957559355824942766L; - - public void actionPerformed(ActionEvent e) { - app.showTab(viewId); - } - }; - } - - private class JGradientButton extends JButton { - private static final long serialVersionUID = -2397650058508947005L; - private Color bckGrndColor; - - private JGradientButton(Action action, Color bckGrndColor){ - super(action); - setContentAreaFilled(false); - setFocusPainted(false); // used for demonstration - this.bckGrndColor = bckGrndColor; - } - - @Override - protected void paintComponent(Graphics g){ - Graphics2D g2 = (Graphics2D)g.create(); - g2.setPaint(new GradientPaint( - new Point(0, getHeight() / 3), - Color.WHITE, - new Point(0, 0), - bckGrndColor, true)); - g2.fillRect(0, 0, getWidth(), (getHeight() * 2) / 3); - g2.setPaint(bckGrndColor); - g2.fillRect(0, (getHeight() * 2) / 3, getWidth(), getHeight()); - g2.dispose(); - - super.paintComponent(g); - } - } - -} +package gov.epa.festc.gui; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.core.FestcConstants; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.SpringLayoutGenerator; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SpringLayout; +import javax.swing.SwingConstants; +import javax.swing.UIManager; + +public class ToolsPanel extends JPanel { + private static final long serialVersionUID = 8082261605112772487L; + private FestcApplication app; + + public ToolsPanel(FestcApplication festcApp) { + app = festcApp; + add(createPanel()); + super.requestFocusInWindow(); + } + + private JPanel createPanel() { + JPanel main = new JPanel(new BorderLayout()); + main.add(getNorthPanel(), BorderLayout.NORTH); + main.add(getCenterPanel(), BorderLayout.CENTER); + Dimension d = main.getMinimumSize(); + d.width = 120; + main.setMinimumSize(d); + d = main.getMaximumSize(); + d.width = 120; + main.setMaximumSize(d); + return main; + } + + private JPanel getNorthPanel() { + JPanel panel = new JPanel(); + JLabel title = new JLabel( + "FEST-C Tools", //"Fertilizer Emission Scenario Tool for CMAQ (FEST-C)", // Tools", + SwingConstants.CENTER); + title.setFont(new Font("Default", Font.BOLD, 20)); + + panel.add(title); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); + + return panel; + } + + private JPanel getCenterPanel() { + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + //hsb = Color.RGBtoHSB(r,g,b,hsb); + + JGradientButton landUsebutton = new JGradientButton(buttonAction(Constants.BELD4_GEN, FestcConstants.BELD4_VIEW), + Color.getHSBColor(210f / 360, 0.25f, 0.95f)); + JGradientButton sitegenbutton = new JGradientButton(buttonAction(Constants.SITE_INFO, FestcConstants.SITE_INFO_VIEW), + Color.getHSBColor(210f / 360, 0.25f, 0.95f)); + JGradientButton m2pbutton = new JGradientButton(buttonAction(Constants.MC2EPIC, FestcConstants.MCIP2EPIC_VIEW), + Color.getHSBColor(210f / 360, 0.25f, 0.95f)); + JGradientButton sitefilebutton = new JGradientButton(buttonAction(Constants.EPIC_SITE, FestcConstants.SITE_FILE_VIEW), + Color.getHSBColor(120f / 360, 0.25f, 0.95f)); + JGradientButton genbutton = new JGradientButton(buttonAction(Constants.SOIL_MATCH, FestcConstants.GEN_SOIL_MAN_FILES_VIEW), + Color.getHSBColor(120f / 360, 0.25f, 0.95f)); + JGradientButton manfilespinbutton = new JGradientButton(buttonAction(Constants.MAN_SPINUP, FestcConstants.MAN_FILE_SPINUP_VIEW), + Color.getHSBColor(120f / 360, 0.25f, 0.95f)); + JGradientButton modbutton = new JGradientButton(buttonAction(Constants.EDIT_INFILES, FestcConstants.MANAGE_VIEW), + Color.getHSBColor(50f / 360, 0.25f, 0.95f)); + JGradientButton epicbutton = new JGradientButton(buttonAction(Constants.EPIC_SPINUP, FestcConstants.EPIC_VIEW), + Color.getHSBColor(30f / 360, 0.25f, 0.95f)); + JGradientButton manfileappbutton = new JGradientButton(buttonAction(Constants.MAN_APP, FestcConstants.MAN_FILE_APP_VIEW), + Color.getHSBColor(30f / 360, 0.25f, 0.95f)); + JGradientButton epicappbutton = new JGradientButton(buttonAction(Constants.EPIC_APP, FestcConstants.EPIC4APP_VIEW), + Color.getHSBColor(30f / 360, 0.25f, 0.95f)); + JGradientButton eya2cbutton = new JGradientButton(buttonAction(Constants.EPIC_YEAR, FestcConstants.EPIC_YEARLY_AVERAGE2CMAQ_VIEW), + Color.getHSBColor(230f / 360, 0.40f, 0.95f)); + JGradientButton e2cbutton = new JGradientButton(buttonAction(Constants.EPIC2CMAQ, FestcConstants.EPIC2CMAQ_VIEW), + Color.getHSBColor(230f / 360, 0.40f, 0.95f)); + JGradientButton e2wbutton = new JGradientButton(buttonAction(Constants.EPIC2SWAT, FestcConstants.EPIC2SWAT_VIEW), + Color.getHSBColor(230f / 360, 0.40f, 0.95f)); + JButton visbutton = new JGradientButton(buttonAction(Constants.VISU, FestcConstants.VISUALIZE_VIEW), + Color.getHSBColor(230f / 360, 0.40f, 0.95f)); + + landUsebutton.setPreferredSize(new Dimension(340, 40)); + sitegenbutton.setPreferredSize(new Dimension(340, 40)); + m2pbutton.setPreferredSize(new Dimension(340, 40)); + sitefilebutton.setPreferredSize(new Dimension(340, 40)); + genbutton.setPreferredSize(new Dimension(340, 40)); + manfilespinbutton.setPreferredSize(new Dimension(340, 40)); + modbutton.setPreferredSize(new Dimension(340, 40)); + epicbutton.setPreferredSize(new Dimension(340, 40)); + eya2cbutton.setPreferredSize(new Dimension(340, 40)); + manfileappbutton.setPreferredSize(new Dimension(340, 40)); + epicappbutton.setPreferredSize(new Dimension(340, 40)); + e2cbutton.setPreferredSize(new Dimension(340, 40)); + e2wbutton.setPreferredSize(new Dimension(340, 40)); + visbutton.setPreferredSize(new Dimension(340, 40)); + + landUsebutton.setFont(new Font("Default", Font.BOLD, 14)); + sitegenbutton.setFont(new Font("Default", Font.BOLD, 14)); + m2pbutton.setFont(new Font("Default", Font.BOLD, 14)); + sitefilebutton.setFont(new Font("Default", Font.BOLD, 14)); + genbutton.setFont(new Font("Default", Font.BOLD, 14)); + manfilespinbutton.setFont(new Font("Default", Font.BOLD, 14)); + modbutton.setFont(new Font("Default", Font.BOLD, 14)); + epicbutton.setFont(new Font("Default", Font.BOLD, 14)); + eya2cbutton.setFont(new Font("Default", Font.BOLD, 14)); + manfileappbutton.setFont(new Font("Default", Font.BOLD, 14)); + epicappbutton.setFont(new Font("Default", Font.BOLD, 14)); + e2cbutton.setFont(new Font("Default", Font.BOLD, 14)); + e2wbutton.setFont(new Font("Default", Font.BOLD, 14)); + visbutton.setFont(new Font("Default", Font.BOLD, 14)); + + layout.addLabelWidgetPair("", landUsebutton, panel); + layout.addLabelWidgetPair("", sitegenbutton, panel); + layout.addLabelWidgetPair("", m2pbutton, panel); + layout.addLabelWidgetPair("", sitefilebutton, panel); + layout.addLabelWidgetPair("", genbutton, panel); + layout.addLabelWidgetPair("", manfilespinbutton, panel); + layout.addLabelWidgetPair("", modbutton, panel); + layout.addLabelWidgetPair("", epicbutton, panel); + layout.addLabelWidgetPair("", manfileappbutton, panel); + layout.addLabelWidgetPair("", epicappbutton, panel); + layout.addLabelWidgetPair("", eya2cbutton, panel); + layout.addLabelWidgetPair("", e2cbutton, panel); + layout.addLabelWidgetPair("", e2wbutton, panel); + layout.addLabelWidgetPair("", visbutton, panel); + + layout.makeCompactGrid(panel, 14, 2, // number of rows and cols + 1, 1, // initial X and Y + 1, 1); // x and y pading + + return panel; + } + + private Action buttonAction(final String name, final String viewId) { + return new AbstractAction(name) { + private static final long serialVersionUID = -957559355824942766L; + + public void actionPerformed(ActionEvent e) { + app.showTab(viewId); + } + }; + } + + private class JGradientButton extends JButton { + private static final long serialVersionUID = -2397650058508947005L; + private Color bckGrndColor; + + private JGradientButton(Action action, Color bckGrndColor){ + super(action); + setContentAreaFilled(false); + setFocusPainted(false); // used for demonstration + this.bckGrndColor = bckGrndColor; + } + + @Override + protected void paintComponent(Graphics g){ + Graphics2D g2 = (Graphics2D)g.create(); + g2.setPaint(new GradientPaint( + new Point(0, getHeight() / 3), + Color.WHITE, + new Point(0, 0), + bckGrndColor, true)); + g2.fillRect(0, 0, getWidth(), (getHeight() * 2) / 3); + g2.setPaint(bckGrndColor); + g2.fillRect(0, (getHeight() * 2) / 3, getWidth(), getHeight()); + g2.dispose(); + + super.paintComponent(g); + } + } + +} diff --git a/festc_core/src/gov/epa/festc/gui/UtilGenerateSiteFilesPanel.java b/festc_core/src/gov/epa/festc/gui/UtilGenerateSiteFilesPanel.java index 6caf274..7dde825 100644 --- a/festc_core/src/gov/epa/festc/gui/UtilGenerateSiteFilesPanel.java +++ b/festc_core/src/gov/epa/festc/gui/UtilGenerateSiteFilesPanel.java @@ -1,341 +1,441 @@ -package gov.epa.festc.gui; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.core.proj.DomainFields; -import gov.epa.festc.core.proj.SiteFilesFields; -import gov.epa.festc.util.Constants; -import gov.epa.festc.util.FileRunner; -import gov.epa.festc.util.SpringLayoutGenerator; - -import java.awt.event.ActionEvent; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SpringLayout; - -import simphony.util.messages.MessageCenter; - -public class UtilGenerateSiteFilesPanel extends UtilFieldsPanel implements PlotEventListener{ - private static final long serialVersionUID = 1326060715078017117L; - - private FestcApplication app; - private MessageCenter msg; - private SiteFilesFields fields; - - private JTextField minAcreas; - - public UtilGenerateSiteFilesPanel(FestcApplication application, MessageCenter msg) { - app = application; - init(); - fields = new SiteFilesFields(); - app.getProject().addPage(fields); - app.addPlotListener(this); - this.msg = msg; - add(createPanel()); - } - - private JPanel createPanel() { - JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - - JPanel panel = new JPanel(new SpringLayout()); - SpringLayoutGenerator layout = new SpringLayoutGenerator(); - - //this.scenarioDir = new JTextField(40); - JPanel minAcrePanel = new JPanel(); - minAcreas = new JTextField(20); - minAcreas.setToolTipText("Default value is 40.0"); - minAcrePanel.add(minAcreas); - - JPanel buttonPanel = new JPanel(); - JButton btn = new JButton(generateSiteFilesAction()); - buttonPanel.add(btn); - buttonPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 0)); - - layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); - layout.addLabelWidgetPair("Minimum Crop Acres: ", minAcrePanel, panel); - - layout.makeCompactGrid(panel, 2, 2, // number of rows and cols - 10, 10, // initial X and Y - 5, 5); // x and y pading - - mainPanel.add(panel); - mainPanel.add(buttonPanel); - mainPanel.add(messageBox()); - return mainPanel; - } - - private Action generateSiteFilesAction() { - return new AbstractAction("Generate Site Files") { - private static final long serialVersionUID = 5558465823154735475L; - - public void actionPerformed(ActionEvent e) { - try { - - generateRunScript(); - - } catch (Exception exc) { - //msg.error("ERROR", exc); - app.showMessage("Run script", exc.getMessage()); - } - } - }; - } - - private void generateRunScript() throws Exception { - String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - if (baseDir == null || baseDir.isEmpty()) - throw new Exception("Base dir is empty, please specify in the configuration file!"); - - String scenarioDir = this.scenarioDir.getText(); - validateScen(scenarioDir); - - String minAcres = minAcreas.getText(); - if (minAcres == null || minAcres.isEmpty()) - throw new Exception("Minimum Crop Acres is not specified!"); - - String sMAcres = domain.getCMinAcres(); - if (sMAcres == null || sMAcres.trim().isEmpty()) { - domain.setCMinAcres(minAcres); - sMAcres = minAcres; - } - else if (sMAcres != null && !sMAcres.trim().isEmpty() - && (Float.parseFloat(sMAcres))!=(Float.parseFloat(minAcres)) && app.allowDiffCheck()) - throw new Exception("Current minimum acre "+minAcres+ " is inconsistent with previous one (" + sMAcres + ")"); - - - try { - Float.parseFloat(minAcres); - }catch(NumberFormatException e) { - throw new Exception("Minimum Crop Acres is not a number!"); - } - - outMessages += "Epic base: " + baseDir + ls; - outMessages += "Scen directory: " + scenarioDir + ls; - - final String file = writeRunScriptScript(baseDir, scenarioDir); - - Thread populateThread = new Thread(new Runnable() { - public void run() { - runScript(file); - } - }); - populateThread.start(); - } - - private void runScript(final String file) { - String log = file + ".log"; - - outMessages += "Script file: " + file + ls; - outMessages += "Log file: " + log + ls; - runMessages.setText(outMessages); - runMessages.validate(); - FileRunner.runScript(file, log, msg); - } - - private String writeRunScriptScript( - String baseDir, - String scenarioDir ) throws Exception { - - Date now = new Date(); // java.util.Date, NOT java.sql.Date or java.sql.Timestamp! - String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - - String file = scenarioDir.trim() + "/scripts"; - if ( !file.endsWith(System.getProperty("file.separator"))) - file += System.getProperty("file.separator"); - file += "generateEpicSiteFile_" + timeStamp + ".csh"; - - StringBuilder sb = new StringBuilder(); - sb.append(getScirptHeader()); - sb.append(getEnvironmentDef(baseDir, scenarioDir)); - sb.append(getSiteGrid()); - sb.append(getBeld4HUC8()); - - String mesg = ""; - - try { - File script = new File(file); - - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - - mesg += "Script file: " + file + ls; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - - } catch (IOException e) { - //e.printStackTrace(); - //msg.error("Error generating EPIC script file", e); - throw new Exception(e.getMessage()); - } - app.showMessage("Write script", mesg); - - return file; - } - - private String getScirptHeader() { - StringBuilder sb = new StringBuilder(); - sb.append("#!/bin/csh -f" + ls); - sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to run Site Creation and HUC8 Utilities" + ls); - sb.append("#" + ls); - sb.append("# Written by: Fortran by Benson, Script by IE. 2010" + ls); - sb.append("# Modified by:" + ls); - sb.append("#" + ls); - sb.append("# Program: SITE_FILE_CREATOR.exe and SITEBELD4HUC8.exe" + ls); - sb.append("# " + ls); - sb.append("#***************************************************************************************" + ls + ls); - - - return sb.toString(); - } - - private String getEnvironmentDef(String baseDir, String scenarioDir) { - StringBuilder sb = new StringBuilder(); - - sb.append(ls + "#" + ls); - sb.append("# Define environment variables" + ls); - sb.append("#" + ls + ls); - - sb.append("setenv EPIC_DIR " + baseDir + ls); - sb.append("setenv SCEN_DIR " + scenarioDir + ls); - sb.append("setenv WORK_DIR " + scenarioDir + "/work_dir" +ls); - sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls); - sb.append("setenv SIT_DIR " + "$SHARE_DIR/SIT" + ls); - - return sb.toString(); - } - - private String getSiteGrid() { - StringBuilder sb = new StringBuilder(); - - sb.append(ls + "#" + ls); - sb.append("# set input variables" + ls); - sb.append("#" + ls); - - sb.append("setenv INFILE1 \"EPICSites_Info.csv\"" + ls); - sb.append(ls); - - sb.append(ls + "#" + ls); - sb.append("# Set output variable" + ls); - sb.append("#" + ls + ls); - sb.append("if ( ! -e $SHARE_DIR/SITELIST.DAT ) rm -f $SHARE_DIR/SITELIST.DAT" + ls); - sb.append("if ( ! -e $SIT_DIR ) mkdir -p $SIT_DIR" + ls); - sb.append("if ( ! -e $WORK_DIR ) mkdir -p $WORK_DIR" + ls); - - sb.append(ls); - - String exe; - exe = "$EPIC_DIR//util/siteCreate/SITE_FILE_CREATOR.exe"; - - sb.append(ls + "#" + ls); - sb.append("# Generate site files " + ls); - sb.append("#" + ls ); - sb.append("time " + exe + ls ); - sb.append("if ( $status == 0 ) then " + ls); - sb.append(" echo ==== Finished site creation step1. " + ls); - sb.append("else " + ls); - sb.append(" echo ==== Error site creation step1." + ls ); - sb.append(" exit 1 " + ls ); - sb.append("endif " + ls); - sb.append(ls); - - outMessages += "Exectable1: $EPIC_DIR//util/siteCreate/SITE_FILE_CREATOR.exe" +ls; - outMessages += "Outputs: 1. SITELIST.DAT ($SCEN_DIR/share_data)" +ls; - outMessages += "Outputs: 2. All sitefiles ($SCEN_DIR//share_data/SIT)" +ls; - - return sb.toString(); - } - - private String getBeld4HUC8() { - StringBuilder sb = new StringBuilder(); - - sb.append("# Delineation Soil, Site and Crop fractions" + ls); - sb.append("#" + ls); - sb.append("# set input variables" + ls); - sb.append("#" + ls); - - sb.append("setenv INFILE2 \"EPICSites_Crop.csv\"" + ls +ls); - - sb.append("# Set minimum crop acres for site selection " + ls ); - sb.append("setenv MINIMUM_CROP_ACRES " + minAcreas.getText() +ls +ls ); - - sb.append("# Create directories for crops " + ls); - sb.append("foreach crop ( HAY ALFALFA OTHGRASS BARLEY EBEANS CORNG CORNS " + - " COTTON OATS PEANUTS POTATOES RICE RYE SORGHUMG SORGHUMS SOYBEANS " + - " SWHEAT WWHEAT OTHER CANOLA BEANS )" +ls ); - sb.append(" if ( ! -e $SCEN_DIR/$crop ) mkdir -p $SCEN_DIR/$crop " + ls); - sb.append("end" +ls ); - - String exe; - exe = "$EPIC_DIR/util/siteCreate/SITEBELD4HUC8.exe"; - sb.append("time " + exe + ls ); - sb.append("if ( $status == 0 ) then " + ls); - sb.append(" echo ==== Finished site creation step2. " + ls); - sb.append("else " + ls); - sb.append(" echo ==== Error in site creation step2." + ls ); - sb.append("endif " + ls); - sb.append("#" + ls + ls); - - outMessages += "Exectable2: $EPIC_DIR/util/siteCreate/SITEBELD4HUC8.exe"+ls; - //outMessages += "Input: SITELIST.DAT "+ls; - outMessages += "Outputs: crop list files, $SCEN_DIR/$CROP ${CROP}-LIST.DAT...."+ls+ls; - - return sb.toString(); - } - - @Override - public void projectLoaded() { - fields = (SiteFilesFields) app.getProject().getPage(fields.getName()); - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - if ( fields != null ){ - String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length()>0 ) - this.scenarioDir.setText(scenloc); - else - this.scenarioDir.setText(fields.getScenarioDir()); - runMessages.setText(fields.getMessage()); - minAcreas.setText(fields.getMinAcres()==null? "40.0":fields.getMinAcres()); - } else{ - newProjectCreated(); - } - domain.setCMinAcres(null); - } - - @Override - public void saveProjectRequested() { - if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); - if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); - if ( runMessages != null ) fields.setMessage(runMessages.getText()); - if ( minAcreas != null) fields.setMinAcres(minAcreas.getText()); - if ( runMessages != null ) fields.setMessage(runMessages.getText()); - domain.setCMinAcres(null); - } - - @Override - public void newProjectCreated() { - domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - scenarioDir.setText(domain.getScenarioDir()); - runMessages.setText(""); - minAcreas.setText("40.0"); - - if ( fields == null ) { - fields = new SiteFilesFields(); - app.getProject().addPage(fields); - } - } - -} +package gov.epa.festc.gui; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.core.proj.DomainFields; +import gov.epa.festc.core.proj.SiteFilesFields; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.FileRunner; +import gov.epa.festc.util.SpringLayoutGenerator; + +import java.awt.event.ActionEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SpringLayout; + +import simphony.util.messages.MessageCenter; + +public class UtilGenerateSiteFilesPanel extends UtilFieldsPanel implements PlotEventListener{ + private static final long serialVersionUID = 1326060715078017117L; + + private FestcApplication app; + private MessageCenter msg; + private SiteFilesFields fields; + + private JTextField minAcreas; + + public UtilGenerateSiteFilesPanel(FestcApplication application, MessageCenter msg) { + app = application; + init(); + fields = new SiteFilesFields(); + app.getProject().addPage(fields); + app.addPlotListener(this); + this.msg = msg; + add(createPanel()); + } + + private JPanel createPanel() { + JPanel mainPanel = new JPanel(); + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + + //this.scenarioDir = new JTextField(40); + JPanel minAcrePanel = new JPanel(); + minAcreas = new JTextField(20); + minAcreas.setToolTipText("Default value is 0.0"); + minAcrePanel.add(minAcreas); + + JPanel buttonPanel = new JPanel(); + JButton btn = new JButton(generateSiteFilesAction()); + buttonPanel.add(btn); + buttonPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 0)); + + layout.addLabelWidgetPair(Constants.LABEL_EPIC_SCENARIO, scenarioDirP, panel); + layout.addLabelWidgetPair("Minimum Crop Acres: ", minAcrePanel, panel); + + layout.makeCompactGrid(panel, 2, 2, // number of rows and cols + 10, 10, // initial X and Y + 5, 5); // x and y pading + + mainPanel.add(panel); + mainPanel.add(buttonPanel); + mainPanel.add(messageBox()); + return mainPanel; + } + + private Action generateSiteFilesAction() { + return new AbstractAction("Generate Site Files") { + private static final long serialVersionUID = 5558465823154735475L; + + public void actionPerformed(ActionEvent e) { + try { + + generateRunScript(); + + } catch (Exception exc) { + //msg.error("ERROR", exc); + app.showMessage("Run script", exc.getMessage()); + } + } + }; + } + + private void generateRunScript() throws Exception { + String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); + if (baseDir == null || baseDir.isEmpty()) + throw new Exception("Base dir is empty, please specify in the configuration file!"); + + String scenarioDir = this.scenarioDir.getText(); + validateScen(scenarioDir); + + String minAcres = minAcreas.getText(); + if (minAcres == null || minAcres.isEmpty()) + throw new Exception("Minimum Crop Acres is not specified!"); + + String sMAcres = domain.getCMinAcres(); + if (sMAcres == null || sMAcres.trim().isEmpty()) { + domain.setCMinAcres(minAcres); + sMAcres = minAcres; + } + else if (sMAcres != null && !sMAcres.trim().isEmpty() + && (Float.parseFloat(sMAcres))!=(Float.parseFloat(minAcres)) && app.allowDiffCheck()) + throw new Exception("Current minimum acre "+minAcres+ " is inconsistent with previous one (" + sMAcres + ")"); + + + try { + Float.parseFloat(minAcres); + }catch(NumberFormatException e) { + throw new Exception("Minimum Crop Acres is not a number!"); + } + + outMessages += "Epic base: " + baseDir + ls; + outMessages += "Scen directory: " + scenarioDir + ls; + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + + final String jobFile = writeRunScriptScript(baseDir, scenarioDir); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir); + } else { + batchFile = null; + } + Thread populateThread = new Thread(new Runnable() { + public void run() { + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + // final String batchFile = writeBatchFile(jobFile, + // scenarioDir); + runBatchScript(batchFile, jobFile); + } + + } + }); + populateThread.start(); + } + + // This is legacy code that has been moved to it's own method + protected void writeScriptFile(String file, String content) { + + String mesg = ""; + + try { + File script = new File(file); + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(content); + out.close(); + + mesg += "Script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + + } catch (IOException e) { + // printStackTrace(); + // g.error("Error generating EPIC script file", e); + app.showMessage("Write script", e.getMessage()); + } + + app.showMessage("Write script", mesg); + } + + private void runScript(final String file) { + String log = file + ".log"; + + outMessages += "Script file: " + file + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + FileRunner.runScript(file, log, msg); + } + + private void runBatchScript(final String batchFile, final String jobFile) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qEpicSite = Constants.getProperty(Constants.QUEUE_EPIC_SITE, msg); + + File script = new File(batchFile.replaceAll("\\\\", "\\\\\\\\")); + + sb.append(qcmd + " " + qEpicSite + " -o " + log + " " + script.getAbsolutePath()); + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } + + protected String writeBatchFile(String jobFile, String scenarioDir) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String batchFile = scenarioDir.trim() + "/scripts"; + if (!batchFile.endsWith(System.getProperty("file.separator"))) + batchFile += System.getProperty("file.separator"); + batchFile += "submitEpicSiteFile_" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh" + ls + ls); + + // TODO - add #SBATCH options here + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage == null || qSingModule.trim().isEmpty()) { + throw new Exception("Singularity image path must be specified"); + } + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + jobFile); + } else { + sb.append(jobFile); + } + + writeScriptFile(batchFile, sb.toString()); + + return batchFile; + } + + + private String writeRunScriptScript( + String baseDir, + String scenarioDir ) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + + String file = scenarioDir.trim() + "/scripts"; + if ( !file.endsWith(System.getProperty("file.separator"))) + file += System.getProperty("file.separator"); + file += "generateEpicSiteFile_" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + sb.append(getScirptHeader()); + sb.append(getEnvironmentDef(baseDir, scenarioDir)); + sb.append(getSiteGrid()); + sb.append(getBeld4HUC8()); + + String mesg = ""; + + try { + File script = new File(file); + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(sb.toString()); + out.close(); + + mesg += "Script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + + } catch (IOException e) { + //e.printStackTrace(); + //msg.error("Error generating EPIC script file", e); + throw new Exception(e.getMessage()); + } + app.showMessage("Write script", mesg); + + return file; + } + + private String getScirptHeader() { + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh -f" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: to run Site Creation and HUC8 Utilities" + ls); + sb.append("#" + ls); + sb.append("# Written by: Fortran by Benson, Script by IE. 2010" + ls); + sb.append("# Modified by:" + ls); + sb.append("#" + ls); + sb.append("# Program: SITE_FILE_CREATOR.exe and SITEBELD4HUC8.exe" + ls); + sb.append("# " + ls); + sb.append("#***************************************************************************************" + ls + ls); + + + return sb.toString(); + } + + private String getEnvironmentDef(String baseDir, String scenarioDir) { + StringBuilder sb = new StringBuilder(); + + sb.append(ls + "#" + ls); + sb.append("# Define environment variables" + ls); + sb.append("#" + ls + ls); + + sb.append("setenv EPIC_DIR " + baseDir + ls); + sb.append("setenv SCEN_DIR " + scenarioDir + ls); + sb.append("setenv WORK_DIR " + scenarioDir + "/work_dir" +ls); + sb.append("setenv SHARE_DIR " + scenarioDir + "/share_data" + ls); + sb.append("setenv SIT_DIR " + "$SHARE_DIR/SIT" + ls); + + return sb.toString(); + } + + private String getSiteGrid() { + StringBuilder sb = new StringBuilder(); + + sb.append(ls + "#" + ls); + sb.append("# set input variables" + ls); + sb.append("#" + ls); + + sb.append("setenv INFILE1 \"EPICSites_Info.csv\"" + ls); + sb.append(ls); + + sb.append(ls + "#" + ls); + sb.append("# Set output variable" + ls); + sb.append("#" + ls + ls); + sb.append("if ( ! -e $SHARE_DIR/SITELIST.DAT ) rm -f $SHARE_DIR/SITELIST.DAT" + ls); + sb.append("if ( ! -e $SIT_DIR ) mkdir -p $SIT_DIR" + ls); + sb.append("if ( ! -e $WORK_DIR ) mkdir -p $WORK_DIR" + ls); + + sb.append(ls); + + String exe; + exe = "$EPIC_DIR//util/siteCreate/SITE_FILE_CREATOR.exe"; + + sb.append(ls + "#" + ls); + sb.append("# Generate site files " + ls); + sb.append("#" + ls ); + sb.append("time " + exe + ls ); + sb.append("if ( $status == 0 ) then " + ls); + sb.append(" echo ==== Finished site creation step1. " + ls); + sb.append("else " + ls); + sb.append(" echo ==== Error site creation step1." + ls ); + sb.append(" exit 1 " + ls ); + sb.append("endif " + ls); + sb.append(ls); + + outMessages += "Exectable1: $EPIC_DIR//util/siteCreate/SITE_FILE_CREATOR.exe" +ls; + outMessages += "Outputs: 1. SITELIST.DAT ($SCEN_DIR/share_data)" +ls; + outMessages += "Outputs: 2. All sitefiles ($SCEN_DIR//share_data/SIT)" +ls; + + return sb.toString(); + } + + private String getBeld4HUC8() { + StringBuilder sb = new StringBuilder(); + + sb.append("# Delineation Soil, Site and Crop fractions" + ls); + sb.append("#" + ls); + sb.append("# set input variables" + ls); + sb.append("#" + ls); + + sb.append("setenv INFILE2 \"EPICSites_Crop.csv\"" + ls +ls); + + sb.append("# Set minimum crop acres for site selection " + ls ); + sb.append("setenv MINIMUM_CROP_ACRES " + minAcreas.getText() +ls +ls ); + + sb.append("# Create directories for crops " + ls); + sb.append("foreach crop ( HAY ALFALFA OTHGRASS BARLEY EBEANS CORNG CORNS " + + " COTTON OATS PEANUTS POTATOES RICE RYE SORGHUMG SORGHUMS SOYBEANS " + + " SWHEAT WWHEAT OTHER CANOLA BEANS )" +ls ); + sb.append(" if ( ! -e $SCEN_DIR/$crop ) mkdir -p $SCEN_DIR/$crop " + ls); + sb.append("end" +ls ); + + String exe; + exe = "$EPIC_DIR/util/siteCreate/SITEBELD4HUC8.exe"; + sb.append("time " + exe + ls ); + sb.append("if ( $status == 0 ) then " + ls); + sb.append(" echo ==== Finished site creation step2. " + ls); + sb.append("else " + ls); + sb.append(" echo ==== Error in site creation step2." + ls ); + sb.append("endif " + ls); + sb.append("#" + ls + ls); + + outMessages += "Exectable2: $EPIC_DIR/util/siteCreate/SITEBELD4HUC8.exe"+ls; + //outMessages += "Input: SITELIST.DAT "+ls; + outMessages += "Outputs: crop list files, $SCEN_DIR/$CROP ${CROP}-LIST.DAT...."+ls+ls; + + return sb.toString(); + } + + @Override + public void projectLoaded() { + fields = (SiteFilesFields) app.getProject().getPage(fields.getName()); + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + if ( fields != null ){ + String scenloc = domain.getScenarioDir(); + if (scenloc != null && scenloc.trim().length()>0 ) + this.scenarioDir.setText(scenloc); + else + this.scenarioDir.setText(fields.getScenarioDir()); + runMessages.setText(fields.getMessage()); + minAcreas.setText(fields.getMinAcres()==null? "0.0":fields.getMinAcres()); + } else{ + newProjectCreated(); + } + domain.setCMinAcres(null); + } + + @Override + public void saveProjectRequested() { + if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); + if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); + if ( runMessages != null ) fields.setMessage(runMessages.getText()); + if ( minAcreas != null) fields.setMinAcres(minAcreas.getText()); + if ( runMessages != null ) fields.setMessage(runMessages.getText()); + domain.setCMinAcres(null); + } + + @Override + public void newProjectCreated() { + domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); + scenarioDir.setText(domain.getScenarioDir()); + runMessages.setText(""); + minAcreas.setText("0.0"); + + if ( fields == null ) { + fields = new SiteFilesFields(); + app.getProject().addPage(fields); + } + } + +} diff --git a/festc_core/src/gov/epa/festc/gui/UtilGenerateSoilMatchPanel.java b/festc_core/src/gov/epa/festc/gui/UtilGenerateSoilMatchPanel.java index 6370122..ef10f4f 100644 --- a/festc_core/src/gov/epa/festc/gui/UtilGenerateSoilMatchPanel.java +++ b/festc_core/src/gov/epa/festc/gui/UtilGenerateSoilMatchPanel.java @@ -33,13 +33,13 @@ import simphony.util.messages.MessageCenter; public class UtilGenerateSoilMatchPanel extends UtilFieldsPanel implements PlotEventListener { - + private FestcApplication app; private MessageCenter msg; private SoilFilesFields fields; - private CropSelectionPanel cropSelectionPanel; - + private CropSelectionPanel cropSelectionPanel; + public UtilGenerateSoilMatchPanel(FestcApplication application, MessageCenter msg) { app = application; fields = new SoilFilesFields(); @@ -48,31 +48,31 @@ public UtilGenerateSoilMatchPanel(FestcApplication application, MessageCenter ms this.msg = msg; add(createPanel()); } - + private JPanel createPanel() { - JPanel mainPanel = new JPanel(); + JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - + mainPanel.add(scenPanel()); mainPanel.add(cropsPanel()); mainPanel.add(messageBox()); - return mainPanel; + return mainPanel; } - - private JPanel cropsPanel(){ - + + private JPanel cropsPanel() { + JPanel panel = new JPanel(new SpringLayout()); SpringLayoutGenerator layout = new SpringLayoutGenerator(); JPanel buttonPanel = new JPanel(); JButton btn = new JButton(runAction()); - btn.setPreferredSize(new Dimension(100,50)); + btn.setPreferredSize(new Dimension(100, 50)); buttonPanel.add(btn); buttonPanel.setBorder(BorderFactory.createEmptyBorder(70, 30, 70, 30)); this.cropSelectionPanel = new CropSelectionPanel(app); layout.addWidgetPair(cropSelectionPanel, buttonPanel, panel); layout.makeCompactGrid(panel, 1, 2, // number of rows and cols 10, 10, // initial X and Y - 5, 5); // x and y pading + 5, 5); // x and y pading return panel; } @@ -81,117 +81,359 @@ private Action runAction() { private static final long serialVersionUID = 5558465823154735475L; public void actionPerformed(ActionEvent e) { - try { + try { generateSoilMatchFiles(); } catch (Exception exc) { - //msg.error("ERROR", exc); + // msg.error("ERROR", exc); app.showMessage("Run script", exc.getMessage()); } } }; } - + private void generateSoilMatchFiles() throws Exception { String baseDir = Constants.getProperty(Constants.EPIC_HOME, msg); - if (baseDir == null || baseDir.isEmpty()) + if (baseDir == null || baseDir.isEmpty()) throw new Exception("Base dir is empty, please specify in the configuration file!"); - + String scenarioDir = this.scenarioDir.getText(); - if ( scenarioDir == null || scenarioDir.isEmpty()) + if (scenarioDir == null || scenarioDir.isEmpty()) throw new Exception("Please select scenario dir first!"); - + String seCropsString = cropSelectionPanel.selectedItemTostring(); String[] seCrops = cropSelectionPanel.getSelectedCrops(); - if ( seCrops == null || seCrops.length == 0) - throw new Exception("Please select crop(s) first!"); - + if (seCrops == null || seCrops.length == 0) + throw new Exception("Please select crop(s) first!"); + outMessages += "Epic base: " + baseDir + ls; outMessages += "Scen directory: " + scenarioDir + ls; - - final String file = writeRunScript(baseDir, scenarioDir, seCropsString); - + + final String jobFile = writeRunScript(baseDir, scenarioDir, seCropsString); + String cropNums = getChosenCropNums(); + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + final String batchFile; + if (qcmd != null && !qcmd.trim().isEmpty()) { + batchFile = writeBatchFile(jobFile, scenarioDir); + } else { + batchFile = null; + } + Thread populateThread = new Thread(new Runnable() { public void run() { - runScript(file); + if (qcmd == null || qcmd.trim().isEmpty()) { + runScript(jobFile); + } else { + runBatchScript(batchFile, jobFile, cropNums); + } } }); populateThread.start(); } - + private void runScript(final String file) { String log = file + ".log"; - + outMessages += "Script file: " + file + ls; outMessages += "Log file: " + log + ls; runMessages.setText(outMessages); runMessages.validate(); FileRunner.runScript(file, log, msg); } - - protected String writeRunScript( - String baseDir, - String scenarioDir, - String cropNames ) throws Exception { - - Date now = new Date(); // java.util.Date, NOT java.sql.Date or java.sql.Timestamp! + + private void runBatchScript(final String batchFile, final String jobFile, final String chosenCrops) { + String log = jobFile + ".log"; + + outMessages += "Batch Script file: " + batchFile + ls; + outMessages += "Job Script file: " + jobFile + ls; + outMessages += "Log file: " + log + ls; + runMessages.setText(outMessages); + runMessages.validate(); + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + StringBuilder sb = new StringBuilder(); + String qEpicSoilMatch = Constants.getProperty(Constants.QUEUE_SOIL_MATCH, msg); + if (qcmd.contains("sbatch")) { + // SLURM + sb.append("sbatch --job-name=EPICSoilMatchArrayJob --output=runEpicSoilMatch_JobArray_%A_%a.out --array=" + + chosenCrops + " " + qEpicSoilMatch + " " + batchFile + ls); + } else if (qcmd.contains("qsub")) { + // PBS + sb.append("qsub -N EPICSoilMatchArrayJob -t " + chosenCrops + " " + qEpicSoilMatch + " " + batchFile + ls); + } else if (qcmd.contains("bsub")) { + // LSF + sb.append("bsub -J EPICSoilMatchArrayJob[" + chosenCrops + "] " + qEpicSoilMatch + " " + batchFile + ls); + } + + FileRunner.runScriptwCmd(batchFile, log, msg, sb.toString()); + } + + protected String writeRunScript(String baseDir, String scenarioDir, String cropNames) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); - + String file = scenarioDir.trim() + "/scripts"; - if ( !file.endsWith(System.getProperty("file.separator"))) - file += System.getProperty("file.separator"); + if (!file.endsWith(System.getProperty("file.separator"))) + file += System.getProperty("file.separator"); file += "runEpicSoilMatch_" + timeStamp + ".csh"; - + + StringBuilder sb = new StringBuilder(); + String scriptContent = null; + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); + if (qcmd == null || qcmd.trim().isEmpty()) { + // no batch system + sb.append(getScirptHeader()); + sb.append(getEnvironmentDef(baseDir, scenarioDir)); + sb.append(getRunDef(cropNames)); + scriptContent = sb.toString(); + } else { + // assume batch system that supports job arrays (SLURM, LSF, etc) + + // create job array script + // String taskScriptContent = createArrayTaskScript(baseDir, + // scenarioDir); + // String taskFile = scenarioDir.trim() + "/scripts"; + // if (!taskFile.endsWith(System.getProperty("file.separator"))) + // taskFile += System.getProperty("file.separator"); + // taskFile += "runEpicSoilMatchCrop_" + timeStamp + ".csh"; + // writeScriptFile(taskFile, taskScriptContent); + // + // scriptContent = createArraySubmitScript(taskFile, scenarioDir); + + scriptContent = createArrayTaskScript(baseDir, scenarioDir); + + } + + // create submit script + writeScriptFile(file, scriptContent); + + return file; + } + + // private String createArraySubmitScript(String taskScript, String + // scenarioDir) throws Exception{ + // + // StringBuilder sb = new StringBuilder(); + // sb.append("#!/bin/csh -f" + ls); + // sb.append("#**************************************************************************************" + // + ls); + // sb.append("# Purpose: to submit batch job for job arrays" + ls); + // sb.append("# #" + ls); + // sb.append("# #" + ls); + // sb.append("# + // #***************************************************************************************" + // + ls); + // sb.append("# submit job array tasks"+ls); + // + // sb.append("set CROPSLIST = " + getChosenCropNums() + ls + ls); + // + // String qEpicSoilMatch = Constants.getProperty(Constants.QUEUE_SOIL_MATCH, + // msg); + // sb.append("sbatch --job-name=EPICSoilMatchArrayJob + // --output=submitEPICSoilMatch_JobArray_%A_%a.out --array=$CROPSLIST " + + // qEpicSoilMatch + " " + taskScript +ls); + // + // return sb.toString(); + // } + + private String createArrayTaskScript(String baseDir, String scenarioDir) throws Exception { + + String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg).toLowerCase(); + String arrayIdEnvVar = ""; + + if (qcmd.contains("sbatch")) { + // SLURM + arrayIdEnvVar = "$SLURM_ARRAY_TASK_ID"; + } else if (qcmd.contains("qsub")) { + // PBS + arrayIdEnvVar = "$PBS_ARRAYID"; + } else if (qcmd.contains("bsub")) { + // LSF + arrayIdEnvVar = "$LSB_JOBINDEX"; + } + StringBuilder sb = new StringBuilder(); - sb.append(getScirptHeader()); + + // header + sb.append("#!/bin/csh -f" + ls); + sb.append("#**************************************************************************************" + ls); + sb.append("# Purpose: to run Soil Match Utility" + ls); + sb.append("# SLURM example cmd:" + ls); + sb.append( + "# sbatch --job-name=EPICSoilMatchArrayJob --output=submitEPICSoilMatch_JobArray_%A_%a.out --array=1,31 --time=2:00:00" + + ls); + sb.append("# /PATH_TO_SCRIPT/runEpicSoilMatch_TIMESTAMP.csh" + ls); + sb.append("# where 1,31 are rainfed (odd) crop numbers only" + ls); + sb.append("#" + ls); + sb.append("# Written by: Fortran by Benson, Original Script by IE. 2010" + ls); + sb.append("# Modified by: EMVL " + ls); + sb.append("#" + ls); + sb.append("# Program: SOILMATCH*.exe" + ls); + sb.append("# Needed environment variables included in the script file to run." + ls); + sb.append("# " + ls); + sb.append("#***************************************************************************************" + ls + ls); + + // environmental variables sb.append(getEnvironmentDef(baseDir, scenarioDir)); - sb.append(getRunDef(cropNames)); - + + // + sb.append("set CROPS = (HAY ALFALFA OTHGRASS BARLEY EBEANS CORNG CORNS COTTON OATS PEANUTS POTATOES RICE RYE)" + + ls); + sb.append("set CROPS = ($CROPS SORGHUMG SORGHUMS SOYBEANS SWHEAT WWHEAT OTHER CANOLA BEANS)" + ls); + + sb.append("# Generate soil match files" + ls + ls); + sb.append("# set input variables" + ls + ls); + + // sb.append("@ rem = $SLURM_ARRAY_TASK_ID % 2" + ls); + sb.append("@ rem = " + arrayIdEnvVar + " % 2" + ls); + // sb.append("@ ind = ($SLURM_ARRAY_TASK_ID + $rem) / 2" + ls + ls); + sb.append("@ ind = (" + arrayIdEnvVar + " + $rem) / 2" + ls + ls); + + sb.append("setenv CROP_NAME $CROPS[$ind]" + ls + ls); + + sb.append("rm -rf $SCEN_DIR/$CROP_NAME/NONRISOIL*.DAT > & /dev/null" + ls); + sb.append("rm -rf $SCEN_DIR/$CROP_NAME/SOILSKM*.LOC > & /dev/null" + ls + ls); + + sb.append("echo ==== Begin soil match run for crop $CROP_NAME" + ls); + sb.append("echo ==== Running step 1 ...." + ls); + sb.append("time $EXEC_DIR/SOILMATCH1ST.exe" + ls + ls); + sb.append("echo ==== Running step 2 ...." + ls); + sb.append("time $EXEC_DIR/SOILMATCH2ND.exe" + ls + ls); + sb.append("echo ==== Running step 3 ...." + ls); + sb.append("time $EXEC_DIR/SOILMATCH3RD.exe" + ls + ls); + sb.append("echo ==== Running step 4 ...." + ls); + sb.append("time $EXEC_DIR/SOILMATCH4TH.exe" + ls + ls); + sb.append("echo ==== Running step 5 ...." + ls); + sb.append("time $EXEC_DIR/SOILMATCH5TH.exe" + ls + ls); + sb.append("echo ==== Running step 6 ...." + ls); + sb.append("time $EXEC_DIR/SOILMATCH6TH.exe" + ls + ls); + + sb.append("if ($status == 0 ) then" + ls); + sb.append(" echo ==== Finished soil match for crop $CROP_NAME." + ls); + sb.append("else" + ls); + sb.append(" echo ==status== Error in soil match run for crop $CROP_NAME." + ls); + sb.append(" exit 1" + ls); + sb.append("endif" + ls + ls); + sb.append("echo \" Merging *LOC to SOILLIST.DAT\"" + ls); + sb.append("cat $SCEN_DIR/$CROP_NAME/*LOC > $SCEN_DIR/$CROP_NAME/SOILLIST.DAT" + ls); + + return sb.toString(); + + } + + // This is legacy code that has been moved to it's own method + protected void writeScriptFile(String file, String content) { + String mesg = ""; - + try { File script = new File(file); - - BufferedWriter out = new BufferedWriter(new FileWriter(script)); - out.write(sb.toString()); - out.close(); - - mesg += "Script file: " + file + ls; - boolean ok = script.setExecutable(true, false); - mesg += "Set the script file to be executable: "; - mesg += ok ? "ok." : "failed."; - - } catch (IOException e) { - //e.printStackTrace(); - //msg.error("Error generating EPIC script file", e); - throw new Exception(e.getMessage()); - } - - app.showMessage("Write script", mesg); - - return file; + + BufferedWriter out = new BufferedWriter(new FileWriter(script)); + out.write(content); + out.close(); + + mesg += "Script file: " + file + ls; + boolean ok = script.setExecutable(true, false); + mesg += "Set the script file to be executable: "; + mesg += ok ? "ok." : "failed."; + + } catch (IOException e) { + // printStackTrace(); + // g.error("Error generating EPIC script file", e); + app.showMessage("Write script", e.getMessage()); + } + + app.showMessage("Write script", mesg); } - + + protected String writeBatchFile(String jobFile, String scenarioDir) throws Exception { + + Date now = new Date(); // java.util.Date, NOT java.sql.Date or + // java.sql.Timestamp! + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(now); + String batchFile = scenarioDir.trim() + "/scripts"; + if (!batchFile.endsWith(System.getProperty("file.separator"))) + batchFile += System.getProperty("file.separator"); + batchFile += "submitEpicSoilMatch_" + timeStamp + ".csh"; + + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/csh" + ls + ls); + + // TODO - add #SBATCH options here + + String qSingModule = Constants.getProperty(Constants.QUEUE_SINGULARITY_MODULE, msg); + if (qSingModule != null && !qSingModule.trim().isEmpty()) { + sb.append("module load " + qSingModule + ls); + + String qSingImage = Constants.getProperty(Constants.QUEUE_SINGULARITY_IMAGE, msg); + String qSingBind = Constants.getProperty(Constants.QUEUE_SINGULARITY_BIND, msg); + if (qSingImage == null || qSingModule.trim().isEmpty()) { + throw new Exception("Singularity image path must be specified"); + } + sb.append("set CONTAINER = " + qSingImage + ls); + sb.append("singularity exec"); + if (qSingBind != null && !qSingBind.trim().isEmpty()) { + sb.append(" -B " + qSingBind); + } + sb.append(" $CONTAINER " + jobFile); + } else { + sb.append(jobFile); + } + + writeScriptFile(batchFile, sb.toString()); + + return batchFile; + } + + // returns comma separated list of chosen crop numbers to run + // This only returns one crop id (rainf), not both rainf and irr variations + private String getChosenCropNums() throws Exception { + String[] seCrops = cropSelectionPanel.getSelectedCrops(); + if (seCrops == null || seCrops.length == 0) + throw new Exception("Please select crop(s) first!"); + String crop = null; + String cropIDs = ""; + for (int i = 0; i < seCrops.length; i++) { + crop = seCrops[i]; + Integer cropID = Constants.CROPS.get(crop); + if (cropID == null || cropID <= 0) + throw new Exception("crop id is null for crop " + crop); + Integer cropIrID = cropID + 1; + + if (i != 0) { + cropIDs += "," + cropID; + } else { + cropIDs = "" + cropID; + } + // cropIDs += "," + cropIrID; + } + + return cropIDs; + } + private String getScirptHeader() { StringBuilder sb = new StringBuilder(); - + sb.append("#!/bin/csh -f" + ls); sb.append("#**************************************************************************************" + ls); - sb.append("# Purpose: to run Soil Match Utility" + ls); + sb.append("# Purpose: to run Soil Match Utility" + ls); sb.append("#" + ls); sb.append("# Written by: Fortran by Benson, Script by IE. 2010" + ls); - sb.append("# Modified by:" + ls); + sb.append("# Modified by:" + ls); sb.append("#" + ls); sb.append("# Program: SOILMATCH*.exe" + ls); - sb.append("# Needed environment variables included in the script file to run." + ls); + sb.append("# Needed environment variables included in the script file to run." + ls); sb.append("# " + ls); sb.append("#***************************************************************************************" + ls + ls); - + return sb.toString(); } - + private String getEnvironmentDef(String baseDir, String scenarioDir) { StringBuilder sb = new StringBuilder(); - + sb.append(ls + "#" + ls); sb.append("# Define environment variables" + ls); sb.append("#" + ls + ls); @@ -203,69 +445,69 @@ private String getEnvironmentDef(String baseDir, String scenarioDir) { sb.append("" + ls); sb.append("set EXEC_DIR = " + baseDir + "/util/soilMatch" + ls); sb.append("" + ls); - + return sb.toString(); } - + private String getRunDef(String cropNames) { StringBuilder sb = new StringBuilder(); - + sb.append(ls + "#" + ls); sb.append("# Generate soil match files " + ls); - sb.append("#" + ls ); + sb.append("#" + ls); sb.append("# set input variables" + ls); sb.append("set CROPS = " + cropNames + ls); sb.append("foreach crop ($CROPS) " + ls); sb.append(" setenv CROP_NAME $crop " + ls); - sb.append(" rm -rf $SCEN_DIR/$CROP_NAME/NONRISOIL*.DAT " + ls ); - sb.append(" rm -rf $SCEN_DIR/$CROP_NAME/SOILSKM*.LOC " + ls +ls); - sb.append(" echo ==== Begin soil match run for crop $CROP_NAME." +ls); + sb.append(" rm -rf $SCEN_DIR/$CROP_NAME/NONRISOIL*.DAT >& /dev/null " + ls); + sb.append(" rm -rf $SCEN_DIR/$CROP_NAME/SOILSKM*.LOC >& /dev/null" + ls + ls); + sb.append(" echo ==== Begin soil match run for crop $CROP_NAME." + ls); sb.append(" echo ==== Running step 1 .... " + ls); - sb.append(" time $EXEC_DIR/SOILMATCH1ST.exe" + ls ); - + sb.append(" time $EXEC_DIR/SOILMATCH1ST.exe" + ls); + sb.append(" " + ls); sb.append(" echo ==== Running step 2 .... " + ls); - sb.append(" time $EXEC_DIR/SOILMATCH2ND.exe" + ls ); - + sb.append(" time $EXEC_DIR/SOILMATCH2ND.exe" + ls); + sb.append(" " + ls); sb.append(" echo ==== Running step 3 .... " + ls); - sb.append(" time $EXEC_DIR/SOILMATCH3RD.exe" + ls ); - + sb.append(" time $EXEC_DIR/SOILMATCH3RD.exe" + ls); + sb.append(" " + ls); sb.append(" echo ==== Running step 4 .... " + ls); - sb.append(" time $EXEC_DIR/SOILMATCH4TH.exe" + ls ); - + sb.append(" time $EXEC_DIR/SOILMATCH4TH.exe" + ls); + sb.append(" " + ls); sb.append(" echo ==== Running step 5 .... " + ls); - sb.append(" time $EXEC_DIR/SOILMATCH5TH.exe" + ls ); - + sb.append(" time $EXEC_DIR/SOILMATCH5TH.exe" + ls); + sb.append(" " + ls); sb.append(" echo ==== Running step 6 .... " + ls); - sb.append(" time $EXEC_DIR/SOILMATCH6TH.exe" + ls ); - + sb.append(" time $EXEC_DIR/SOILMATCH6TH.exe" + ls); + sb.append(" if ( $status == 0 ) then " + ls); sb.append(" echo ==== Finished soil match run for crop $CROP_NAME. " + ls); sb.append(" else " + ls); - sb.append(" echo ==status== Error in soil match run for crop $CROP_NAME. "+ ls + ls); - sb.append(" exit 1 " + ls ); + sb.append(" echo ==status== Error in soil match run for crop $CROP_NAME. " + ls + ls); + sb.append(" exit 1 " + ls); sb.append(" endif " + ls); sb.append(" " + ls); sb.append(" echo \" Merging *LOC to SOILLIST.DAT\"" + ls); sb.append(" cat $SCEN_DIR/$CROP_NAME/*LOC > $SCEN_DIR/$CROP_NAME/SOILLIST.DAT" + ls); sb.append("end " + ls); sb.append(ls); - -// outMessages += " Inputs: ALL-CULTIVATED10-12-09.LST" + ls; -// outMessages += " NRI-ALL-HUC8S-ALLCROPS.prn" + ls; -// outMessages += " HUC8_SITE_INFO-2REV.prn" + ls; -// outMessages += " NRI-crop-codes-BELD4-codes.prn" + ls; -// outMessages += " HUC8NRICROPSOIL.DAT" + ls; -// outMessages += " HUCSITELATLONG.DAT" + ls; + + // outMessages += " Inputs: ALL-CULTIVATED10-12-09.LST" + ls; + // outMessages += " NRI-ALL-HUC8S-ALLCROPS.prn" + ls; + // outMessages += " HUC8_SITE_INFO-2REV.prn" + ls; + // outMessages += " NRI-crop-codes-BELD4-codes.prn" + ls; + // outMessages += " HUC8NRICROPSOIL.DAT" + ls; + // outMessages += " HUCSITELATLONG.DAT" + ls; outMessages += " Step 1 output: $SCEN_DIR/$CROP SOILSKM1.LOC" + ls; - outMessages += " Step 2 output: $SCEN_DIR/$CROP SOILSKM2.LOC" + ls; - outMessages += " ... " ; - outMessages += " Final output : $SCEN_DIR/$CROP *.LOC > SOILLIST.DAT" + ls; - + outMessages += " Step 2 output: $SCEN_DIR/$CROP SOILSKM2.LOC" + ls; + outMessages += " ... "; + outMessages += " Final output : $SCEN_DIR/$CROP *.LOC > SOILLIST.DAT" + ls; + return sb.toString(); } @@ -273,24 +515,27 @@ private String getRunDef(String cropNames) { public void projectLoaded() { fields = (SoilFilesFields) app.getProject().getPage(fields.getName()); domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); - if ( fields != null ){ + if (fields != null) { String scenloc = domain.getScenarioDir(); - if (scenloc != null && scenloc.trim().length()>0 ) + if (scenloc != null && scenloc.trim().length() > 0) this.scenarioDir.setText(scenloc); - else + else this.scenarioDir.setText(fields.getScenarioDir()); runMessages.setText(fields.getMessage()); - }else{ + } else { newProjectCreated(); } - + } @Override public void saveProjectRequested() { - if ( scenarioDir != null ) domain.setScenarioDir(scenarioDir.getText()); - if ( scenarioDir != null ) fields.setScenarioDir(scenarioDir.getText()); - if ( runMessages != null ) fields.setMessage(runMessages.getText()); + if (scenarioDir != null) + domain.setScenarioDir(scenarioDir.getText()); + if (scenarioDir != null) + fields.setScenarioDir(scenarioDir.getText()); + if (runMessages != null) + fields.setMessage(runMessages.getText()); } @Override @@ -298,9 +543,9 @@ public void newProjectCreated() { domain = (DomainFields) app.getProject().getPage(DomainFields.class.getCanonicalName()); scenarioDir.setText(domain.getScenarioDir()); runMessages.setText(""); - if ( fields == null ) { + if (fields == null) { fields = new SoilFilesFields(); app.getProject().addPage(fields); } - } + } } diff --git a/festc_core/src/gov/epa/festc/gui/ViewFileDialog.java b/festc_core/src/gov/epa/festc/gui/ViewFileDialog.java index a7e2741..499d8f3 100644 --- a/festc_core/src/gov/epa/festc/gui/ViewFileDialog.java +++ b/festc_core/src/gov/epa/festc/gui/ViewFileDialog.java @@ -1,269 +1,269 @@ -package gov.epa.festc.gui; - -import gov.epa.festc.core.FestcApplication; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Frame; -import java.awt.Point; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; - -public class ViewFileDialog extends JDialog { - private static final long serialVersionUID = 712640590623729433L; - private File file; - private JTextArea text; - - private boolean editable = false; - private int maxWidth, preferedWidth; - private int maxHeight, preferedHeight; - private FestcApplication app; - - ViewFileDialog() { - super.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/epa_logo.JPG"))); - } - - ViewFileDialog(Frame parent, String title, File file, boolean editable) { - super(parent); - super.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/epa_logo.JPG"))); - - this.file = file; - this.editable = editable; - - Container contentPane = getContentPane(); - contentPane.setLayout(new BorderLayout(5, 5)); // Border Layout does not respect maxSize - //contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); - contentPane.add(createScrollTextPane(file)); - contentPane.add(createButtonsPanel(), BorderLayout.SOUTH); - //contentPane.add(createButtonsPanel()); - setTitle(title); - - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - maxWidth = (int) (screenSize.getWidth()*0.7); - maxHeight = (int) (screenSize.getHeight()*0.7); - preferedWidth = (int) (screenSize.getWidth()/3); - preferedHeight = (int) (screenSize.getHeight()/2); - - setMinimumSize(new Dimension(150,350)); - setPreferredSize(new Dimension(preferedWidth,preferedHeight)); - setMaximumSize(new Dimension(maxWidth,maxHeight)); - setSize(preferedWidth, preferedHeight); - -// System.out.println(preferedWidth); -// System.out.println(preferedHeight); - - if (parent != null) { - //setPreferredSize(parent.getSize()); - setLocation(getPointToCenter(parent)); - } - - pack(); - setModal(true); - } - - private JComponent createScrollTextPane(File file) { - text = new JTextArea(); - text.setText(getFileContent(file)); - text.setEditable(this.editable); - text.setMaximumSize(new Dimension(this.maxWidth,this.maxHeight)); - ScrollablePanel panel = new ScrollablePanel(); - panel.add(text); - //panel.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT ); - panel.setScrollableBlockIncrement( - ScrollablePanel.VERTICAL, ScrollablePanel.IncrementType.PERCENT, 200); - panel.setScrollableBlockIncrement( - ScrollablePanel.HORIZONTAL, ScrollablePanel.IncrementType.PERCENT, 200); - //return panel; - //JScrollPane scroll = new JScrollPane(text); - JScrollPane scroll = new JScrollPane(panel); - scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); - scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - scroll.setMaximumSize(new Dimension(this.maxWidth,this.maxHeight)); - scroll.setPreferredSize(new Dimension(this.preferedWidth,this.preferedHeight)); - - return scroll; - } - - private void saveToFile() throws IOException{ - if ( file == null) { - return; - } - - BufferedWriter writer = new BufferedWriter( new FileWriter(file)); - String content = text.getText(); - if (writer!=null) { - writer.write( content); - writer.flush(); - writer.close(); - } - } - - private String getFileContent(File file) { - StringBuilder sb = new StringBuilder(); - - if (file == null || !file.exists()) { - return sb.toString(); - } - - BufferedReader reader = null; - String line = null; - - try { - reader = new BufferedReader(new FileReader(file)); - while ((line = reader.readLine()) != null) - sb.append(line + "\n"); - } catch (IOException e) { - sb.append("Error reading file!\n"); - } finally { - if (reader != null) - try { - reader.close(); - } catch (IOException e) { - sb.append("Error closing file. " + e.getMessage() + "\n"); - } - } - - return sb.toString(); - } - - private Action save() { - return new AbstractAction("Save") { - - /** - * - */ - private static final long serialVersionUID = 3366464532536102377L; - - public void actionPerformed(ActionEvent e) { - - try { - saveToFile(); - } catch (Exception ex) { - app.showMessage("Save file", ex.getMessage()); - } - - } - }; - } - - private JPanel createButtonsPanel() { - JPanel container = new JPanel(); - - if ( this.editable) { - JButton saveButton = new JButton(" Save "); - saveButton.addActionListener(save()); - container.add(saveButton); - JButton closeButton = new JButton(" Close "); - closeButton.addActionListener(close()); - container.add(closeButton); - } else { - JButton closeButton = new JButton(" Close "); - closeButton.addActionListener(close()); - container.add(closeButton); - } - -// JButton saveButton = new JButton("Save"); -// saveButton.addActionListener(saveFileAction()); -// container.add(saveButton); -// -// JButton saveAsButton = new JButton("Save As..."); -// saveAsButton.setMargin(new Insets(2, 4, 2, 4)); -// saveAsButton.addActionListener(saveAsAction()); -// container.add(saveAsButton); - - return container; - } - - private Action close() { - return new AbstractAction() { - private static final long serialVersionUID = 751779481914111010L; - - public void actionPerformed(ActionEvent e) { - dispose(); - } - }; - } - - public static Point getPointToCenter(Component comp) { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - if (comp == null) { - return new Point((int)screenSize.getWidth()/2,(int)screenSize.getHeight()/2); - } - - Dimension frameSize = comp.getSize(); - - if (frameSize.height > screenSize.height) { - frameSize.height = screenSize.height; - } - - if (frameSize.width > screenSize.width) { - frameSize.width = screenSize.width; - } - - return new Point( (screenSize.width - frameSize.width) / 2, - (screenSize.height - frameSize.height) / 2); - } - - // do not use the following now - get back to it later!! - /* - public static void main(String[] args) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - new ViewFileDialog().makeUI(); - } - }); - } - - public void makeUI() { - final JFrame frame = new ViewFileDialog("") { - - @Override - public void paint(Graphics g) { - Dimension d = getSize(); - Dimension m = getMaximumSize(); - boolean resize = d.width > m.width || d.height > m.height; - d.width = Math.min(m.width, d.width); - d.height = Math.min(m.height, d.height); - if (resize) { - Point p = getLocation(); - setVisible(false); - setSize(d); - setLocation(p); - setVisible(true); - } - super.paint(g); - } - }; - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS E); - frame.setSize(400, 400); - frame.setMaximumSize(new Dimension(500, 500)); - frame.setMinimumSize(new Dimension(300, 300)); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - } - - } - */ - -} - +package gov.epa.festc.gui; + +import gov.epa.festc.core.FestcApplication; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +public class ViewFileDialog extends JDialog { + private static final long serialVersionUID = 712640590623729433L; + private File file; + private JTextArea text; + + private boolean editable = false; + private int maxWidth, preferedWidth; + private int maxHeight, preferedHeight; + private FestcApplication app; + + ViewFileDialog() { + super.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/epa_logo.JPG"))); + } + + ViewFileDialog(Frame parent, String title, File file, boolean editable) { + super(parent); + super.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/epa_logo.JPG"))); + + this.file = file; + this.editable = editable; + + Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout(5, 5)); // Border Layout does not respect maxSize + //contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); + contentPane.add(createScrollTextPane(file)); + contentPane.add(createButtonsPanel(), BorderLayout.SOUTH); + //contentPane.add(createButtonsPanel()); + setTitle(title); + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + maxWidth = (int) (screenSize.getWidth()*0.7); + maxHeight = (int) (screenSize.getHeight()*0.7); + preferedWidth = (int) (screenSize.getWidth()/3); + preferedHeight = (int) (screenSize.getHeight()/2); + + setMinimumSize(new Dimension(150,350)); + setPreferredSize(new Dimension(preferedWidth,preferedHeight)); + setMaximumSize(new Dimension(maxWidth,maxHeight)); + setSize(preferedWidth, preferedHeight); + +// System.out.println(preferedWidth); +// System.out.println(preferedHeight); + + if (parent != null) { + //setPreferredSize(parent.getSize()); + setLocation(getPointToCenter(parent)); + } + + pack(); + setModal(true); + } + + private JComponent createScrollTextPane(File file) { + text = new JTextArea(); + text.setText(getFileContent(file)); + text.setEditable(this.editable); + text.setMaximumSize(new Dimension(this.maxWidth,this.maxHeight)); + ScrollablePanel panel = new ScrollablePanel(); + panel.add(text); + //panel.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT ); + panel.setScrollableBlockIncrement( + ScrollablePanel.VERTICAL, ScrollablePanel.IncrementType.PERCENT, 200); + panel.setScrollableBlockIncrement( + ScrollablePanel.HORIZONTAL, ScrollablePanel.IncrementType.PERCENT, 200); + //return panel; + //JScrollPane scroll = new JScrollPane(text); + JScrollPane scroll = new JScrollPane(panel); + scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scroll.setMaximumSize(new Dimension(this.maxWidth,this.maxHeight)); + scroll.setPreferredSize(new Dimension(this.preferedWidth,this.preferedHeight)); + + return scroll; + } + + private void saveToFile() throws IOException{ + if ( file == null) { + return; + } + + BufferedWriter writer = new BufferedWriter( new FileWriter(file)); + String content = text.getText(); + if (writer!=null) { + writer.write( content); + writer.flush(); + writer.close(); + } + } + + private String getFileContent(File file) { + StringBuilder sb = new StringBuilder(); + + if (file == null || !file.exists()) { + return sb.toString(); + } + + BufferedReader reader = null; + String line = null; + + try { + reader = new BufferedReader(new FileReader(file)); + while ((line = reader.readLine()) != null) + sb.append(line + "\n"); + } catch (IOException e) { + sb.append("Error reading file!\n"); + } finally { + if (reader != null) + try { + reader.close(); + } catch (IOException e) { + sb.append("Error closing file. " + e.getMessage() + "\n"); + } + } + + return sb.toString(); + } + + private Action save() { + return new AbstractAction("Save") { + + /** + * + */ + private static final long serialVersionUID = 3366464532536102377L; + + public void actionPerformed(ActionEvent e) { + + try { + saveToFile(); + } catch (Exception ex) { + app.showMessage("Save file", ex.getMessage()); + } + + } + }; + } + + private JPanel createButtonsPanel() { + JPanel container = new JPanel(); + + if ( this.editable) { + JButton saveButton = new JButton(" Save "); + saveButton.addActionListener(save()); + container.add(saveButton); + JButton closeButton = new JButton(" Close "); + closeButton.addActionListener(close()); + container.add(closeButton); + } else { + JButton closeButton = new JButton(" Close "); + closeButton.addActionListener(close()); + container.add(closeButton); + } + +// JButton saveButton = new JButton("Save"); +// saveButton.addActionListener(saveFileAction()); +// container.add(saveButton); +// +// JButton saveAsButton = new JButton("Save As..."); +// saveAsButton.setMargin(new Insets(2, 4, 2, 4)); +// saveAsButton.addActionListener(saveAsAction()); +// container.add(saveAsButton); + + return container; + } + + private Action close() { + return new AbstractAction() { + private static final long serialVersionUID = 751779481914111010L; + + public void actionPerformed(ActionEvent e) { + dispose(); + } + }; + } + + public static Point getPointToCenter(Component comp) { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + if (comp == null) { + return new Point((int)screenSize.getWidth()/2,(int)screenSize.getHeight()/2); + } + + Dimension frameSize = comp.getSize(); + + if (frameSize.height > screenSize.height) { + frameSize.height = screenSize.height; + } + + if (frameSize.width > screenSize.width) { + frameSize.width = screenSize.width; + } + + return new Point( (screenSize.width - frameSize.width) / 2, + (screenSize.height - frameSize.height) / 2); + } + + // do not use the following now - get back to it later!! + /* + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + new ViewFileDialog().makeUI(); + } + }); + } + + public void makeUI() { + final JFrame frame = new ViewFileDialog("") { + + @Override + public void paint(Graphics g) { + Dimension d = getSize(); + Dimension m = getMaximumSize(); + boolean resize = d.width > m.width || d.height > m.height; + d.width = Math.min(m.width, d.width); + d.height = Math.min(m.height, d.height); + if (resize) { + Point p = getLocation(); + setVisible(false); + setSize(d); + setLocation(p); + setVisible(true); + } + super.paint(g); + } + }; + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS E); + frame.setSize(400, 400); + frame.setMaximumSize(new Dimension(500, 500)); + frame.setMinimumSize(new Dimension(300, 300)); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + } + */ + +} + diff --git a/festc_core/src/gov/epa/festc/gui/VisualizationPanel.java b/festc_core/src/gov/epa/festc/gui/VisualizationPanel.java index 4963894..a847d7b 100644 --- a/festc_core/src/gov/epa/festc/gui/VisualizationPanel.java +++ b/festc_core/src/gov/epa/festc/gui/VisualizationPanel.java @@ -1,337 +1,337 @@ -package gov.epa.festc.gui; - -import gov.epa.festc.core.FestcApplication; -import gov.epa.festc.core.proj.SiteFilesFields; -import gov.epa.festc.core.proj.VisualizationFields; -import gov.epa.festc.util.Constants; -import gov.epa.festc.util.SpringLayoutGenerator; - -import java.awt.BorderLayout; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JTextField; -import javax.swing.SpringLayout; -import javax.swing.SwingConstants; - -import simphony.util.messages.MessageCenter; - -public class VisualizationPanel extends JPanel implements PlotEventListener { - private static final long serialVersionUID = 7114847591403108679L; - private JTextField mcipFile; - private JButton mcipFileBrowser; - private JTextField beldFile; - private JButton beldFileBrowser; - private JTextField epicFile; - private JButton epicFileBrowser; - private JRadioButton mcipButton; - private JRadioButton beldButton; - private JRadioButton epicButton; - private MessageCenter msg; - private FestcApplication app; - private VisualizationFields fields; - - public VisualizationPanel(FestcApplication application) { - app = application; - msg = app.getMessageCenter(); - fields = new VisualizationFields(); - app.getProject().addPage(fields); - app.addPlotListener(this); - add(createPanel()); - } - - private JPanel createPanel() { - JPanel main = new JPanel(new BorderLayout()); - main.add(getNorthPanel(), BorderLayout.NORTH); - main.add(getCenterPanel(), BorderLayout.CENTER); - main.add(getSouthPanel(), BorderLayout.SOUTH); - return main; - } - - private JPanel getNorthPanel() { - JPanel panel = new JPanel(); - JLabel title = new JLabel(Constants.VISU, SwingConstants.CENTER); - title.setFont(new Font("Default", Font.BOLD, 20)); - - panel.add(title); - panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 60, 0)); - - return panel; - } - - private JPanel getSouthPanel() { - JPanel panel = new JPanel(); - JButton display = new JButton(displayAction()); - panel.add(display); - - panel.setBorder(BorderFactory.createEmptyBorder(60, 0, 10, 0)); - - return panel; - } - - private JPanel getCenterPanel() { - JPanel panel = new JPanel(new SpringLayout()); - SpringLayoutGenerator layout = new SpringLayoutGenerator(); - - mcipButton = new JRadioButton("MCIP Data:"); - beldButton = new JRadioButton("Model Grid BELD Data:"); - epicButton = new JRadioButton("EPIC Output Data:"); - ButtonGroup group = new ButtonGroup(); - epicButton.setSelected(true); - group.add(mcipButton); - group.add(beldButton); - group.add(epicButton); - - JPanel mcip = new JPanel(); - mcipFile = new JTextField(40); - mcipFileBrowser = new JButton(browseAction("MCIP data file", mcipFile)); - mcip.add(mcipFile); - mcip.add(mcipFileBrowser); - - JPanel beld = new JPanel(); - beldFile = new JTextField(40); - beld.add(beldFile); - beldFileBrowser = new JButton(browseAction("BELD data file", beldFile)); - beld.add(beldFileBrowser); - - JPanel epic = new JPanel(); - epicFile = new JTextField(40); - epicFileBrowser = new JButton(browseAction("EPIC data file", epicFile)); - epic.add(epicFile); - epic.add(epicFileBrowser); - -// String[] vars = new String[] { "Select a variable...", -// "CANOPY(Percent)", "IMPERV(Percent)", "LANDMASK(None)", -// "LU_INDEX(Category)", "XLAT_M(degrees latitude)", -// "XLONG_M(degrees longitude" }; -// JComboBox varBox = new JComboBox(vars); -// epic.add(varBox); - - layout.addWidgetPair(mcipButton, mcip, panel); - layout.addWidgetPair(beldButton, beld, panel); - layout.addWidgetPair(epicButton, epic, panel); - - layout.makeCompactGrid(panel, 3, 2, // number of rows and cols - 10, 10, // initial X and Y - 5, 5); // x and y pading - - return panel; - } - - private Action displayAction() { - return new AbstractAction("Display") { - private static final long serialVersionUID = 8505323087261015010L; - - public void actionPerformed(ActionEvent e) { - String temp = epicFile.getText(); - - if (beldButton.isSelected()) - temp = beldFile.getText(); - - if (mcipButton.isSelected()) - temp = mcipFile.getText(); - - if (temp == null || temp.trim().isEmpty()) - return; - - temp = temp.trim(); - - File file = new File(temp); - - if (!file.isFile() || !file.exists()) - return; - - final String filePath = temp; - - Thread populateThread = new Thread(new Runnable() { - public void run() { - callVerdi(filePath); - } - }); - populateThread.start(); - } - }; - } - - private Action browseAction(final String name, final JTextField text) { - return new AbstractAction("Browse...") { - private static final long serialVersionUID = 0L; - - public void actionPerformed(ActionEvent e) { - JFileChooser chooser; - File file = new File(text.getText()); - - if (file != null && file.exists()) - chooser = new JFileChooser(file); - else - chooser = new JFileChooser(app.getCurrentDir()); - - chooser.setDialogTitle("Please select the " + name); - - int option = chooser.showDialog(VisualizationPanel.this, - "Select"); - if (option == JFileChooser.APPROVE_OPTION) { - File selected = chooser.getSelectedFile(); - text.setText("" + selected); - app.setCurrentDir(selected.getParentFile()); - } - } - }; - } - - private void callVerdi(final String file) { - String visProgHome = Constants.getProperty(Constants.VISUAL_PROGRAM_HOME, msg); - String visProg = Constants.getProperty(Constants.VISUAL_PROGRAM, msg); - File ncfile = new File(file.replaceAll("\\\\", "\\\\\\\\")); - ProcessBuilder pb = null; - String cmd = visProgHome.replaceAll("\\\\", "\\\\\\\\"); - - String osName = System.getProperty("os.name"); - if (osName.equals("Linux") || osName.trim().equalsIgnoreCase("Mac OS X")) { - cmd += "/" + visProg + " " + ncfile; - System.out.println("Command: " + cmd); - pb = new ProcessBuilder("csh", "-c", cmd); - } - - // set up the working directory. - pb.directory(ncfile.getParentFile()); - - // merge child's error and normal output streams. - pb.redirectErrorStream(true); - - Process p = null; - - try { - p = pb.start(); - final InputStream es = p.getErrorStream(); - final InputStream is = p.getInputStream(); - - // spawn two threads to handle I/O with child while we wait for it - // to complete. - Thread esthread = new Thread(new Runnable() { - public void run() { - readMsg(msg, es, "ERROR"); - } - }); - esthread.start(); - - Thread isthread = new Thread(new Runnable() { - public void run() { - readMsg(msg, is, "INPUT"); - } - }); - isthread.start(); - - - if (Constants.DEBUG) { - System.out.println("Verdi starting Process started: " + p.toString()); - msg.info("Verdi starting Process started: " + p.toString()); - } - - p.waitFor(); - es.close(); - is.close(); - - if (Constants.DEBUG) { - System.out.println("Verdi starting Process finished."); - msg.info("Verdi starting Process finished."); - } - } catch (IOException e) { - System.out.println("Error happened: " + e.getMessage()); - e.printStackTrace(); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - System.out.println("Interrupted: " + e.getMessage()); - e.printStackTrace(); - } - catch (Exception e) { - System.out.println("Error happened: " + e.getMessage()); - e.printStackTrace(); - } - finally { - if (p != null) { - try { - p.getErrorStream().close(); - p.getInputStream().close(); - } catch (IOException e) { - // - } - } - } - } - - private void readMsg(MessageCenter msgcenter, InputStream is, String type) { - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - - try { - String message = reader.readLine(); - - if (type.equals("ERROR") && message != null) - msgcenter.warn("Running Script:", new Exception(message)); - - if (type.equals("INPUT")) - msgcenter.info("Start running script.", (message != null ? message : "")); - } catch (Exception e) { - msgcenter.warn("Error reading message:", e); - } finally { - try { - reader.close(); - } catch (Exception e) { - msgcenter.warn("Error closing reading message:", e); - } - } - - } - - @Override - public void projectLoaded() { - fields = (VisualizationFields) app.getProject().getPage(fields.getName()); - if ( fields != null ){ - mcipFile.setText(fields.getMcipDataDir()); - beldFile.setText(fields.getBeldDataDir()); - epicFile.setText(fields.getEpicDataDir()); - mcipButton.setSelected(fields.isMcipDataSelected()); - beldButton.setSelected(fields.isBeldDataSelected()); - epicButton.setSelected(fields.isEpicDataSelected()); - } else{ - newProjectCreated(); - } - } - - @Override - public void saveProjectRequested() { - if (mcipFile != null) fields.setMcipDataDir(mcipFile.getText()); - if (beldFile != null) fields.setBeldDataDir(beldFile.getText()); - if (epicFile != null) fields.setEpicDataDir(epicFile.getText()); - if (mcipButton != null) fields.setMcipDataSelected(mcipButton.isSelected()); - if (beldButton != null) fields.setBeldDataSelected(beldButton.isSelected()); - if (epicButton != null) fields.setEpicDataSelected(epicButton.isSelected()); - } - - @Override - public void newProjectCreated() { - fields.setMcipDataDir(""); - fields.setBeldDataDir(""); - fields.setEpicDataDir(""); - if (fields == null){ - fields = new VisualizationFields(); - app.getProject().addPage(fields); - } - } - -} +package gov.epa.festc.gui; + +import gov.epa.festc.core.FestcApplication; +import gov.epa.festc.core.proj.SiteFilesFields; +import gov.epa.festc.core.proj.VisualizationFields; +import gov.epa.festc.util.Constants; +import gov.epa.festc.util.SpringLayoutGenerator; + +import java.awt.BorderLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.SpringLayout; +import javax.swing.SwingConstants; + +import simphony.util.messages.MessageCenter; + +public class VisualizationPanel extends JPanel implements PlotEventListener { + private static final long serialVersionUID = 7114847591403108679L; + private JTextField mcipFile; + private JButton mcipFileBrowser; + private JTextField beldFile; + private JButton beldFileBrowser; + private JTextField epicFile; + private JButton epicFileBrowser; + private JRadioButton mcipButton; + private JRadioButton beldButton; + private JRadioButton epicButton; + private MessageCenter msg; + private FestcApplication app; + private VisualizationFields fields; + + public VisualizationPanel(FestcApplication application) { + app = application; + msg = app.getMessageCenter(); + fields = new VisualizationFields(); + app.getProject().addPage(fields); + app.addPlotListener(this); + add(createPanel()); + } + + private JPanel createPanel() { + JPanel main = new JPanel(new BorderLayout()); + main.add(getNorthPanel(), BorderLayout.NORTH); + main.add(getCenterPanel(), BorderLayout.CENTER); + main.add(getSouthPanel(), BorderLayout.SOUTH); + return main; + } + + private JPanel getNorthPanel() { + JPanel panel = new JPanel(); + JLabel title = new JLabel(Constants.VISU, SwingConstants.CENTER); + title.setFont(new Font("Default", Font.BOLD, 20)); + + panel.add(title); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 60, 0)); + + return panel; + } + + private JPanel getSouthPanel() { + JPanel panel = new JPanel(); + JButton display = new JButton(displayAction()); + panel.add(display); + + panel.setBorder(BorderFactory.createEmptyBorder(60, 0, 10, 0)); + + return panel; + } + + private JPanel getCenterPanel() { + JPanel panel = new JPanel(new SpringLayout()); + SpringLayoutGenerator layout = new SpringLayoutGenerator(); + + mcipButton = new JRadioButton("MCIP Data:"); + beldButton = new JRadioButton("Model Grid BELD Data:"); + epicButton = new JRadioButton("EPIC Output Data:"); + ButtonGroup group = new ButtonGroup(); + epicButton.setSelected(true); + group.add(mcipButton); + group.add(beldButton); + group.add(epicButton); + + JPanel mcip = new JPanel(); + mcipFile = new JTextField(40); + mcipFileBrowser = new JButton(browseAction("MCIP data file", mcipFile)); + mcip.add(mcipFile); + mcip.add(mcipFileBrowser); + + JPanel beld = new JPanel(); + beldFile = new JTextField(40); + beld.add(beldFile); + beldFileBrowser = new JButton(browseAction("BELD data file", beldFile)); + beld.add(beldFileBrowser); + + JPanel epic = new JPanel(); + epicFile = new JTextField(40); + epicFileBrowser = new JButton(browseAction("EPIC data file", epicFile)); + epic.add(epicFile); + epic.add(epicFileBrowser); + +// String[] vars = new String[] { "Select a variable...", +// "CANOPY(Percent)", "IMPERV(Percent)", "LANDMASK(None)", +// "LU_INDEX(Category)", "XLAT_M(degrees latitude)", +// "XLONG_M(degrees longitude" }; +// JComboBox varBox = new JComboBox(vars); +// epic.add(varBox); + + layout.addWidgetPair(mcipButton, mcip, panel); + layout.addWidgetPair(beldButton, beld, panel); + layout.addWidgetPair(epicButton, epic, panel); + + layout.makeCompactGrid(panel, 3, 2, // number of rows and cols + 10, 10, // initial X and Y + 5, 5); // x and y pading + + return panel; + } + + private Action displayAction() { + return new AbstractAction("Display") { + private static final long serialVersionUID = 8505323087261015010L; + + public void actionPerformed(ActionEvent e) { + String temp = epicFile.getText(); + + if (beldButton.isSelected()) + temp = beldFile.getText(); + + if (mcipButton.isSelected()) + temp = mcipFile.getText(); + + if (temp == null || temp.trim().isEmpty()) + return; + + temp = temp.trim(); + + File file = new File(temp); + + if (!file.isFile() || !file.exists()) + return; + + final String filePath = temp; + + Thread populateThread = new Thread(new Runnable() { + public void run() { + callVerdi(filePath); + } + }); + populateThread.start(); + } + }; + } + + private Action browseAction(final String name, final JTextField text) { + return new AbstractAction("Browse...") { + private static final long serialVersionUID = 0L; + + public void actionPerformed(ActionEvent e) { + JFileChooser chooser; + File file = new File(text.getText()); + + if (file != null && file.exists()) + chooser = new JFileChooser(file); + else + chooser = new JFileChooser(app.getCurrentDir()); + + chooser.setDialogTitle("Please select the " + name); + + int option = chooser.showDialog(VisualizationPanel.this, + "Select"); + if (option == JFileChooser.APPROVE_OPTION) { + File selected = chooser.getSelectedFile(); + text.setText("" + selected); + app.setCurrentDir(selected.getParentFile()); + } + } + }; + } + + private void callVerdi(final String file) { + String visProgHome = Constants.getProperty(Constants.VISUAL_PROGRAM_HOME, msg); + String visProg = Constants.getProperty(Constants.VISUAL_PROGRAM, msg); + File ncfile = new File(file.replaceAll("\\\\", "\\\\\\\\")); + ProcessBuilder pb = null; + String cmd = visProgHome.replaceAll("\\\\", "\\\\\\\\"); + + String osName = System.getProperty("os.name"); + if (osName.equals("Linux") || osName.trim().equalsIgnoreCase("Mac OS X")) { + cmd += "/" + visProg + " " + ncfile; + System.out.println("Command: " + cmd); + pb = new ProcessBuilder("csh", "-c", cmd); + } + + // set up the working directory. + pb.directory(ncfile.getParentFile()); + + // merge child's error and normal output streams. + pb.redirectErrorStream(true); + + Process p = null; + + try { + p = pb.start(); + final InputStream es = p.getErrorStream(); + final InputStream is = p.getInputStream(); + + // spawn two threads to handle I/O with child while we wait for it + // to complete. + Thread esthread = new Thread(new Runnable() { + public void run() { + readMsg(msg, es, "ERROR"); + } + }); + esthread.start(); + + Thread isthread = new Thread(new Runnable() { + public void run() { + readMsg(msg, is, "INPUT"); + } + }); + isthread.start(); + + + if (Constants.DEBUG) { + System.out.println("Verdi starting Process started: " + p.toString()); + msg.info("Verdi starting Process started: " + p.toString()); + } + + p.waitFor(); + es.close(); + is.close(); + + if (Constants.DEBUG) { + System.out.println("Verdi starting Process finished."); + msg.info("Verdi starting Process finished."); + } + } catch (IOException e) { + System.out.println("Error happened: " + e.getMessage()); + e.printStackTrace(); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.out.println("Interrupted: " + e.getMessage()); + e.printStackTrace(); + } + catch (Exception e) { + System.out.println("Error happened: " + e.getMessage()); + e.printStackTrace(); + } + finally { + if (p != null) { + try { + p.getErrorStream().close(); + p.getInputStream().close(); + } catch (IOException e) { + // + } + } + } + } + + private void readMsg(MessageCenter msgcenter, InputStream is, String type) { + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + + try { + String message = reader.readLine(); + + if (type.equals("ERROR") && message != null) + msgcenter.warn("Running Script:", new Exception(message)); + + if (type.equals("INPUT")) + msgcenter.info("Start running script.", (message != null ? message : "")); + } catch (Exception e) { + msgcenter.warn("Error reading message:", e); + } finally { + try { + reader.close(); + } catch (Exception e) { + msgcenter.warn("Error closing reading message:", e); + } + } + + } + + @Override + public void projectLoaded() { + fields = (VisualizationFields) app.getProject().getPage(fields.getName()); + if ( fields != null ){ + mcipFile.setText(fields.getMcipDataDir()); + beldFile.setText(fields.getBeldDataDir()); + epicFile.setText(fields.getEpicDataDir()); + mcipButton.setSelected(fields.isMcipDataSelected()); + beldButton.setSelected(fields.isBeldDataSelected()); + epicButton.setSelected(fields.isEpicDataSelected()); + } else{ + newProjectCreated(); + } + } + + @Override + public void saveProjectRequested() { + if (mcipFile != null) fields.setMcipDataDir(mcipFile.getText()); + if (beldFile != null) fields.setBeldDataDir(beldFile.getText()); + if (epicFile != null) fields.setEpicDataDir(epicFile.getText()); + if (mcipButton != null) fields.setMcipDataSelected(mcipButton.isSelected()); + if (beldButton != null) fields.setBeldDataSelected(beldButton.isSelected()); + if (epicButton != null) fields.setEpicDataSelected(epicButton.isSelected()); + } + + @Override + public void newProjectCreated() { + fields.setMcipDataDir(""); + fields.setBeldDataDir(""); + fields.setEpicDataDir(""); + if (fields == null){ + fields = new VisualizationFields(); + app.getProject().addPage(fields); + } + } + +} diff --git a/festc_core/src/gov/epa/festc/util/Constants.java b/festc_core/src/gov/epa/festc/util/Constants.java index 2508c8e..ed3f182 100644 --- a/festc_core/src/gov/epa/festc/util/Constants.java +++ b/festc_core/src/gov/epa/festc/util/Constants.java @@ -1,159 +1,178 @@ -package gov.epa.festc.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; - -import simphony.util.messages.MessageCenter; - -public class Constants { - public static final String LABEL_EPIC_SCENARIO = "Scenario Directory:"; - public static final String PROPERTY_COMMENT_CHAR = "#"; - public static final String CONFIG_HOME = "config.home"; - public static final String PROJECT_HOME = "project.home"; - public static final String VERDI_HOME = "verdi.home"; - public static final String VISUAL_PROGRAM_HOME = "visual.program.home"; - public static final String VISUAL_PROGRAM = "visual.program"; - public static final String SA_HOME = "sa.home"; - public static final String SA_SETUP_FILE = "/bin/sa_setup.csh"; - public static final String EPIC_HOME = "epic.home"; - public static final String QUEUE_NAME = "queue.name"; - public static final String QUEUE_BMEM = "queue.bigmem"; - //public static final String QUEUE_PRELOG = "queue.prelog"; - public static final String QUEUE_OPT = "queue.option"; - public static final String QUEUE_CMD = "queue.cmd"; - public static final String WORK_DIR = "work.dir"; - public static final String USER_HOME = "user.home"; - public static final String LINE_SEPARATOR = "line.separator"; - public static final String NEW_SCENARIO = "Create"; - public static final String COPY_SCENARIO = "Copy"; - public static final String SAVE_SCENARIO = "Save"; - public static final String DELETE_SCENARIO = "delete"; - public static final String ALLOW_DIFF_CHECK = "allow.diff.check"; - public static final String PROPERTY_FILE = "/festc/config.properties"; - public static final String[] PROJECTIONS = new String[] {"Stand Lambert", "Other"}; - public static final String[] DEPSELECTIONS = new String[] {"CMAQ deposition directory", "Default", "Zero"}; - - // EPIC Action Names - public static final String BELD4_GEN = "BELD4 Data Generation"; - public static final String SITE_INFO = "Crop Site Info Generation"; - public static final String MC2EPIC = "WRF/CMAQ to EPIC"; - public static final String EPIC_SITE = "EPIC Site File Generation"; - public static final String SOIL_MATCH = "Soil Match for EPIC Spinup"; - public static final String MAN_SPINUP = "Management File Generation for Spinup"; - public static final String EDIT_INFILES = "View/Edit EPIC Inputs"; - public static final String[] FERTYEARS = new String[] {"2001", "2006"}; - public static final String[] NLCDYEARS = new String[] {"2001", "2006", "2011"}; - public static final String[] NDEPS = new String[] {"CMAQ", "EPIC parameter input file", - "2002-2006 5-year CMAQ average", - "2006-2010 5-year CMAQ average"}; - public static final String[] SU_NDEPS = new String[] {"EPIC parameter input file", - "2002-2006 5-year CMAQ average", - "2006-2010 5-year CMAQ average"}; - public static final String[] SWAT_NDEPS = new String[] {"CMAQ", - "2002-2006 5-year CMAQ average", - "2006-2010 5-year CMAQ average"}; //dir:dailyNDep_2004, dailyNDep_2008 - public static final String[] AREAS = new String[] {"Domain","State","County","HUC8","HUC6","HUC2"}; - public static final String EPIC_SPINUP = "EPIC Runs for Spinup"; - public static final String MAN_APP = "Management File Generation for Application"; - public static final String EPIC_APP = "EPIC Runs for Application"; - public static final String EPIC_YEAR = "EPIC Yearly Extraction"; - public static final String EPIC2CMAQ = "EPIC to CMAQ"; - public static final String EPIC2SWAT = "EPIC to SWAT"; - public static final String VISU = "Visualization"; - - // Crop list - public static final HashMap CROPS = new HashMap(){ - private static final long serialVersionUID = -7600822219153629808L; - { - put("HAY", 1); - put("ALFALFA", 3); - put("OTHGRASS", 5); - put("BARLEY", 7); - put("EBEANS", 9); - put("CORNG", 11); - put("CORNS", 13); - put("COTTON", 15); - put("OATS", 17); - put("PEANUTS", 19); - put("POTATOES", 21); - put("RICE", 23); - put("RYE", 25); - put("SORGHUMG", 27); - put("SORGHUMS", 29); - put("SOYBEANS", 31); - put("SWHEAT", 33); - put("WWHEAT", 35); - put("OTHER", 37); - put("CANOLA", 39); - put("BEANS", 41); - } - }; - - public static final String[] CATEGORIES = new String[]{ - "SIT", - "SOL", - "OPC", - "OPS" - }; - - public static final String BOX_SIZE = "This is used to calculate combobox sizes."; - - public static boolean DEBUG=true; - - private static boolean propertiesLoaded = false; - - - private static void loadPropertyFile(MessageCenter msg) { - - File file = new File(System.getProperty(USER_HOME) + PROPERTY_FILE); - try { - if (!file.exists()) { - msg.warn("Error loading config properties", new Exception("File " + file + " doesn't exist.")); - System.out.println("File " + file + " doesn't exist."); - System.exit(1); - } - - if (file.exists()) { - System.getProperties().load(new FileInputStream(file)); - propertiesLoaded = true; - System.out.println("Config file " + file + " loaded at: " + new Date()); - } - - if ( System.getProperty("debug") == null) { - DEBUG = false; - } else { - DEBUG = "TRUE".equalsIgnoreCase(System.getProperty("debug").trim()); // init the debug according to config file - } - - test(); - - } catch (IOException e) { - msg.warn("Error loading config properties", e); - } - } - - public static String getProperty(String key, MessageCenter msg) { - if (!propertiesLoaded) - loadPropertyFile(msg); - - String prop = System.getProperty(key); - if ( prop != null) { - if (prop.contains(PROPERTY_COMMENT_CHAR)) { - prop = prop.substring(0, prop.indexOf(PROPERTY_COMMENT_CHAR)); - } - prop = prop.trim(); - } - return prop; - } - - private static void test() { - MessageCenter msg = MessageCenter.getMessageCenter(Constants.class); - System.out.println(getProperty("visual.program.home", msg)); - System.out.println(getProperty("visual.program", msg)); - - } - -} +package gov.epa.festc.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; + +import simphony.util.messages.MessageCenter; + +public class Constants { + public static final String LABEL_EPIC_SCENARIO = "Scenario Directory:"; + public static final String PROPERTY_COMMENT_CHAR = "#"; + public static final String CONFIG_HOME = "config.home"; + public static final String PROJECT_HOME = "project.home"; + public static final String VERDI_HOME = "verdi.home"; + public static final String VISUAL_PROGRAM_HOME = "visual.program.home"; + public static final String VISUAL_PROGRAM = "visual.program"; + public static final String SA_HOME = "sa.home"; + public static final String SA_SETUP_FILE = "/bin/sa_setup.csh"; + public static final String EPIC_HOME = "epic.home"; + public static final String QUEUE_NAME = "queue.name"; +// public static final String QUEUE_BMEM = "queue.bigmem"; + //public static final String QUEUE_PRELOG = "queue.prelog"; + public static final String QUEUE_OPT = "queue.option"; + public static final String QUEUE_CMD = "queue.cmd"; + public static final String QUEUE_R_MODULE = "queue.Rmodules"; + public static final String QUEUE_SINGULARITY_MODULE = "queue.singularitymodule"; + public static final String QUEUE_SINGULARITY_IMAGE = "queue.singularityimage"; + public static final String QUEUE_SINGULARITY_BIND = "queue.singularitybind"; + + public static final String QUEUE_BELD4_CMD = "queue.beld4"; + public static final String QUEUE_SITE_INFO = "queue.siteinfo"; + public static final String QUEUE_MC2EPIC = "queue.mc2epic"; + public static final String QUEUE_EPIC_SITE = "queue.epicsite"; + public static final String QUEUE_SOIL_MATCH = "queue.soilmatch"; + public static final String QUEUE_MAN_SPINUP = "queue.manspinup"; + public static final String QUEUE_EPIC_SPINUP = "queue.epicspinup"; + public static final String QUEUE_MAN_APP = "queue.manapp"; + public static final String QUEUE_EPIC_APP = "queue.epicapp"; + public static final String QUEUE_YEARLY_EXT = "queue.yearlyext"; + public static final String QUEUE_EPIC2CMAQ = "queue.epic2cmaq"; + public static final String QUEUE_EPIC2SWAT = "queue.epic2swat"; + + public static final String WORK_DIR = "work.dir"; + public static final String EPIC_VER = "epic.ver"; + public static final String USER_HOME = "user.home"; + public static final String LINE_SEPARATOR = "line.separator"; + public static final String NEW_SCENARIO = "Create"; + public static final String COPY_SCENARIO = "Copy"; + public static final String SAVE_SCENARIO = "Save"; + public static final String DELETE_SCENARIO = "delete"; + public static final String ALLOW_DIFF_CHECK = "allow.diff.check"; + public static final String PROPERTY_FILE = "/festc/config.properties"; + public static final String[] PROJECTIONS = new String[] {"Stand Lambert", "Other"}; + public static final String[] DEPSELECTIONS = new String[] {"CMAQ deposition directory", "Default", "Zero"}; + + // EPIC Action Names + public static final String BELD4_GEN = "BELD4 Data Generation"; + public static final String SITE_INFO = "Crop Site Info Generation"; + public static final String MC2EPIC = "WRF/CMAQ to EPIC"; + public static final String EPIC_SITE = "EPIC Site File Generation"; + public static final String SOIL_MATCH = "Soil Match for EPIC Spinup"; + public static final String MAN_SPINUP = "Management File Generation for Spinup"; + public static final String EDIT_INFILES = "View/Edit EPIC Inputs"; + public static final String[] FERTYEARS = new String[] {"2001", "2006", "2011", "2016"}; + public static final String[] NLCDYEARS = new String[] {"2001", "2006", "2011"}; + public static final String[] NDEPS = new String[] {"CMAQ", "EPIC parameter input file", + "2002-2006 5-year CMAQ average", + "2006-2010 5-year CMAQ average"}; + public static final String[] SU_NDEPS = new String[] {"EPIC parameter input file", + "2002-2006 5-year CMAQ average", + "2006-2010 5-year CMAQ average"}; + public static final String[] SWAT_NDEPS = new String[] {"CMAQ", + "2002-2006 5-year CMAQ average", + "2006-2010 5-year CMAQ average"}; //dir:dailyNDep_2004, dailyNDep_2008 + public static final String[] AREAS = new String[] {"Domain","State","County","HUC8","HUC6","HUC2"}; + public static final String EPIC_SPINUP = "EPIC Runs for Spinup"; + public static final String MAN_APP = "Management File Generation for Application"; + public static final String EPIC_APP = "EPIC Runs for Application"; + public static final String EPIC_YEAR = "EPIC Yearly Extraction"; + public static final String EPIC2CMAQ = "EPIC to CMAQ"; + public static final String EPIC2SWAT = "EPIC to SWAT"; + public static final String VISU = "Visualization"; + + // Crop list + public static final HashMap CROPS = new HashMap(){ + private static final long serialVersionUID = -7600822219153629808L; + { + put("HAY", 1); + put("ALFALFA", 3); + put("OTHGRASS", 5); + put("BARLEY", 7); + put("EBEANS", 9); + put("CORNG", 11); + put("CORNS", 13); + put("COTTON", 15); + put("OATS", 17); + put("PEANUTS", 19); + put("POTATOES", 21); + put("RICE", 23); + put("RYE", 25); + put("SORGHUMG", 27); + put("SORGHUMS", 29); + put("SOYBEANS", 31); + put("SWHEAT", 33); + put("WWHEAT", 35); + put("OTHER", 37); + put("CANOLA", 39); + put("BEANS", 41); + } + }; + + public static final String[] CATEGORIES = new String[]{ + "SIT", + "SOL", + "OPC", + "OPS" + }; + + public static final String BOX_SIZE = "This is used to calculate combobox sizes."; + + public static boolean DEBUG=true; + + private static boolean propertiesLoaded = false; + + + private static void loadPropertyFile(MessageCenter msg) { + + File file = new File(System.getProperty(USER_HOME) + PROPERTY_FILE); + try { + if (!file.exists()) { + msg.warn("Error loading config properties", new Exception("File " + file + " doesn't exist.")); + System.out.println("File " + file + " doesn't exist."); + System.exit(1); + } + + if (file.exists()) { + System.getProperties().load(new FileInputStream(file)); + propertiesLoaded = true; + System.out.println("Config file " + file + " loaded at: " + new Date()); + } + + if ( System.getProperty("debug") == null) { + DEBUG = false; + } else { + DEBUG = "TRUE".equalsIgnoreCase(System.getProperty("debug").trim()); // init the debug according to config file + } + + test(); + + } catch (IOException e) { + msg.warn("Error loading config properties", e); + } + } + + public static String getProperty(String key, MessageCenter msg) { + if (!propertiesLoaded) + loadPropertyFile(msg); + + String prop = System.getProperty(key); + if ( prop != null) { + if (prop.contains(PROPERTY_COMMENT_CHAR)) { + prop = prop.substring(0, prop.indexOf(PROPERTY_COMMENT_CHAR)); + } + prop = prop.trim(); + } + return prop; + } + + private static void test() { + MessageCenter msg = MessageCenter.getMessageCenter(Constants.class); + System.out.println(getProperty("visual.program.home", msg)); + System.out.println(getProperty("visual.program", msg)); + + } + +} diff --git a/festc_core/src/gov/epa/festc/util/DateFormat.java b/festc_core/src/gov/epa/festc/util/DateFormat.java index bd8955b..3253b30 100644 --- a/festc_core/src/gov/epa/festc/util/DateFormat.java +++ b/festc_core/src/gov/epa/festc/util/DateFormat.java @@ -1,124 +1,124 @@ -package gov.epa.festc.util; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -public class DateFormat { - - public static final String PATTERN_yyyyMMddHHmm = "yyyy/MM/dd HH:mm"; - - public static final String PATTERN_MMddYYYY_HHmm = "MM/dd/yyyy HH:mm"; - - private static SimpleDateFormat dateFormatter = new SimpleDateFormat(); - - - public static String format_YYYY_MM_DD_HH_MM(Date date) { - dateFormatter.applyPattern(PATTERN_yyyyMMddHHmm); - return date == null ? "" : dateFormatter.format(date); - } - - public static String format_YYYYMMDDHHMM(Date date) { - dateFormatter.applyPattern("yyyyMMddHHmm"); - return date == null ? "" : dateFormatter.format(date); - } - - public static String format_MM_DD_YYYY(Date date) { - dateFormatter.applyPattern("MM/dd/yyyy"); - return date == null ? "" : dateFormatter.format(date); - } - - public static String format_MM_DD_YYYY_HH_mm(Date date) { - dateFormatter.applyPattern(PATTERN_MMddYYYY_HHmm); - return date == null ? "" : dateFormatter.format(date); - } - - public static Date parse_MM_DD_YYYY_HH_mm(String date) throws ParseException { - dateFormatter.applyPattern(PATTERN_MMddYYYY_HHmm); - return date == null || date.trim().isEmpty() ? null : dateFormatter.parse(date); - } - - public static String format_YYYY(Date date) { - dateFormatter.applyPattern("yyyy"); - return date == null ? "" : dateFormatter.format(date); - } - - public static Date parse_YYYY(String date) throws ParseException { - dateFormatter.applyPattern("yyyy"); - return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); - } - - public static Date parse_MMddyyyy(String date) throws ParseException { - dateFormatter.applyPattern("MM/dd/yyyy"); - return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); - } - - public static String format_ddMMMyyyy(Date date) { - dateFormatter.applyPattern("ddMMMyyyy"); - return date == null ? "" : dateFormatter.format(date); - } - - public static String format_MM_DD_YYYY_HH_mm_ss(Date date) { - dateFormatter.applyPattern("MM/dd/yyyy HH:mm:ss"); - return date == null ? "" : dateFormatter.format(date); - } - - public static String format_MMDDYYYYHHmmss(Date date) { - dateFormatter.applyPattern("MM-dd-yyyy-HHmmss"); - return date == null ? "" : dateFormatter.format(date); - } - - public static Date parse_YYYY_MM_DD_HH_MM(String date) throws ParseException { - dateFormatter.applyPattern("yyyy/MM/dd HH:mm"); - return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); - } - - public static String format_YYYY_MM_DD_HH_MM_ss_SS(Date date) { - dateFormatter.applyPattern("yyyy/MM/dd HH:mm:ss:SS"); - return date == null ? "" : dateFormatter.format(date); - } - - public static String format_yyyy_MM_dd_HHmmssSS(Date date) { - dateFormatter.applyPattern("yyyy-MM-dd-HH:mm:ss:SS"); - return date == null ? "" : dateFormatter.format(date); - } - - public static Date format_yyyy_MM_dd_HHmmssSS(String date) throws ParseException { - dateFormatter.applyPattern("yyyy-MM-dd-HH:mm:ss:SS"); - return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); -// return date == null ? "" : dateFormatter.format(date); - } - - public static Date format_yyyy_MM_dd_HHmmss(String date) throws ParseException { - dateFormatter.applyPattern("yyyy-MM-dd HH:mm:ss"); - return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); -// return date == null ? "" : dateFormatter.format(date); - } - - public static String format_YYYYMMDDHHMMSS(Date date) { - dateFormatter.applyPattern("yyyyMMddHHmmss"); - return date == null ? "" : dateFormatter.format(date); - } - - - public static String format_YYYYMMDDHHMMSSSS(Date date) { - dateFormatter.applyPattern("yyyyMMddHHmmssSS"); - return date == null ? "" : dateFormatter.format(date); - } - - public static String format_YYDDHHMMSS(Date date) { - dateFormatter.applyPattern("yyddHHmmss"); - return date == null ? "" : dateFormatter.format(date); - } - - public static String format_HHMM(Date date) { - dateFormatter.applyPattern("HHmm"); - return date == null ? "" : dateFormatter.format(date); - } - - public static String format_HHMMSSSS(Date date) { - dateFormatter.applyPattern("HHmmssSS"); - return date == null ? "" : dateFormatter.format(date); - } - -} +package gov.epa.festc.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class DateFormat { + + public static final String PATTERN_yyyyMMddHHmm = "yyyy/MM/dd HH:mm"; + + public static final String PATTERN_MMddYYYY_HHmm = "MM/dd/yyyy HH:mm"; + + private static SimpleDateFormat dateFormatter = new SimpleDateFormat(); + + + public static String format_YYYY_MM_DD_HH_MM(Date date) { + dateFormatter.applyPattern(PATTERN_yyyyMMddHHmm); + return date == null ? "" : dateFormatter.format(date); + } + + public static String format_YYYYMMDDHHMM(Date date) { + dateFormatter.applyPattern("yyyyMMddHHmm"); + return date == null ? "" : dateFormatter.format(date); + } + + public static String format_MM_DD_YYYY(Date date) { + dateFormatter.applyPattern("MM/dd/yyyy"); + return date == null ? "" : dateFormatter.format(date); + } + + public static String format_MM_DD_YYYY_HH_mm(Date date) { + dateFormatter.applyPattern(PATTERN_MMddYYYY_HHmm); + return date == null ? "" : dateFormatter.format(date); + } + + public static Date parse_MM_DD_YYYY_HH_mm(String date) throws ParseException { + dateFormatter.applyPattern(PATTERN_MMddYYYY_HHmm); + return date == null || date.trim().isEmpty() ? null : dateFormatter.parse(date); + } + + public static String format_YYYY(Date date) { + dateFormatter.applyPattern("yyyy"); + return date == null ? "" : dateFormatter.format(date); + } + + public static Date parse_YYYY(String date) throws ParseException { + dateFormatter.applyPattern("yyyy"); + return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); + } + + public static Date parse_MMddyyyy(String date) throws ParseException { + dateFormatter.applyPattern("MM/dd/yyyy"); + return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); + } + + public static String format_ddMMMyyyy(Date date) { + dateFormatter.applyPattern("ddMMMyyyy"); + return date == null ? "" : dateFormatter.format(date); + } + + public static String format_MM_DD_YYYY_HH_mm_ss(Date date) { + dateFormatter.applyPattern("MM/dd/yyyy HH:mm:ss"); + return date == null ? "" : dateFormatter.format(date); + } + + public static String format_MMDDYYYYHHmmss(Date date) { + dateFormatter.applyPattern("MM-dd-yyyy-HHmmss"); + return date == null ? "" : dateFormatter.format(date); + } + + public static Date parse_YYYY_MM_DD_HH_MM(String date) throws ParseException { + dateFormatter.applyPattern("yyyy/MM/dd HH:mm"); + return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); + } + + public static String format_YYYY_MM_DD_HH_MM_ss_SS(Date date) { + dateFormatter.applyPattern("yyyy/MM/dd HH:mm:ss:SS"); + return date == null ? "" : dateFormatter.format(date); + } + + public static String format_yyyy_MM_dd_HHmmssSS(Date date) { + dateFormatter.applyPattern("yyyy-MM-dd-HH:mm:ss:SS"); + return date == null ? "" : dateFormatter.format(date); + } + + public static Date format_yyyy_MM_dd_HHmmssSS(String date) throws ParseException { + dateFormatter.applyPattern("yyyy-MM-dd-HH:mm:ss:SS"); + return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); +// return date == null ? "" : dateFormatter.format(date); + } + + public static Date format_yyyy_MM_dd_HHmmss(String date) throws ParseException { + dateFormatter.applyPattern("yyyy-MM-dd HH:mm:ss"); + return date == null || date.trim().isEmpty()? null : dateFormatter.parse(date); +// return date == null ? "" : dateFormatter.format(date); + } + + public static String format_YYYYMMDDHHMMSS(Date date) { + dateFormatter.applyPattern("yyyyMMddHHmmss"); + return date == null ? "" : dateFormatter.format(date); + } + + + public static String format_YYYYMMDDHHMMSSSS(Date date) { + dateFormatter.applyPattern("yyyyMMddHHmmssSS"); + return date == null ? "" : dateFormatter.format(date); + } + + public static String format_YYDDHHMMSS(Date date) { + dateFormatter.applyPattern("yyddHHmmss"); + return date == null ? "" : dateFormatter.format(date); + } + + public static String format_HHMM(Date date) { + dateFormatter.applyPattern("HHmm"); + return date == null ? "" : dateFormatter.format(date); + } + + public static String format_HHMMSSSS(Date date) { + dateFormatter.applyPattern("HHmmssSS"); + return date == null ? "" : dateFormatter.format(date); + } + +} diff --git a/festc_core/src/gov/epa/festc/util/FileRunner.java b/festc_core/src/gov/epa/festc/util/FileRunner.java index f2c6180..fa365b4 100644 --- a/festc_core/src/gov/epa/festc/util/FileRunner.java +++ b/festc_core/src/gov/epa/festc/util/FileRunner.java @@ -15,10 +15,60 @@ public static void runScript(final String file, final String logText, final Mess String qcmd = Constants.getProperty(Constants.QUEUE_CMD, msg); String qopt = Constants.getProperty(Constants.QUEUE_OPT, msg); //String qname = Constants.getProperty(Constants.QUEUE_NAME, msg); - String qbigmem = Constants.getProperty(Constants.QUEUE_BMEM, msg); +// String qbigmem = Constants.getProperty(Constants.QUEUE_BMEM, msg); String workdir = Constants.getProperty(Constants.WORK_DIR, msg); - boolean useBigMem = false; - if (file.contains("epic2CMAQ_") || file.contains("epic2swat_")) useBigMem = true; + + String qbeld4 = Constants.getProperty(Constants.QUEUE_BELD4_CMD, msg); + String qSiteInfo = Constants.getProperty(Constants.QUEUE_SITE_INFO, msg); + String qMc2Epic = Constants.getProperty(Constants.QUEUE_MC2EPIC, msg); + String qEpicSite = Constants.getProperty(Constants.QUEUE_EPIC_SITE, msg); + String qSoilMatch = Constants.getProperty(Constants.QUEUE_SOIL_MATCH, msg); + String qManSpinup = Constants.getProperty(Constants.QUEUE_MAN_SPINUP, msg); + String qEpicSpinup = Constants.getProperty(Constants.QUEUE_EPIC_SPINUP, msg); + String qManApp = Constants.getProperty(Constants.QUEUE_MAN_APP, msg); + String qEpicApp = Constants.getProperty(Constants.QUEUE_EPIC_APP, msg); + String qYearlyExt = Constants.getProperty(Constants.QUEUE_YEARLY_EXT, msg); + String qEpic2Cmaq = Constants.getProperty(Constants.QUEUE_EPIC2CMAQ, msg); + String qEpic2Swat = Constants.getProperty(Constants.QUEUE_EPIC2SWAT, msg); + String qOption = ""; + +// boolean useBigMem = false; +// if (file.contains("epic2CMAQ_") || file.contains("epic2swat_")) useBigMem = true; + + //choose option based on script file name + if (file.contains("generateBeld4Data")){ + qOption = qbeld4; + } else if (file.contains("generateSiteInfo")){ + qOption = qSiteInfo; + } else if (file.contains("generateEPICsiteDailyWeather")){ + qOption = qMc2Epic; + } else if (file.contains("generateEpicSiteFile")){ + qOption = qEpicSite; + } else if (file.contains("runEpicSoilMatch")){ + qOption = qSoilMatch; + } else if (file.contains("runEpicManSpinup")){ + qOption = qManSpinup; + } else if (file.contains("runEpicSpinup")){ + qOption = qEpicSpinup; + } else if (file.contains("runEPICManApp")){ + qOption = qManApp; + } else if (file.contains("runEpicApp")){ + qOption = qEpicApp; + } else if (file.contains("epicYearlyAverage")){ + qOption = qYearlyExt; + } else if (file.contains("epic2CMAQ")){ + qOption = qEpic2Cmaq; + } else if (file.contains("epic2SWAT")){ + qOption = qEpic2Swat; + } + + // ensure qOption is not null (Constants.getProperty returns null if property is missing) + if (qOption == null){ + qOption = ""; + } + if (qopt == null){ + qopt = ""; + } if (workdir == null || workdir.trim().isEmpty()) workdir = Constants.getProperty(Constants.USER_HOME, msg); @@ -48,12 +98,15 @@ public static void runScript(final String file, final String logText, final Mess // cmd = cmd + " " + qopt; // } - if (useBigMem) - cmd = cmd + " " + qbigmem + " " + qopt + " " + log + " " + script.getAbsolutePath(); - else - cmd = cmd + " " +qopt + " " + log + " " + script.getAbsolutePath(); +// if (useBigMem) +// cmd = cmd + " " + qbigmem + " " + qopt + " " + log + " " + script.getAbsolutePath(); +// else +// cmd = cmd + " " +qopt + " " + log + " " + script.getAbsolutePath(); + + cmd = cmd + " " + qOption + " " + qopt + " -o " + log + " " + script.getAbsolutePath(); - if ((qcmd == null || qcmd.trim().isEmpty()) || (qcmd == null || qcmd.trim().isEmpty())) + //Always use direct submission if spinup or app (for compatibility with job array submission) + if (qcmd == null || qcmd.trim().isEmpty()) cmd = "cd " + scriptDir+ "\n" + script.getAbsolutePath() + " > " + log + " & " ; cmd = cmd + "\ncd - \n"; @@ -133,6 +186,87 @@ public void run() { } } + + public static void runScriptwCmd(final String file, final String logText, final MessageCenter msg, final String cmd) { + + File script = new File(file.replaceAll("\\\\", "\\\\\\\\")); + + if (Constants.DEBUG) { + System.out.println("Command = " + cmd); + msg.info("Command = " + cmd); + } + + ProcessBuilder pb = new ProcessBuilder("cmd", "/C", cmd); + + String osName = System.getProperty("os.name" ); + + if(osName.equals("Linux")) + pb = new ProcessBuilder("csh", "-c", cmd); + + // set up the working directory. + pb.directory(script.getParentFile()); + + // merge child's error and normal output streams. + pb.redirectErrorStream(true); + + Process p = null; + + if (Constants.DEBUG) { + System.out.println("Starting a new process to run the script file..."); + msg.info("Starting a new process to run the script file..."); + } + + try { + p = pb.start(); + final InputStream es = p.getErrorStream(); + final InputStream is = p.getInputStream(); + + // spawn two threads to handle I/O with child while we wait for it + // to complete. + Thread esthread = new Thread(new Runnable() { + public void run() { + readMsg(msg, es, "ERROR"); + } + }); + esthread.start(); + + Thread isthread = new Thread(new Runnable() { + public void run() { + readMsg(msg, is, "INPUT"); + } + }); + isthread.start(); + + + if (Constants.DEBUG) { + System.out.println("Process started: " + p.toString()); + msg.info("Process started: " + p.toString()); + } + + p.waitFor(); + es.close(); + is.close(); + + if (Constants.DEBUG) { + System.out.println("Job submitted."); + msg.info("Job submitted."); + } + + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (IOException e) { + // + } finally { + if (p != null) { + try { + p.getErrorStream().close(); + } catch (IOException e) { + // + } + } + } + } + private static void readMsg(MessageCenter msgcenter, InputStream is, String type) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); diff --git a/festc_core/src/gov/epa/festc/util/FormattedTextFieldDemo.java b/festc_core/src/gov/epa/festc/util/FormattedTextFieldDemo.java index bd55b4e..1a2a030 100644 --- a/festc_core/src/gov/epa/festc/util/FormattedTextFieldDemo.java +++ b/festc_core/src/gov/epa/festc/util/FormattedTextFieldDemo.java @@ -1,193 +1,193 @@ -package gov.epa.festc.util; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.GridLayout; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.text.NumberFormat; - -import javax.swing.BorderFactory; -import javax.swing.JFormattedTextField; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - -/** - * FormattedTextFieldDemo.java requires no other files. - * - * It implements a mortgage calculator that uses four - * JFormattedTextFields. - */ -public class FormattedTextFieldDemo extends JPanel - implements PropertyChangeListener { - /** - * - */ - private static final long serialVersionUID = -4839273043247054365L; - //Values for the fields - private double amount = 100000; - private double rate = 7.5; //7.5% - private int numPeriods = 30; - - //Labels to identify the fields - private JLabel amountLabel; - private JLabel rateLabel; - private JLabel numPeriodsLabel; - private JLabel paymentLabel; - - //Strings for the labels - private static String amountString = "Loan Amount: "; - private static String rateString = "APR (%): "; - private static String numPeriodsString = "Years: "; - private static String paymentString = "Monthly Payment: "; - - //Fields for data entry - private JFormattedTextField amountField; - private JFormattedTextField rateField; - private JFormattedTextField numPeriodsField; - private JFormattedTextField paymentField; - - //Formats to format and parse numbers - private NumberFormat amountFormat; - private NumberFormat percentFormat; - private NumberFormat paymentFormat; - - public FormattedTextFieldDemo() { - super(new BorderLayout()); - setUpFormats(); - double payment = computePayment(amount, - rate, - numPeriods); - - //Create the labels. - amountLabel = new JLabel(amountString); - rateLabel = new JLabel(rateString); - numPeriodsLabel = new JLabel(numPeriodsString); - paymentLabel = new JLabel(paymentString); - - //Create the text fields and set them up. - amountField = new JFormattedTextField(amountFormat); - amountField.setValue(new Double(amount)); - amountField.setColumns(10); - amountField.addPropertyChangeListener("value", this); - - rateField = new JFormattedTextField(percentFormat); - rateField.setValue(new Double(rate)); - rateField.setColumns(10); - rateField.addPropertyChangeListener("value", this); - - numPeriodsField = new JFormattedTextField(); - numPeriodsField.setValue(new Integer(numPeriods)); - numPeriodsField.setColumns(10); - numPeriodsField.addPropertyChangeListener("value", this); - - paymentField = new JFormattedTextField(paymentFormat); - paymentField.setValue(new Double(payment)); - paymentField.setColumns(10); - paymentField.setEditable(false); - paymentField.setForeground(Color.red); - - //Tell accessibility tools about label/textfield pairs. - amountLabel.setLabelFor(amountField); - rateLabel.setLabelFor(rateField); - numPeriodsLabel.setLabelFor(numPeriodsField); - paymentLabel.setLabelFor(paymentField); - - //Lay out the labels in a panel. - JPanel labelPane = new JPanel(new GridLayout(0,1)); - labelPane.add(amountLabel); - labelPane.add(rateLabel); - labelPane.add(numPeriodsLabel); - labelPane.add(paymentLabel); - - //Layout the text fields in a panel. - JPanel fieldPane = new JPanel(new GridLayout(0,1)); - fieldPane.add(amountField); - fieldPane.add(rateField); - fieldPane.add(numPeriodsField); - fieldPane.add(paymentField); - - //Put the panels in this panel, labels on left, - //text fields on right. - setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); - add(labelPane, BorderLayout.CENTER); - add(fieldPane, BorderLayout.LINE_END); - } - - /** Called when a field's "value" property changes. */ - public void propertyChange(PropertyChangeEvent e) { - Object source = e.getSource(); - if (source == amountField) { - amount = ((Number)amountField.getValue()).doubleValue(); - } else if (source == rateField) { - rate = ((Number)rateField.getValue()).doubleValue(); - } else if (source == numPeriodsField) { - numPeriods = ((Number)numPeriodsField.getValue()).intValue(); - } - - double payment = computePayment(amount, rate, numPeriods); - paymentField.setValue(new Double(payment)); - } - - /** - * Create the GUI and show it. For thread safety, - * this method should be invoked from the - * event dispatch thread. - */ - private static void createAndShowGUI() { - //Create and set up the window. - JFrame frame = new JFrame("FormattedTextFieldDemo"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - //Add contents to the window. - frame.add(new FormattedTextFieldDemo()); - - //Display the window. - frame.pack(); - frame.setVisible(true); - } - - public static void main(String[] args) { - //Schedule a job for the event dispatch thread: - //creating and showing this application's GUI. - SwingUtilities.invokeLater(new Runnable() { - public void run() { - //Turn off metal's use of bold fonts - UIManager.put("swing.boldMetal", Boolean.FALSE); - createAndShowGUI(); - } - }); - } - - //Compute the monthly payment based on the loan amount, - //APR, and length of loan. - double computePayment(double loanAmt, double rate, int numPeriods) { - double I, partial1, denominator, answer; - - numPeriods *= 12; //get number of months - if (rate > 0.01) { - I = rate / 100.0 / 12.0; //get monthly rate from annual - partial1 = Math.pow((1 + I), (0.0 - numPeriods)); - denominator = (1 - partial1) / I; - } else { //rate ~= 0 - denominator = numPeriods; - } - - answer = (-1 * loanAmt) / denominator; - return answer; - } - - //Create and set up number formats. These objects also - //parse numbers input by user. - private void setUpFormats() { - amountFormat = NumberFormat.getNumberInstance(); - - percentFormat = NumberFormat.getNumberInstance(); - percentFormat.setMinimumFractionDigits(3); - - paymentFormat = NumberFormat.getCurrencyInstance(); - } -} +package gov.epa.festc.util; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GridLayout; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.text.NumberFormat; + +import javax.swing.BorderFactory; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +/** + * FormattedTextFieldDemo.java requires no other files. + * + * It implements a mortgage calculator that uses four + * JFormattedTextFields. + */ +public class FormattedTextFieldDemo extends JPanel + implements PropertyChangeListener { + /** + * + */ + private static final long serialVersionUID = -4839273043247054365L; + //Values for the fields + private double amount = 100000; + private double rate = 7.5; //7.5% + private int numPeriods = 30; + + //Labels to identify the fields + private JLabel amountLabel; + private JLabel rateLabel; + private JLabel numPeriodsLabel; + private JLabel paymentLabel; + + //Strings for the labels + private static String amountString = "Loan Amount: "; + private static String rateString = "APR (%): "; + private static String numPeriodsString = "Years: "; + private static String paymentString = "Monthly Payment: "; + + //Fields for data entry + private JFormattedTextField amountField; + private JFormattedTextField rateField; + private JFormattedTextField numPeriodsField; + private JFormattedTextField paymentField; + + //Formats to format and parse numbers + private NumberFormat amountFormat; + private NumberFormat percentFormat; + private NumberFormat paymentFormat; + + public FormattedTextFieldDemo() { + super(new BorderLayout()); + setUpFormats(); + double payment = computePayment(amount, + rate, + numPeriods); + + //Create the labels. + amountLabel = new JLabel(amountString); + rateLabel = new JLabel(rateString); + numPeriodsLabel = new JLabel(numPeriodsString); + paymentLabel = new JLabel(paymentString); + + //Create the text fields and set them up. + amountField = new JFormattedTextField(amountFormat); + amountField.setValue(new Double(amount)); + amountField.setColumns(10); + amountField.addPropertyChangeListener("value", this); + + rateField = new JFormattedTextField(percentFormat); + rateField.setValue(new Double(rate)); + rateField.setColumns(10); + rateField.addPropertyChangeListener("value", this); + + numPeriodsField = new JFormattedTextField(); + numPeriodsField.setValue(new Integer(numPeriods)); + numPeriodsField.setColumns(10); + numPeriodsField.addPropertyChangeListener("value", this); + + paymentField = new JFormattedTextField(paymentFormat); + paymentField.setValue(new Double(payment)); + paymentField.setColumns(10); + paymentField.setEditable(false); + paymentField.setForeground(Color.red); + + //Tell accessibility tools about label/textfield pairs. + amountLabel.setLabelFor(amountField); + rateLabel.setLabelFor(rateField); + numPeriodsLabel.setLabelFor(numPeriodsField); + paymentLabel.setLabelFor(paymentField); + + //Lay out the labels in a panel. + JPanel labelPane = new JPanel(new GridLayout(0,1)); + labelPane.add(amountLabel); + labelPane.add(rateLabel); + labelPane.add(numPeriodsLabel); + labelPane.add(paymentLabel); + + //Layout the text fields in a panel. + JPanel fieldPane = new JPanel(new GridLayout(0,1)); + fieldPane.add(amountField); + fieldPane.add(rateField); + fieldPane.add(numPeriodsField); + fieldPane.add(paymentField); + + //Put the panels in this panel, labels on left, + //text fields on right. + setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + add(labelPane, BorderLayout.CENTER); + add(fieldPane, BorderLayout.LINE_END); + } + + /** Called when a field's "value" property changes. */ + public void propertyChange(PropertyChangeEvent e) { + Object source = e.getSource(); + if (source == amountField) { + amount = ((Number)amountField.getValue()).doubleValue(); + } else if (source == rateField) { + rate = ((Number)rateField.getValue()).doubleValue(); + } else if (source == numPeriodsField) { + numPeriods = ((Number)numPeriodsField.getValue()).intValue(); + } + + double payment = computePayment(amount, rate, numPeriods); + paymentField.setValue(new Double(payment)); + } + + /** + * Create the GUI and show it. For thread safety, + * this method should be invoked from the + * event dispatch thread. + */ + private static void createAndShowGUI() { + //Create and set up the window. + JFrame frame = new JFrame("FormattedTextFieldDemo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + //Add contents to the window. + frame.add(new FormattedTextFieldDemo()); + + //Display the window. + frame.pack(); + frame.setVisible(true); + } + + public static void main(String[] args) { + //Schedule a job for the event dispatch thread: + //creating and showing this application's GUI. + SwingUtilities.invokeLater(new Runnable() { + public void run() { + //Turn off metal's use of bold fonts + UIManager.put("swing.boldMetal", Boolean.FALSE); + createAndShowGUI(); + } + }); + } + + //Compute the monthly payment based on the loan amount, + //APR, and length of loan. + double computePayment(double loanAmt, double rate, int numPeriods) { + double I, partial1, denominator, answer; + + numPeriods *= 12; //get number of months + if (rate > 0.01) { + I = rate / 100.0 / 12.0; //get monthly rate from annual + partial1 = Math.pow((1 + I), (0.0 - numPeriods)); + denominator = (1 - partial1) / I; + } else { //rate ~= 0 + denominator = numPeriods; + } + + answer = (-1 * loanAmt) / denominator; + return answer; + } + + //Create and set up number formats. These objects also + //parse numbers input by user. + private void setUpFormats() { + amountFormat = NumberFormat.getNumberInstance(); + + percentFormat = NumberFormat.getNumberInstance(); + percentFormat.setMinimumFractionDigits(3); + + paymentFormat = NumberFormat.getCurrencyInstance(); + } +} diff --git a/festc_core/src/gov/epa/festc/util/Messenger.java b/festc_core/src/gov/epa/festc/util/Messenger.java index 672c660..71251b0 100644 --- a/festc_core/src/gov/epa/festc/util/Messenger.java +++ b/festc_core/src/gov/epa/festc/util/Messenger.java @@ -1,51 +1,51 @@ -package gov.epa.festc.util; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; - -public class Messenger extends Thread { - InputStream is; - String type; - OutputStream os; - - public Messenger(InputStream is, String type) { - this(is, type, null); - } - - public Messenger(InputStream is, String type, OutputStream redirect) { - this.is = is; - this.type = type; - this.os = redirect; - } - - public void run() { - try { - PrintWriter pw = null; - if (os != null) - pw = new PrintWriter(os); - - InputStreamReader isr = new InputStreamReader(is); - BufferedReader br = new BufferedReader(isr); - String line = null; - - while ((line = br.readLine()) != null) { - if (pw != null) - pw.println(line); - System.out.println(type + ">" + line); - } - - br.close(); - - if (pw != null) { - pw.flush(); - pw.close(); - } - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } -} +package gov.epa.festc.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; + +public class Messenger extends Thread { + InputStream is; + String type; + OutputStream os; + + public Messenger(InputStream is, String type) { + this(is, type, null); + } + + public Messenger(InputStream is, String type, OutputStream redirect) { + this.is = is; + this.type = type; + this.os = redirect; + } + + public void run() { + try { + PrintWriter pw = null; + if (os != null) + pw = new PrintWriter(os); + + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line = null; + + while ((line = br.readLine()) != null) { + if (pw != null) + pw.println(line); + System.out.println(type + ">" + line); + } + + br.close(); + + if (pw != null) { + pw.flush(); + pw.close(); + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } +} diff --git a/festc_core/src/gov/epa/festc/util/ModelYearInconsistantException.java b/festc_core/src/gov/epa/festc/util/ModelYearInconsistantException.java index 11a9723..03539a2 100644 --- a/festc_core/src/gov/epa/festc/util/ModelYearInconsistantException.java +++ b/festc_core/src/gov/epa/festc/util/ModelYearInconsistantException.java @@ -1,13 +1,13 @@ -package gov.epa.festc.util; - -public class ModelYearInconsistantException extends Exception { - - /** - * - */ - private static final long serialVersionUID = 4511072740276009475L; - - public ModelYearInconsistantException(String msg) { - super(msg); - } -} +package gov.epa.festc.util; + +public class ModelYearInconsistantException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 4511072740276009475L; + + public ModelYearInconsistantException(String msg) { + super(msg); + } +} diff --git a/festc_core/src/gov/epa/festc/util/SpringLayoutGenerator.java b/festc_core/src/gov/epa/festc/util/SpringLayoutGenerator.java index 218f776..867dea6 100644 --- a/festc_core/src/gov/epa/festc/util/SpringLayoutGenerator.java +++ b/festc_core/src/gov/epa/festc/util/SpringLayoutGenerator.java @@ -1,173 +1,173 @@ -package gov.epa.festc.util; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Container; - -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.Spring; -import javax.swing.SpringLayout; - -/** - * A 1.4 file that provides utility methods for creating form- or grid-style layouts with SpringLayout. These utilities - * are used by several programs, such as SpringBox and SpringCompactGrid. - */ -public class SpringLayoutGenerator { - - /** - * Aligns the first rows * cols components of parent in a grid. Each - * component is as big as the maximum preferred width and height of the components. The parent is made just big - * enough to fit them all. - * - * @param rows - * number of rows - * @param cols - * number of columns - * @param initialX - * x location to start the grid at - * @param initialY - * y location to start the grid at - * @param xPad - * x padding between cells - * @param yPad - * y padding between cells - */ - public void makeGrid(Container parent, int rows, int cols, int initialX, int initialY, int xPad, int yPad) { - SpringLayout layout; - layout = (SpringLayout) parent.getLayout(); - - Spring xPadSpring = Spring.constant(xPad); - Spring yPadSpring = Spring.constant(yPad); - Spring initialXSpring = Spring.constant(initialX); - Spring initialYSpring = Spring.constant(initialY); - int max = rows * cols; - - // Calculate Springs that are the max of the width/height so that all - // cells have the same size. - Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)).getWidth(); - Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)).getWidth(); - for (int i = 1; i < max; i++) { - SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); - - maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth()); - maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight()); - } - - // Apply the new width/height Spring. This forces all the - // components to have the same size. - for (int i = 0; i < max; i++) { - SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); - - cons.setWidth(maxWidthSpring); - cons.setHeight(maxHeightSpring); - } - - // Then adjust the x/y constraints of all the cells so that they - // are aligned in a grid. - SpringLayout.Constraints lastCons = null; - SpringLayout.Constraints lastRowCons = null; - for (int i = 0; i < max; i++) { - SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); - if (i % cols == 0) { // start of new row - lastRowCons = lastCons; - cons.setX(initialXSpring); - } else { // x position depends on previous component - cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST), xPadSpring)); - } - - if (i / cols == 0) { // first row - cons.setY(initialYSpring); - } else { // y position depends on previous row - cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH), yPadSpring)); - } - lastCons = cons; - } - - // Set the parent's size. - SpringLayout.Constraints pCons = layout.getConstraints(parent); - pCons.setConstraint(SpringLayout.SOUTH, Spring.sum(Spring.constant(yPad), lastCons - .getConstraint(SpringLayout.SOUTH))); - pCons.setConstraint(SpringLayout.EAST, Spring.sum(Spring.constant(xPad), lastCons - .getConstraint(SpringLayout.EAST))); - } - - /* Used by makeCompactGrid. */ - private SpringLayout.Constraints getConstraintsForCell(int row, int col, Container parent, int cols) { - SpringLayout layout = (SpringLayout) parent.getLayout(); - Component c = parent.getComponent(row * cols + col); - return layout.getConstraints(c); - } - - /** - * Aligns the first rows * cols components of parent in a grid. Each - * component in a column is as wide as the maximum preferred width of the components in that column; height is - * similarly determined for each row. The parent is made just big enough to fit them all. - * - * @param rows - * number of rows - * @param cols - * number of columns - * @param initialX - * x location to start the grid at - * @param initialY - * y location to start the grid at - * @param xPad - * x padding between cells - * @param yPad - * y padding between cells - */ - public void makeCompactGrid(Container parent, int rows, int cols, int initialX, int initialY, int xPad, int yPad) { - SpringLayout layout; - layout = (SpringLayout) parent.getLayout(); - - // Align all cells in each column and make them the same width. - Spring x = Spring.constant(initialX); - for (int c = 0; c < cols; c++) { - Spring width = Spring.constant(0); - for (int r = 0; r < rows; r++) { - width = Spring.max(width, getConstraintsForCell(r, c, parent, cols).getWidth()); - } - for (int r = 0; r < rows; r++) { - SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); - constraints.setX(x); - constraints.setWidth(width); - } - x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad))); - } - - // Align all cells in each row and make them the same height. - Spring y = Spring.constant(initialY); - for (int r = 0; r < rows; r++) { - Spring height = Spring.constant(0); - for (int c = 0; c < cols; c++) { - height = Spring.max(height, getConstraintsForCell(r, c, parent, cols).getHeight()); - } - for (int c = 0; c < cols; c++) { - SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); - constraints.setY(y); - constraints.setHeight(height); - } - y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad))); - } - - // Set the parent's size. - SpringLayout.Constraints pCons = layout.getConstraints(parent); - pCons.setConstraint(SpringLayout.SOUTH, y); - pCons.setConstraint(SpringLayout.EAST, x); - } - - public void addLabelWidgetPair(String label, JComponent widget, JPanel panel) { - addWidgetPair(new JLabel(label), widget, panel); - } - - public void addWidgetPair(JComponent widget1, JComponent widget2, JPanel panel) { - panel.add(widget1); - - JPanel widgetPanel = new JPanel(new BorderLayout()); - widgetPanel.add(widget2, BorderLayout.LINE_START); - panel.add(widgetPanel); - } - -} +package gov.epa.festc.util; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.Spring; +import javax.swing.SpringLayout; + +/** + * A 1.4 file that provides utility methods for creating form- or grid-style layouts with SpringLayout. These utilities + * are used by several programs, such as SpringBox and SpringCompactGrid. + */ +public class SpringLayoutGenerator { + + /** + * Aligns the first rows * cols components of parent in a grid. Each + * component is as big as the maximum preferred width and height of the components. The parent is made just big + * enough to fit them all. + * + * @param rows + * number of rows + * @param cols + * number of columns + * @param initialX + * x location to start the grid at + * @param initialY + * y location to start the grid at + * @param xPad + * x padding between cells + * @param yPad + * y padding between cells + */ + public void makeGrid(Container parent, int rows, int cols, int initialX, int initialY, int xPad, int yPad) { + SpringLayout layout; + layout = (SpringLayout) parent.getLayout(); + + Spring xPadSpring = Spring.constant(xPad); + Spring yPadSpring = Spring.constant(yPad); + Spring initialXSpring = Spring.constant(initialX); + Spring initialYSpring = Spring.constant(initialY); + int max = rows * cols; + + // Calculate Springs that are the max of the width/height so that all + // cells have the same size. + Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)).getWidth(); + Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)).getWidth(); + for (int i = 1; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); + + maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth()); + maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight()); + } + + // Apply the new width/height Spring. This forces all the + // components to have the same size. + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); + + cons.setWidth(maxWidthSpring); + cons.setHeight(maxHeightSpring); + } + + // Then adjust the x/y constraints of all the cells so that they + // are aligned in a grid. + SpringLayout.Constraints lastCons = null; + SpringLayout.Constraints lastRowCons = null; + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints(parent.getComponent(i)); + if (i % cols == 0) { // start of new row + lastRowCons = lastCons; + cons.setX(initialXSpring); + } else { // x position depends on previous component + cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST), xPadSpring)); + } + + if (i / cols == 0) { // first row + cons.setY(initialYSpring); + } else { // y position depends on previous row + cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH), yPadSpring)); + } + lastCons = cons; + } + + // Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, Spring.sum(Spring.constant(yPad), lastCons + .getConstraint(SpringLayout.SOUTH))); + pCons.setConstraint(SpringLayout.EAST, Spring.sum(Spring.constant(xPad), lastCons + .getConstraint(SpringLayout.EAST))); + } + + /* Used by makeCompactGrid. */ + private SpringLayout.Constraints getConstraintsForCell(int row, int col, Container parent, int cols) { + SpringLayout layout = (SpringLayout) parent.getLayout(); + Component c = parent.getComponent(row * cols + col); + return layout.getConstraints(c); + } + + /** + * Aligns the first rows * cols components of parent in a grid. Each + * component in a column is as wide as the maximum preferred width of the components in that column; height is + * similarly determined for each row. The parent is made just big enough to fit them all. + * + * @param rows + * number of rows + * @param cols + * number of columns + * @param initialX + * x location to start the grid at + * @param initialY + * y location to start the grid at + * @param xPad + * x padding between cells + * @param yPad + * y padding between cells + */ + public void makeCompactGrid(Container parent, int rows, int cols, int initialX, int initialY, int xPad, int yPad) { + SpringLayout layout; + layout = (SpringLayout) parent.getLayout(); + + // Align all cells in each column and make them the same width. + Spring x = Spring.constant(initialX); + for (int c = 0; c < cols; c++) { + Spring width = Spring.constant(0); + for (int r = 0; r < rows; r++) { + width = Spring.max(width, getConstraintsForCell(r, c, parent, cols).getWidth()); + } + for (int r = 0; r < rows; r++) { + SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); + constraints.setX(x); + constraints.setWidth(width); + } + x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad))); + } + + // Align all cells in each row and make them the same height. + Spring y = Spring.constant(initialY); + for (int r = 0; r < rows; r++) { + Spring height = Spring.constant(0); + for (int c = 0; c < cols; c++) { + height = Spring.max(height, getConstraintsForCell(r, c, parent, cols).getHeight()); + } + for (int c = 0; c < cols; c++) { + SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); + constraints.setY(y); + constraints.setHeight(height); + } + y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad))); + } + + // Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, y); + pCons.setConstraint(SpringLayout.EAST, x); + } + + public void addLabelWidgetPair(String label, JComponent widget, JPanel panel) { + addWidgetPair(new JLabel(label), widget, panel); + } + + public void addWidgetPair(JComponent widget1, JComponent widget2, JPanel panel) { + panel.add(widget1); + + JPanel widgetPanel = new JPanel(new BorderLayout()); + widgetPanel.add(widget2, BorderLayout.LINE_START); + panel.add(widgetPanel); + } + +} diff --git a/festc_dist/.classpath b/festc_dist/.classpath index e9bcd51..ac37fb2 100644 --- a/festc_dist/.classpath +++ b/festc_dist/.classpath @@ -1,5 +1,5 @@ - - - - - + + + + + diff --git a/festc_dist/.project b/festc_dist/.project index 2f166aa..ed78eae 100644 --- a/festc_dist/.project +++ b/festc_dist/.project @@ -1,17 +1,17 @@ - - - festc_dist - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - + + + festc_dist + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/festc_dist/build.properties b/festc_dist/build.properties index 13bb0e6..b8beba5 100644 --- a/festc_dist/build.properties +++ b/festc_dist/build.properties @@ -1,17 +1,19 @@ -######## -# Please copy it as build.properties (in the same folder as this file), -# and change the properties as needed - -# Properties for specify a local distribution directory - -# app -app.name=festc -app.version=1.3 - - -# basic settings - use '/' as a separator -#jre.home=/home/dyang/application/jdk1.7.0_07/jre -#jre.home=/home/dyang/application/jdk1.7.0_45/jre -jre.home=/home/dyang/application/jdk1.7.0_40/jre -build.home=/home/dyang +######## +# Please copy it as build.properties (in the same folder as this file), +# and change the properties as needed + +# Properties for specify a local distribution directory + +# app +app.name=festc +app.version=1.4 + + +# basic settings - use '/' as a separator +#jre.home=/home/dyang/application/jdk1.7.0_07/jre +#jre.home=/home/dyang/application/jdk1.7.0_45/jre +#jre.home=/home/dyang/application/jdk1.7.0_40/jre +jre.home=C:/Program Files/Java/jdk1.8.0_144/jre +#build.home=/home/dyang +build.home=C:/Users/csimmo02/FESTC_jars/build install.dir=festc_install \ No newline at end of file diff --git a/festc_dist/build2.properties b/festc_dist/build2.properties new file mode 100644 index 0000000..2400478 --- /dev/null +++ b/festc_dist/build2.properties @@ -0,0 +1,17 @@ +######## +# Please copy it as build.properties (in the same folder as this file), +# and change the properties as needed + +# Properties for specify a local distribution directory + +# app +app.name=festc +app.version=1.3 + + +# basic settings - use '/' as a separator +#jre.home=/home/dyang/application/jdk1.7.0_07/jre +#jre.home=/home/dyang/application/jdk1.7.0_45/jre +jre.home=/home/dyang/application/jdk1.7.0_40/jre +build.home=/home/dyang +install.dir=festc_install \ No newline at end of file diff --git a/festc_dist/build_32bit.properties b/festc_dist/build_32bit.properties index 6d52862..b66d920 100644 --- a/festc_dist/build_32bit.properties +++ b/festc_dist/build_32bit.properties @@ -1,17 +1,17 @@ -######## -# Please copy it as build.properties (in the same folder as this file), -# and change the properties as needed - -# Properties for specify a local distribution directory - -# app -app.name=festc -app.version=2.0 - - -# basic settings - use '/' as a separator -#jre.home=/Users/dyang/Applications/jdk1.8.0_91_64bits/jre -jre.home=/Users/dyang/Applications/jdk1.8.0_91_32bits/jre -#jre.home=/Users/dyang/Downloads/jdk1.7.0_51/jre -build.home=/Users/dyang +######## +# Please copy it as build.properties (in the same folder as this file), +# and change the properties as needed + +# Properties for specify a local distribution directory + +# app +app.name=festc +app.version=2.0 + + +# basic settings - use '/' as a separator +#jre.home=/Users/dyang/Applications/jdk1.8.0_91_64bits/jre +jre.home=/Users/dyang/Applications/jdk1.8.0_91_32bits/jre +#jre.home=/Users/dyang/Downloads/jdk1.7.0_51/jre +build.home=/Users/dyang install.dir=festc_install_32bits \ No newline at end of file diff --git a/festc_dist/build_64bit.properties b/festc_dist/build_64bit.properties index 319e08d..22bdb14 100644 --- a/festc_dist/build_64bit.properties +++ b/festc_dist/build_64bit.properties @@ -1,17 +1,17 @@ -######## -# Please copy it as build.properties (in the same folder as this file), -# and change the properties as needed - -# Properties for specify a local distribution directory - -# app -app.name=festc -app.version=1.4 - - -# basic settings - use '/' as a separator -jre.home=/Users/dyang/Applications/jdk1.8.0_91_64bits/jre -#jre.home=/Users/dyang/Applications/jdk1.8.0_91_32bits/jre -#jre.home=/Users/dyang/Downloads/jdk1.7.0_51/jre -build.home=/Users/dyang +######## +# Please copy it as build.properties (in the same folder as this file), +# and change the properties as needed + +# Properties for specify a local distribution directory + +# app +app.name=festc +app.version=1.4 + + +# basic settings - use '/' as a separator +jre.home=/Users/dyang/Applications/jdk1.8.0_91_64bits/jre +#jre.home=/Users/dyang/Applications/jdk1.8.0_91_32bits/jre +#jre.home=/Users/dyang/Downloads/jdk1.7.0_51/jre +build.home=/Users/dyang install.dir=festc_install_64bits \ No newline at end of file diff --git a/festc_dist/build_dist.xml b/festc_dist/build_dist.xml index cc75d96..c63d82f 100644 --- a/festc_dist/build_dist.xml +++ b/festc_dist/build_dist.xml @@ -1,206 +1,223 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/festc_dist/build_dist_32bit.xml b/festc_dist/build_dist_32bit.xml index 6b1ae55..680aaf6 100644 --- a/festc_dist/build_dist_32bit.xml +++ b/festc_dist/build_dist_32bit.xml @@ -1,209 +1,209 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/festc_dist/build_dist_64bit.xml b/festc_dist/build_dist_64bit.xml index 8384b58..41f4ccc 100644 --- a/festc_dist/build_dist_64bit.xml +++ b/festc_dist/build_dist_64bit.xml @@ -1,209 +1,209 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/festc_dist/distfiles/Functions.nsh b/festc_dist/distfiles/Functions.nsh index 00abe39..62a4584 100644 --- a/festc_dist/distfiles/Functions.nsh +++ b/festc_dist/distfiles/Functions.nsh @@ -1,254 +1,254 @@ -!ifndef OTHER_MACROS_NSH -!define OTHER_MACROS_NSH - -; From http://nsis.sourceforge.net/wiki/A_slightly_better_Java_Launcher -; Find JRE (javaw.exe) -; 1 - in .\jre directory (JRE Installed with application) -; 2 - in JAVA_HOME environment variable -; 3 - in the registry -; 4 - assume javaw.exe in current dir or PATH -; Stores the JRE on the top of the stack -Function GetJRE - Push $R0 - Push $R1 - - ClearErrors - StrCpy $R0 "$EXEDIR\jre\bin\javaw.exe" - IfFileExists $R0 JreFound - StrCpy $R0 "" - - ClearErrors - ReadEnvStr $R0 "JAVA_HOME" - StrCpy $R0 "$R0\bin\javaw.exe" - IfErrors 0 JreFound - - ClearErrors - ReadRegStr $R1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion" - ReadRegStr $R0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$R1" "JavaHome" - StrCpy $R0 "$R0\bin\javaw.exe" - - IfErrors 0 JreFound - StrCpy $R0 "javaw.exe" - - JreFound: - Pop $R1 - Exch $R0 -FunctionEnd - - - ; GetParameters - ; input, none - ; output, top of stack (replaces, with e.g. whatever) - ; modifies no other variables. - -Function GetParameters - - Push $R0 - Push $R1 - Push $R2 - Push $R3 - - StrCpy $R2 1 - StrLen $R3 $CMDLINE - - ;Check for quote or space - StrCpy $R0 $CMDLINE $R2 - StrCmp $R0 '"' 0 +3 - StrCpy $R1 '"' - Goto loop - StrCpy $R1 " " - - loop: - IntOp $R2 $R2 + 1 - StrCpy $R0 $CMDLINE 1 $R2 - StrCmp $R0 $R1 get - StrCmp $R2 $R3 get - Goto loop - - get: - IntOp $R2 $R2 + 1 - StrCpy $R0 $CMDLINE 1 $R2 - StrCmp $R0 " " get - StrCpy $R0 $CMDLINE "" $R2 - - Pop $R3 - Pop $R2 - Pop $R1 - Exch $R0 - -FunctionEnd - -; -- written by Alexis de Valence -- -; GetONEParameter - -; Usage: -; Push 3 ; to get the 3rd parameter of the command line -; Call GetONEParameter -; Pop $R0 ; saves the result in $R0 -; returns an empty string if not found - -Function GetONEParameter - Exch $R0 - Push $R1 - Push $R2 - Push $R3 - Push $R4 - Push $R5 - Push $R6 - -; init variables - IntOp $R5 $R0 + 1 - StrCpy $R2 0 - StrCpy $R4 1 - StrCpy $R6 0 - - loop3: ; looking for a char that's not a space - IntOp $R2 $R2 + 1 - StrCpy $R0 $CMDLINE 1 $R2 - StrCmp $R0 " " loop3 - StrCpy $R3 $R2 ; found the begining of the current parameter - - - loop: ; scanning for the end of the current parameter - - StrCpy $R0 $CMDLINE 1 $R2 - StrCmp $R0 " " loop2 - StrCmp $R0 "" last - IntOp $R2 $R2 + 1 - Goto loop - - last: ; there will be no other parameter to extract - StrCpy $R6 1 - - loop2: ; found the end of the current parameter - - IntCmp $R4 $R5 0 NextParam end - StrCpy $R6 1 ; to quit after this process - - IntOp $R1 $R2 - $R3 ;number of letter of current parameter - StrCpy $R0 $CMDLINE $R1 $R3 ; stores the result in R0 - - NextParam: - IntCmp $R6 1 end ; leave if found or if not enough parameters - - ; process the next parameter - IntOp $R4 $R4 + 1 - - Goto loop3 - - end: - - Pop $R6 ; restore R0 - R6 to their initial value - Pop $R5 - Pop $R4 - Pop $R3 - Pop $R2 - Pop $R1 - - Exch $R0 ;Puts the result on the stack - - FunctionEnd - - -; GetParameterValue -; Chris Morgan 5/10/2004 -; Searches the command line input, retrieved using GetParameters, for the -; value of an option given the option name. If no option is found the -; default value is placed on the top of the stack upon function return -; -; Inputs - Top of stack is default if parameter isn't found, -; second in stack is parameter to search for, ex. "OUTPUT" -; Outputs - Top of the stack contains the value of this parameter -; So if the command line contained /OUTPUT=somedirectory, "somedirectory" -; will be on the top of the stack when this function returns -; -; Register usage -;$R0 - default return value if the parameter isn't found -;$R1 - input parameter, for example OUTPUT from the above example -;$R2 - the length of the search, this is the search parameter+2 -; as we have '/OUTPUT=' -;$R3 - the command line string -;$R4 - result from StrStr's -;$R5 - search for ' ' or '"' - -Function GetParameterValue - Exch $R0 ; get the default parameter into R1 - Exch ; exchange the top two - Exch $R1 ; get the search parameter into $R0 - - ;Preserve on the stack the registers we will use in this function - Push $R2 - Push $R3 - Push $R4 - Push $R5 - - Strlen $R2 $R1+1 ; store the length of the search string into R2 - - Call GetParameters ;get the command line parameters - Pop $R3 ; store the command line string in R3 - # search for quoted search string - StrCpy $R5 '"' ; later on we want to search for a open quote - Push $R3 ; push the 'search in' string onto the stack - Push '$R1="' ; push the 'search for' - Call StrStr - Pop $R4 - StrCpy $R4 $R4 "" # skip quote - StrCmp $R4 "" "" next - # search for non-quoted search string - StrCpy $R5 ' ' ; later on we want to search for a space - Push $R3 ; push the command line back on the stack for searching - Push '$R1=' ; search for the non-quoted search string - Call StrStr - Pop $R4 -next: - StrCmp $R4 "" done ; if we didn't find anything then we are done - # copy the value after /$R1= - StrCpy $R0 $R4 "" $R2 ; copy commandline text beyond parameter into $R0 - # search for the next parameter so we can trim this extra text off - Push $R0 - Push $R5 - Call StrStr ; search for the next parameter - Pop $R4 - StrCmp $R4 "" done - StrLen $R4 $R4 - StrCpy $R0 $R0 -$R4 ; using the length of the string beyond the value, - ;copy only the value into $R0 -done: - Pop $R5 - Pop $R4 - Pop $R3 - Pop $R2 - Pop $R1 - Exch $R0 ; put the value in $R0 at the top of the stack -FunctionEnd - -Function StrStr - Exch $R1 ; st=haystack,old$R1, $R1=needle - Exch ; st=old$R1,haystack - Exch $R2 ; st=old$R1,old$R2, $R2=haystack - Push $R3 - Push $R4 - Push $R5 - StrLen $R3 $R1 - StrCpy $R4 0 - ; $R1=needle - ; $R2=haystack - ; $R3=len(needle) - ; $R4=cnt - ; $R5=tmp - loop: - StrCpy $R5 $R2 $R3 $R4 - StrCmp $R5 $R1 done - StrCmp $R5 "" done - IntOp $R4 $R4 + 1 - Goto loop - done: - StrCpy $R1 $R2 "" $R4 - Pop $R5 - Pop $R4 - Pop $R3 - Pop $R2 - Exch $R1 -FunctionEnd - -!endif +!ifndef OTHER_MACROS_NSH +!define OTHER_MACROS_NSH + +; From http://nsis.sourceforge.net/wiki/A_slightly_better_Java_Launcher +; Find JRE (javaw.exe) +; 1 - in .\jre directory (JRE Installed with application) +; 2 - in JAVA_HOME environment variable +; 3 - in the registry +; 4 - assume javaw.exe in current dir or PATH +; Stores the JRE on the top of the stack +Function GetJRE + Push $R0 + Push $R1 + + ClearErrors + StrCpy $R0 "$EXEDIR\jre\bin\javaw.exe" + IfFileExists $R0 JreFound + StrCpy $R0 "" + + ClearErrors + ReadEnvStr $R0 "JAVA_HOME" + StrCpy $R0 "$R0\bin\javaw.exe" + IfErrors 0 JreFound + + ClearErrors + ReadRegStr $R1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion" + ReadRegStr $R0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$R1" "JavaHome" + StrCpy $R0 "$R0\bin\javaw.exe" + + IfErrors 0 JreFound + StrCpy $R0 "javaw.exe" + + JreFound: + Pop $R1 + Exch $R0 +FunctionEnd + + + ; GetParameters + ; input, none + ; output, top of stack (replaces, with e.g. whatever) + ; modifies no other variables. + +Function GetParameters + + Push $R0 + Push $R1 + Push $R2 + Push $R3 + + StrCpy $R2 1 + StrLen $R3 $CMDLINE + + ;Check for quote or space + StrCpy $R0 $CMDLINE $R2 + StrCmp $R0 '"' 0 +3 + StrCpy $R1 '"' + Goto loop + StrCpy $R1 " " + + loop: + IntOp $R2 $R2 + 1 + StrCpy $R0 $CMDLINE 1 $R2 + StrCmp $R0 $R1 get + StrCmp $R2 $R3 get + Goto loop + + get: + IntOp $R2 $R2 + 1 + StrCpy $R0 $CMDLINE 1 $R2 + StrCmp $R0 " " get + StrCpy $R0 $CMDLINE "" $R2 + + Pop $R3 + Pop $R2 + Pop $R1 + Exch $R0 + +FunctionEnd + +; -- written by Alexis de Valence -- +; GetONEParameter + +; Usage: +; Push 3 ; to get the 3rd parameter of the command line +; Call GetONEParameter +; Pop $R0 ; saves the result in $R0 +; returns an empty string if not found + +Function GetONEParameter + Exch $R0 + Push $R1 + Push $R2 + Push $R3 + Push $R4 + Push $R5 + Push $R6 + +; init variables + IntOp $R5 $R0 + 1 + StrCpy $R2 0 + StrCpy $R4 1 + StrCpy $R6 0 + + loop3: ; looking for a char that's not a space + IntOp $R2 $R2 + 1 + StrCpy $R0 $CMDLINE 1 $R2 + StrCmp $R0 " " loop3 + StrCpy $R3 $R2 ; found the begining of the current parameter + + + loop: ; scanning for the end of the current parameter + + StrCpy $R0 $CMDLINE 1 $R2 + StrCmp $R0 " " loop2 + StrCmp $R0 "" last + IntOp $R2 $R2 + 1 + Goto loop + + last: ; there will be no other parameter to extract + StrCpy $R6 1 + + loop2: ; found the end of the current parameter + + IntCmp $R4 $R5 0 NextParam end + StrCpy $R6 1 ; to quit after this process + + IntOp $R1 $R2 - $R3 ;number of letter of current parameter + StrCpy $R0 $CMDLINE $R1 $R3 ; stores the result in R0 + + NextParam: + IntCmp $R6 1 end ; leave if found or if not enough parameters + + ; process the next parameter + IntOp $R4 $R4 + 1 + + Goto loop3 + + end: + + Pop $R6 ; restore R0 - R6 to their initial value + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Pop $R1 + + Exch $R0 ;Puts the result on the stack + + FunctionEnd + + +; GetParameterValue +; Chris Morgan 5/10/2004 +; Searches the command line input, retrieved using GetParameters, for the +; value of an option given the option name. If no option is found the +; default value is placed on the top of the stack upon function return +; +; Inputs - Top of stack is default if parameter isn't found, +; second in stack is parameter to search for, ex. "OUTPUT" +; Outputs - Top of the stack contains the value of this parameter +; So if the command line contained /OUTPUT=somedirectory, "somedirectory" +; will be on the top of the stack when this function returns +; +; Register usage +;$R0 - default return value if the parameter isn't found +;$R1 - input parameter, for example OUTPUT from the above example +;$R2 - the length of the search, this is the search parameter+2 +; as we have '/OUTPUT=' +;$R3 - the command line string +;$R4 - result from StrStr's +;$R5 - search for ' ' or '"' + +Function GetParameterValue + Exch $R0 ; get the default parameter into R1 + Exch ; exchange the top two + Exch $R1 ; get the search parameter into $R0 + + ;Preserve on the stack the registers we will use in this function + Push $R2 + Push $R3 + Push $R4 + Push $R5 + + Strlen $R2 $R1+1 ; store the length of the search string into R2 + + Call GetParameters ;get the command line parameters + Pop $R3 ; store the command line string in R3 + # search for quoted search string + StrCpy $R5 '"' ; later on we want to search for a open quote + Push $R3 ; push the 'search in' string onto the stack + Push '$R1="' ; push the 'search for' + Call StrStr + Pop $R4 + StrCpy $R4 $R4 "" # skip quote + StrCmp $R4 "" "" next + # search for non-quoted search string + StrCpy $R5 ' ' ; later on we want to search for a space + Push $R3 ; push the command line back on the stack for searching + Push '$R1=' ; search for the non-quoted search string + Call StrStr + Pop $R4 +next: + StrCmp $R4 "" done ; if we didn't find anything then we are done + # copy the value after /$R1= + StrCpy $R0 $R4 "" $R2 ; copy commandline text beyond parameter into $R0 + # search for the next parameter so we can trim this extra text off + Push $R0 + Push $R5 + Call StrStr ; search for the next parameter + Pop $R4 + StrCmp $R4 "" done + StrLen $R4 $R4 + StrCpy $R0 $R0 -$R4 ; using the length of the string beyond the value, + ;copy only the value into $R0 +done: + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Pop $R1 + Exch $R0 ; put the value in $R0 at the top of the stack +FunctionEnd + +Function StrStr + Exch $R1 ; st=haystack,old$R1, $R1=needle + Exch ; st=old$R1,haystack + Exch $R2 ; st=old$R1,old$R2, $R2=haystack + Push $R3 + Push $R4 + Push $R5 + StrLen $R3 $R1 + StrCpy $R4 0 + ; $R1=needle + ; $R2=haystack + ; $R3=len(needle) + ; $R4=cnt + ; $R5=tmp + loop: + StrCpy $R5 $R2 $R3 $R4 + StrCmp $R5 $R1 done + StrCmp $R5 "" done + IntOp $R4 $R4 + 1 + Goto loop + done: + StrCpy $R1 $R2 "" $R4 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Exch $R1 +FunctionEnd + +!endif diff --git a/festc_dist/distfiles/config.properties b/festc_dist/distfiles/config.properties index 219928d..52fe06f 100644 --- a/festc_dist/distfiles/config.properties +++ b/festc_dist/distfiles/config.properties @@ -1,13 +1,13 @@ -# This file should be put in $USER_HOME/festc/ subdirectory -# Linux example settings - -work.dir=/nas01/depts/ie/cempd/EPIC/epic -sa.home=/nas01/depts/ie/cempd/SA/sa_06_2009 -epic.home=/nas01/depts/ie/cempd/EPIC/epic -visual.program.home=/usr/local/ -visual.program=verdi -f -queue.cmd=bsub -queue.option=-q week -oo -queue.bigmem=-R mem96 -M 40 -debug=true -allow.diff.check=true +# This file should be put in $USER_HOME/festc/ subdirectory +# Linux example settings + +work.dir=/nas01/depts/ie/cempd/EPIC/epic +sa.home=/nas01/depts/ie/cempd/SA/sa_06_2009 +epic.home=/nas01/depts/ie/cempd/EPIC/epic +visual.program.home=/usr/local/ +visual.program=verdi -f +queue.cmd=bsub +queue.option=-q week -oo +queue.bigmem=-R mem96 -M 40 +debug=true +allow.diff.check=true diff --git a/festc_dist/distfiles/festc b/festc_dist/distfiles/festc old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/festc.ini b/festc_dist/distfiles/festc.ini index 126c3ba..b431eee 100644 --- a/festc_dist/distfiles/festc.ini +++ b/festc_dist/distfiles/festc.ini @@ -1,2 +1,2 @@ -[boot] -heapSize=1024M +[boot] +heapSize=1024M diff --git a/festc_dist/distfiles/festc.nsi b/festc_dist/distfiles/festc.nsi index ab47caa..8265023 100644 --- a/festc_dist/distfiles/festc.nsi +++ b/festc_dist/distfiles/festc.nsi @@ -1,202 +1,202 @@ -;-------------------------------- -; RepastSimphony.nsi -; -; This script builds the Repast Simphony installer/uninstaller -; Created by Jerry Vos, Nick Collier -; Adapted to FEST-C by IE, UNC -; Last modified Oct 29, 2009 -;-------------------------------- - -;-------------------------------- -; Header Files -!include "MUI.nsh" - - -;-------------------------------- -; Variables - -; Start menu dir var -Var "ICONS_GROUP" - - -;-------------------------------------------- -; File macros -!define FILE_IGNORE_STRING "/x CVS /x .svn /x *.nsh /x *.res /x *.obj /x obj /x *.pch /x *.pdb /x debug /x *.ilk /x .cvsignore /x *.nsi /x distfiles /x distlib /x build_dist.xml /x config.properties" -!define File "File ${FILE_IGNORE_STRING} " -!define FileR "File /r ${FILE_IGNORE_STRING} " - - -;-------------------------------- -; MUI Settings -!define MUI_ABORTWARNING -!define MUI_COMPONENTSPAGE_SMALLDESC - -; if this is defined as a picture, it will be the picture that shows up on the header of the installer -;!define MUI_HEADERIMAGE - -; Other settings -!define PRODUCT_NAME "FESTC" -!define PRODUCT_VERSION "1.0" -!define PRODUCT_PUBLISHER "US EPA" -;!define PRODUCT_WEB_SITE "http://www.epa.gov" -!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\FESTC" -!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" -!define PRODUCT_UNINST_ROOT_KEY "HKLM" -!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir" -!define USERHOME "$STARTMENU\..\festc" -!define licensefile "licenses\festc_gpl-3.0.txt" - - -;-------------------------------- -; Custom defines - -; This is the file that launches the main class. This is created through RepastSimphonyLauncher.nsi -!define RS_LAUNCHER "FESTC.exe" -; This is the location of the root of the sources. This is used to find what files to copy. -!define SRCROOT ".\" - - -;-------------------------------- -; Setup the installer info - -; The name of the installer -Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" - - -; This is the installer executable file's name -; File name has underscores only because sourceforge doesn't like spaces, can get rid of them if you don't want them -OutFile "${PRODUCT_NAME}_${PRODUCT_VERSION}_Installer.exe" - -; The default installation directory -InstallDir "$PROGRAMFILES\${PRODUCT_NAME}_${PRODUCT_VERSION}" - - -; Registry key to check for directory (so if you install again, it will -; overwrite the old one automatically) -InstallDirRegKey HKLM "Software\${PRODUCT_NAME}" "Install_Dir" - -ShowInstDetails show -ShowUnInstDetails show - - -;-------------------------------- -; Installer pages - -!insertmacro MUI_PAGE_WELCOME - -; License page -!ifdef licensefile -LicenseText "FEST-C License" -LicenseData "${SRCROOT}\${licensefile}" -Page license -!endif -; End of license page - -;!insertmacro MUI_PAGE_COMPONENTS - -; Install directory selector -!define MUI_DIRECTORYPAGE_TEXT_TOP "Please select the directory to install ${PRODUCT_NAME}." -!define MUI_DIRECTORYPAGE_VARIABLE $INSTDIR -!insertmacro MUI_PAGE_DIRECTORY - -; Start menu directory selector -!define MUI_STARTMENUPAGE_NODISABLE -!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${PRODUCT_NAME}" -!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}" -!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}" -!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}" - -!insertmacro MUI_PAGE_STARTMENU "StartMenuPageID" $ICONS_GROUP - -; Install -!insertmacro MUI_PAGE_INSTFILES - -!insertmacro MUI_LANGUAGE "English" - -;-------------------------------- -; Uninstaller pages - -!insertmacro MUI_UNPAGE_INSTFILES - - - - -;-------------------------------- -; Install sections - -Section "All" SecAll - SectionIn 1 - - ; Copy default festc properties file - CreateDirectory "${USERHOME}" - SetOutPath "${USERHOME}" - File "${SRCROOT}\config.properties" - - ; BEGIN FILE LISTING - ; Just copy everything - SetOutPath "$INSTDIR" - ${FileR} "${SRCROOT}\*" - - ; the RS launcher - ${File} "${RS_LAUNCHER}" - ; END FILE LISTING - - CreateDirectory "$SMPROGRAMS\$ICONS_GROUP\" - CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\${PRODUCT_NAME}.lnk" "$INSTDIR\${RS_LAUNCHER}" -SectionEnd - - -Section -Post - WriteUninstaller "$INSTDIR\Uninstall.exe" - - WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" - WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" - WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" - ;WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" - WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" -SectionEnd - - -Section -AdditionalIcons - !insertmacro MUI_STARTMENU_WRITE_BEGIN "StartMenuPageID" - CreateDirectory "$SMPROGRAMS\$ICONS_GROUP\" - !ifdef PRODUCT_WEB_SITE - WriteIniStr "$SMPROGRAMS\$ICONS_GROUP\${PRODUCT_NAME} Website.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}" - !endif - CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninstall.exe" - !insertmacro MUI_STARTMENU_WRITE_END -SectionEnd - - -;-------------------------------- -; Uninstall sections -Section Uninstall - - !insertmacro MUI_STARTMENU_GETFOLDER "StartMenuPageID" $ICONS_GROUP - - Delete "$INSTDIR\uninstall.exe" - - RMDir /r "$SMPROGRAMS\$ICONS_GROUP" - - RMDir /r "$INSTDIR" - - DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" -; SetAutoClose true -SectionEnd - - -;-------------------------------- -; Functions - -;Function Initialize -; StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCT_NAME}" -;FunctionEnd - -Function un.onUninstSuccess - MessageBox MB_ICONINFORMATION|MB_OK "${PRODUCT_NAME} was successfully removed from your computer." -FunctionEnd - -Function un.onInit - MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove ${PRODUCT_NAME} and all of its components?" IDYES +2 - Abort -FunctionEnd +;-------------------------------- +; RepastSimphony.nsi +; +; This script builds the Repast Simphony installer/uninstaller +; Created by Jerry Vos, Nick Collier +; Adapted to FEST-C by IE, UNC +; Last modified Oct 29, 2009 +;-------------------------------- + +;-------------------------------- +; Header Files +!include "MUI.nsh" + + +;-------------------------------- +; Variables + +; Start menu dir var +Var "ICONS_GROUP" + + +;-------------------------------------------- +; File macros +!define FILE_IGNORE_STRING "/x CVS /x .svn /x *.nsh /x *.res /x *.obj /x obj /x *.pch /x *.pdb /x debug /x *.ilk /x .cvsignore /x *.nsi /x distfiles /x distlib /x build_dist.xml /x config.properties" +!define File "File ${FILE_IGNORE_STRING} " +!define FileR "File /r ${FILE_IGNORE_STRING} " + + +;-------------------------------- +; MUI Settings +!define MUI_ABORTWARNING +!define MUI_COMPONENTSPAGE_SMALLDESC + +; if this is defined as a picture, it will be the picture that shows up on the header of the installer +;!define MUI_HEADERIMAGE + +; Other settings +!define PRODUCT_NAME "FESTC" +!define PRODUCT_VERSION "1.0" +!define PRODUCT_PUBLISHER "US EPA" +;!define PRODUCT_WEB_SITE "http://www.epa.gov" +!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\FESTC" +!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" +!define PRODUCT_UNINST_ROOT_KEY "HKLM" +!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir" +!define USERHOME "$STARTMENU\..\festc" +!define licensefile "licenses\festc_gpl-3.0.txt" + + +;-------------------------------- +; Custom defines + +; This is the file that launches the main class. This is created through RepastSimphonyLauncher.nsi +!define RS_LAUNCHER "FESTC.exe" +; This is the location of the root of the sources. This is used to find what files to copy. +!define SRCROOT ".\" + + +;-------------------------------- +; Setup the installer info + +; The name of the installer +Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" + + +; This is the installer executable file's name +; File name has underscores only because sourceforge doesn't like spaces, can get rid of them if you don't want them +OutFile "${PRODUCT_NAME}_${PRODUCT_VERSION}_Installer.exe" + +; The default installation directory +InstallDir "$PROGRAMFILES\${PRODUCT_NAME}_${PRODUCT_VERSION}" + + +; Registry key to check for directory (so if you install again, it will +; overwrite the old one automatically) +InstallDirRegKey HKLM "Software\${PRODUCT_NAME}" "Install_Dir" + +ShowInstDetails show +ShowUnInstDetails show + + +;-------------------------------- +; Installer pages + +!insertmacro MUI_PAGE_WELCOME + +; License page +!ifdef licensefile +LicenseText "FEST-C License" +LicenseData "${SRCROOT}\${licensefile}" +Page license +!endif +; End of license page + +;!insertmacro MUI_PAGE_COMPONENTS + +; Install directory selector +!define MUI_DIRECTORYPAGE_TEXT_TOP "Please select the directory to install ${PRODUCT_NAME}." +!define MUI_DIRECTORYPAGE_VARIABLE $INSTDIR +!insertmacro MUI_PAGE_DIRECTORY + +; Start menu directory selector +!define MUI_STARTMENUPAGE_NODISABLE +!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${PRODUCT_NAME}" +!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}" +!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}" +!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}" + +!insertmacro MUI_PAGE_STARTMENU "StartMenuPageID" $ICONS_GROUP + +; Install +!insertmacro MUI_PAGE_INSTFILES + +!insertmacro MUI_LANGUAGE "English" + +;-------------------------------- +; Uninstaller pages + +!insertmacro MUI_UNPAGE_INSTFILES + + + + +;-------------------------------- +; Install sections + +Section "All" SecAll + SectionIn 1 + + ; Copy default festc properties file + CreateDirectory "${USERHOME}" + SetOutPath "${USERHOME}" + File "${SRCROOT}\config.properties" + + ; BEGIN FILE LISTING + ; Just copy everything + SetOutPath "$INSTDIR" + ${FileR} "${SRCROOT}\*" + + ; the RS launcher + ${File} "${RS_LAUNCHER}" + ; END FILE LISTING + + CreateDirectory "$SMPROGRAMS\$ICONS_GROUP\" + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\${PRODUCT_NAME}.lnk" "$INSTDIR\${RS_LAUNCHER}" +SectionEnd + + +Section -Post + WriteUninstaller "$INSTDIR\Uninstall.exe" + + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" + ;WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" +SectionEnd + + +Section -AdditionalIcons + !insertmacro MUI_STARTMENU_WRITE_BEGIN "StartMenuPageID" + CreateDirectory "$SMPROGRAMS\$ICONS_GROUP\" + !ifdef PRODUCT_WEB_SITE + WriteIniStr "$SMPROGRAMS\$ICONS_GROUP\${PRODUCT_NAME} Website.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}" + !endif + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninstall.exe" + !insertmacro MUI_STARTMENU_WRITE_END +SectionEnd + + +;-------------------------------- +; Uninstall sections +Section Uninstall + + !insertmacro MUI_STARTMENU_GETFOLDER "StartMenuPageID" $ICONS_GROUP + + Delete "$INSTDIR\uninstall.exe" + + RMDir /r "$SMPROGRAMS\$ICONS_GROUP" + + RMDir /r "$INSTDIR" + + DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" +; SetAutoClose true +SectionEnd + + +;-------------------------------- +; Functions + +;Function Initialize +; StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCT_NAME}" +;FunctionEnd + +Function un.onUninstSuccess + MessageBox MB_ICONINFORMATION|MB_OK "${PRODUCT_NAME} was successfully removed from your computer." +FunctionEnd + +Function un.onInit + MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove ${PRODUCT_NAME} and all of its components?" IDYES +2 + Abort +FunctionEnd diff --git a/festc_dist/distfiles/festc.sh b/festc_dist/distfiles/festc.sh old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/ControlPanel b/festc_dist/distfiles/jre1.6.0_13_linux/bin/ControlPanel old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/java b/festc_dist/distfiles/jre1.6.0_13_linux/bin/java old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/java_vm b/festc_dist/distfiles/jre1.6.0_13_linux/bin/java_vm old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/javaws b/festc_dist/distfiles/jre1.6.0_13_linux/bin/javaws old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/jcontrol b/festc_dist/distfiles/jre1.6.0_13_linux/bin/jcontrol old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/keytool b/festc_dist/distfiles/jre1.6.0_13_linux/bin/keytool old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/orbd b/festc_dist/distfiles/jre1.6.0_13_linux/bin/orbd old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/pack200 b/festc_dist/distfiles/jre1.6.0_13_linux/bin/pack200 old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/policytool b/festc_dist/distfiles/jre1.6.0_13_linux/bin/policytool old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/rmid b/festc_dist/distfiles/jre1.6.0_13_linux/bin/rmid old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/rmiregistry b/festc_dist/distfiles/jre1.6.0_13_linux/bin/rmiregistry old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/servertool b/festc_dist/distfiles/jre1.6.0_13_linux/bin/servertool old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/tnameserv b/festc_dist/distfiles/jre1.6.0_13_linux/bin/tnameserv old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/bin/unpack200 b/festc_dist/distfiles/jre1.6.0_13_linux/bin/unpack200 old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/javaws/javaws b/festc_dist/distfiles/jre1.6.0_13_linux/javaws/javaws old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/deploy/messages_zh_HK.properties b/festc_dist/distfiles/jre1.6.0_13_linux/lib/deploy/messages_zh_HK.properties old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/deploy/splash.gif b/festc_dist/distfiles/jre1.6.0_13_linux/lib/deploy/splash.gif old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/desktop/mime/packages/x-java-archive.xml b/festc_dist/distfiles/jre1.6.0_13_linux/lib/desktop/mime/packages/x-java-archive.xml old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/desktop/mime/packages/x-java-jnlp-file.xml b/festc_dist/distfiles/jre1.6.0_13_linux/lib/desktop/mime/packages/x-java-jnlp-file.xml old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/client/libjsig.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/client/libjsig.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/client/libjvm.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/client/libjvm.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/headless/libmawt.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/headless/libmawt.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/jli/libjli.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/jli/libjli.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libJdbcOdbc.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libJdbcOdbc.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libawt.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libawt.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libcmm.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libcmm.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libdcpr.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libdcpr.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libdeploy.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libdeploy.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libdt_socket.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libdt_socket.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libfontmanager.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libfontmanager.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libhprof.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libhprof.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libinstrument.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libinstrument.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libioser12.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libioser12.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj2gss.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj2gss.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj2pcsc.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj2pcsc.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj2pkcs11.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj2pkcs11.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj3dcore-ogl-cg.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj3dcore-ogl-cg.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj3dcore-ogl.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libj3dcore-ogl.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjaas_unix.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjaas_unix.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjava.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjava.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjava_crw_demo.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjava_crw_demo.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjavaplugin_jni.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjavaplugin_jni.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjavaplugin_nscp.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjavaplugin_nscp.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjavaplugin_nscp_gcc29.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjavaplugin_nscp_gcc29.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjawt.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjawt.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjdwp.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjdwp.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjpeg.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjpeg.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjsig.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjsig.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjsound.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjsound.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjsoundalsa.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libjsoundalsa.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libmanagement.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libmanagement.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libmlib_image.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libmlib_image.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libnet.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libnet.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libnio.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libnio.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libnpjp2.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libnpjp2.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libnpt.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libnpt.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/librmi.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/librmi.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libsplashscreen.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libsplashscreen.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libunpack.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libunpack.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libverify.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libverify.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libzip.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/libzip.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/motif21/libmawt.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/motif21/libmawt.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/native_threads/libhpi.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/native_threads/libhpi.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/server/libjsig.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/server/libjsig.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/server/libjvm.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/server/libjvm.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/xawt/libmawt.so b/festc_dist/distfiles/jre1.6.0_13_linux/lib/i386/xawt/libmawt.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/lib/jexec b/festc_dist/distfiles/jre1.6.0_13_linux/lib/jexec old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/plugin/i386/ns7-gcc29/libjavaplugin_oji.so b/festc_dist/distfiles/jre1.6.0_13_linux/plugin/i386/ns7-gcc29/libjavaplugin_oji.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/jre1.6.0_13_linux/plugin/i386/ns7/libjavaplugin_oji.so b/festc_dist/distfiles/jre1.6.0_13_linux/plugin/i386/ns7/libjavaplugin_oji.so old mode 100755 new mode 100644 diff --git a/festc_dist/distfiles/launcher.nsi b/festc_dist/distfiles/launcher.nsi index d5e37d4..7b78b57 100644 --- a/festc_dist/distfiles/launcher.nsi +++ b/festc_dist/distfiles/launcher.nsi @@ -1,36 +1,36 @@ -!include "Functions.nsh" - -Name "Festc.exe" -OutFile "FESTC.exe" - -Caption "FEST-C" - -SilentInstall silent -AutoCloseWindow true -ShowInstDetails nevershow - -!define CLASSPATH "./bootstrap.jar;./lib/saf.core.runtime.jar;./lib/commons-logging.jar;./lib/jpf-boot.jar;./lib/jpf.jar;./lib/log4j-1.2.13.jar" -!define MAIN_CLASS "saf.core.runtime.Boot" - -Section "" - #Call GetJRE - #Pop $R0 - - StrCmp $R1 "" 0 +2 - StrCpy $R1 "${MAIN_CLASS}" - - ReadINIStr $1 .\festc.ini boot heapSize - - StrCpy $0 '"..\..\jre1.6.0\bin\javaw" -Xmx$1 -classpath "${CLASSPATH}" $R1' - - ;MessageBox MB_OK $0 - - ClearErrors - SetOutPath ".\plugins\bootstrap" - - ExecWait $0 - - IfErrors 0 done - MessageBox MB_OK "Could not find the java run time" - done: -SectionEnd +!include "Functions.nsh" + +Name "Festc.exe" +OutFile "FESTC.exe" + +Caption "FEST-C" + +SilentInstall silent +AutoCloseWindow true +ShowInstDetails nevershow + +!define CLASSPATH "./bootstrap.jar;./lib/saf.core.runtime.jar;./lib/commons-logging.jar;./lib/jpf-boot.jar;./lib/jpf.jar;./lib/log4j-1.2.13.jar" +!define MAIN_CLASS "saf.core.runtime.Boot" + +Section "" + #Call GetJRE + #Pop $R0 + + StrCmp $R1 "" 0 +2 + StrCpy $R1 "${MAIN_CLASS}" + + ReadINIStr $1 .\festc.ini boot heapSize + + StrCpy $0 '"..\..\jre1.6.0\bin\javaw" -Xmx$1 -classpath "${CLASSPATH}" $R1' + + ;MessageBox MB_OK $0 + + ClearErrors + SetOutPath ".\plugins\bootstrap" + + ExecWait $0 + + IfErrors 0 done + MessageBox MB_OK "Could not find the java run time" + done: +SectionEnd diff --git a/festc_saf_core_runtime_temp/.classpath b/festc_saf_core_runtime_temp/.classpath index 7efab8f..1fa99f0 100644 --- a/festc_saf_core_runtime_temp/.classpath +++ b/festc_saf_core_runtime_temp/.classpath @@ -1,13 +1,13 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/festc_saf_core_runtime_temp/.project b/festc_saf_core_runtime_temp/.project index 9a179d4..61e5f42 100644 --- a/festc_saf_core_runtime_temp/.project +++ b/festc_saf_core_runtime_temp/.project @@ -1,17 +1,17 @@ - - - festc_saf_core_runtime_temp - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - + + + festc_saf_core_runtime_temp + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/festc_saf_core_runtime_temp/.settings/org.eclipse.jdt.core.prefs b/festc_saf_core_runtime_temp/.settings/org.eclipse.jdt.core.prefs index bb35fa0..3a21537 100644 --- a/festc_saf_core_runtime_temp/.settings/org.eclipse.jdt.core.prefs +++ b/festc_saf_core_runtime_temp/.settings/org.eclipse.jdt.core.prefs @@ -1,11 +1,11 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/festc_saf_core_runtime_temp/boot.properties b/festc_saf_core_runtime_temp/boot.properties index 2c620cc..d522239 100644 --- a/festc_saf_core_runtime_temp/boot.properties +++ b/festc_saf_core_runtime_temp/boot.properties @@ -1,18 +1,18 @@ -# Comma separated list of folders with plug-ins -# (plug-in repositories) -pluginFolders = ../,./lib,../festc_bootstrap -org.java.plugin.standard.PluginLifecycleHandler = gov.epa.festc.boot.FestcLifecycleHandler - -log4j.rootLogger=warn, console, R -log4j.logger.org.java = warn - -log4j.appender.console = org.apache.log4j.ConsoleAppender -log4j.appender.console.layout = org.apache.log4j.PatternLayout -log4j.appender.console.layout.conversionPattern = %d [%t] %-5p %c %m%n - -log4j.appender.R=org.apache.log4j.RollingFileAppender -log4j.appender.R.File=${user.home}/festc/festc.log -log4j.appender.R.MaxFileSize=100KB -log4j.appender.R.MaxBackupIndex=1 -log4j.appender.R.layout=org.apache.log4j.PatternLayout -log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p %c %m%n +# Comma separated list of folders with plug-ins +# (plug-in repositories) +pluginFolders = ../,./lib,../festc_bootstrap +org.java.plugin.standard.PluginLifecycleHandler = gov.epa.festc.boot.FestcLifecycleHandler + +log4j.rootLogger=warn, console, R +log4j.logger.org.java = warn + +log4j.appender.console = org.apache.log4j.ConsoleAppender +log4j.appender.console.layout = org.apache.log4j.PatternLayout +log4j.appender.console.layout.conversionPattern = %d [%t] %-5p %c %m%n + +log4j.appender.R=org.apache.log4j.RollingFileAppender +log4j.appender.R.File=${user.home}/festc/festc.log +log4j.appender.R.MaxFileSize=100KB +log4j.appender.R.MaxBackupIndex=1 +log4j.appender.R.layout=org.apache.log4j.PatternLayout +log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p %c %m%n diff --git a/festc_saf_core_runtime_temp/lib/log4j-1.2-api-2.22.1.jar b/festc_saf_core_runtime_temp/lib/log4j-1.2-api-2.22.1.jar new file mode 100644 index 0000000..de57f34 Binary files /dev/null and b/festc_saf_core_runtime_temp/lib/log4j-1.2-api-2.22.1.jar differ diff --git a/festc_saf_core_runtime_temp/lib/log4j-api-2.22.1.jar b/festc_saf_core_runtime_temp/lib/log4j-api-2.22.1.jar new file mode 100644 index 0000000..b77e55e Binary files /dev/null and b/festc_saf_core_runtime_temp/lib/log4j-api-2.22.1.jar differ diff --git a/festc_saf_core_runtime_temp/lib/log4j-core-2.22.1.jar b/festc_saf_core_runtime_temp/lib/log4j-core-2.22.1.jar new file mode 100644 index 0000000..0be3f1f Binary files /dev/null and b/festc_saf_core_runtime_temp/lib/log4j-core-2.22.1.jar differ diff --git a/festc_saf_core_runtime_temp/plugin.xml b/festc_saf_core_runtime_temp/plugin.xml index b746bc6..c104af9 100644 --- a/festc_saf_core_runtime_temp/plugin.xml +++ b/festc_saf_core_runtime_temp/plugin.xml @@ -1,57 +1,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/festc_saf_core_runtime_temp/src/saf/core/runtime/Boot.java b/festc_saf_core_runtime_temp/src/saf/core/runtime/Boot.java index 182e2aa..3cbf111 100644 --- a/festc_saf_core_runtime_temp/src/saf/core/runtime/Boot.java +++ b/festc_saf_core_runtime_temp/src/saf/core/runtime/Boot.java @@ -1,337 +1,337 @@ -package saf.core.runtime; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.StringTokenizer; - -import javax.xml.parsers.ParserConfigurationException; - -import org.java.plugin.JpfException; -import org.java.plugin.ObjectFactory; -import org.java.plugin.Plugin; -import org.java.plugin.PluginLifecycleException; -import org.java.plugin.PluginManager; -import org.java.plugin.PluginManager.PluginLocation; -import org.java.plugin.boot.DefaultPluginsCollector; -import org.java.plugin.registry.Identity; -import org.java.plugin.registry.IntegrityCheckReport; -import org.java.plugin.registry.PluginDescriptor; -import org.java.plugin.util.ExtendedProperties; -import org.xml.sax.SAXException; - -import simphony.util.messages.MessageCenter; - -/** - * Boots the plugin infrastructure. - * - * @author Nick Collier - * @version $Revision: 1.11 $ $Date: 2006/06/01 16:31:11 $ - */ -public class Boot { - - private static final String PLUGIN_FOLDER_PROP = "pluginFolders"; - private static final String PLUGIN_DESCRIPTOR_PROP = "plugin.descriptors"; - private static String RUNTIME_DIR_ROOT = "../festc_bootstrap"; - private static String PLUGIN_RESTRICT_PREFIX = "plugin.restrict."; - - private static final String CORE_PLUGIN_ID = "saf.core.runtime"; - private MessageCenter center = MessageCenter.getMessageCenter(Boot.class); - - public Boot() - { - // 2014 created default constructor - } - - public PluginManager init(String[] args) { - - // load properties - if (args.length > 1) - { - // RUNTIME_DIR_ROOT = args[1]; - } - System.setProperty("applicationRoot", RUNTIME_DIR_ROOT); - center = MessageCenter.getMessageCenter(Boot.class); - try { - Properties props = new Properties(); - File file = new File(RUNTIME_DIR_ROOT, "boot.properties"); - InputStream strm; - //System.out.println("file: " + file.exists() +System.getProperty("user.dir")); - if (file.exists()) { - strm = new FileInputStream(file); - } else { - // try as resource - strm = getClass().getClassLoader().getResourceAsStream("boot.properties"); - //System.out.println("file: " + strm); - } - try { - props.load(strm); - } finally { - strm.close(); - } - - // Publish current folder as configuration parameter - // to get it available as ${applicationRoot} variable - // when extended properties are supported - // 2014 NOTE: the following 2 lines appear to do the same thing - props.put("applicationRoot", new File(".").getCanonicalPath()); - // props.put("applicationRoot", RUNTIME_DIR_ROOT); - - return initializePluginManager(findPluginLocations(props), props); - - } catch (Exception ex) { - center.error(ex.getMessage(), ex); - } - return null; - } - - private void run(PluginManager pluginManager, String[] args) { - Plugin corePlugin; - try { - -// Plugin corePlugin = pluginManager.getPlugin(CORE_PLUGIN_ID); // 2014 NOTE: Javadoc for this function states "Note that this method will never return null." -// if (corePlugin == null) { -// throw new Exception("Cannot find core plugin");} - pluginManager.activatePlugin(CORE_PLUGIN_ID); - corePlugin = pluginManager.getPlugin(CORE_PLUGIN_ID); - } - catch (PluginLifecycleException pEx) - { - center.error(pEx.getMessage(), pEx); - return; - } - catch (IllegalArgumentException iaEx) - { - center.error(iaEx.getMessage(), iaEx); - return; - } - catch (Exception ex) - { - center.error(ex.getMessage(), ex); - return; - } - try{ - -// corePlugin.getClass().getMethod("run", String[].class).invoke(corePlugin, (Object) args); - // 2014 breaking up above statement; 1st get name of class at run-time for predetermined instantiated object - Class pClass = corePlugin.getClass(); -// Method[] someMethods = pClass.getDeclaredMethods(); -// System.out.println("Now try to list the methods"); -// for (Method aMethod : someMethods) -// { -// String methodName = aMethod.getName(); -// System.out.println("method name = " + methodName + " and its parameter types:"); -// Type[] someTypes = aMethod.getGenericParameterTypes(); -// for (Type aType : someTypes) -// { -// String myTypeString = aType.toString(); -// System.out.println("\t" + myTypeString); -// } -// } - // 2nd get name of method at run-time that belongs to class - Method aMethod = pClass.getMethod((String) "run", String[].class); - // 3rd invoke actual method of that class on an object - aMethod.invoke(corePlugin, new java.lang.Object[] {args}); - - } catch (InvocationTargetException itEx) - { - System.out.println("caught an InvocationTargetException in Boot.run; printing .getCause()"); - center.error(itEx.getCause(), itEx); - } - catch (Exception ex) { - System.out.println("Caught an Exception in Boot.java"); - center.error(ex.getMessage(), ex); - } - } - - private PluginManager initializePluginManager(Collection locations, Properties props) - throws JpfException, IOException, ParserConfigurationException, SAXException { - -// PluginManager pluginManager = ObjectFactory.newInstance(new ExtendedProperties(props)).createManager(); -// ObjectFactory fac = ObjectFactory.newInstance(new ExtendedProperties(props)); -// PluginManager pluginManager = fac.createManager(); - ExtendedProperties extProperties = new ExtendedProperties(props); // 2014 - ObjectFactory objFactory = ObjectFactory.newInstance(extProperties); - PluginManager pluginManager = objFactory.createManager(); - - List validLocations = new ArrayList(); - - List restrictions = new ArrayList(); - for (Object key : props.keySet()) { - if (key.toString().startsWith(PLUGIN_RESTRICT_PREFIX)) { - String strKey = key.toString(); - String restrictId = strKey.substring(strKey.lastIndexOf(".") + 1, strKey.length()); - String restrictVal = props.getProperty(strKey); - restrictions.add(new Restriction(restrictId, restrictVal)); - } - } - - if (restrictions.size() > 0) { - for (Iterator iter = locations.iterator(); iter.hasNext();) - { - PluginLocation location = (PluginLocation) iter.next(); - PluginReader reader = new PluginReader(location.getManifestLocation()); - PluginAttributes pluginAttribs = reader.parse(); - - boolean pass = true; - for (Restriction restriction : restrictions) { - if (!restriction.pass(pluginAttribs)) { - pass = false; - break; - } - } - - if (pass) { - validLocations.add(location); - } - } - - } else { -// validLocations.addAll(locations); // 2014 CHANGE TO ITERATE locations & ADD ONLY THOSE NOT ALREADY IN validLocations - for (Iterator anIterator = locations.iterator(); anIterator.hasNext();) - { - PluginLocation aLocation = (PluginLocation)anIterator.next(); - if(!validLocations.contains(aLocation) ) - { - // that location not already in validLocations, so add it - validLocations.add(aLocation); - } - } - } -PluginLocation[] myLocations = validLocations.toArray(new PluginManager.PluginLocation[validLocations.size()]); -//for(int i=0; i map = pluginManager.publishPlugins(myLocations); -// Map map = pluginManager.publishPlugins((PluginManager.PluginLocation[]) validLocations //.toArray()); -// .toArray(new PluginManager.PluginLocation[validLocations.size()])); // 2014 - // Check plug-in's integrity - IntegrityCheckReport integrityCheckReport = pluginManager.getRegistry().checkIntegrity( - pluginManager.getPathResolver(), true); -// if (integrityCheckReport.countErrors() > 0) { // 2014 had been != 0 -// // something wrong with the plugin set -// center.fatal(integrityCheckReport2str(integrityCheckReport), new RuntimeException("Invalid plugin configuration")); -// System.exit(1); -// } - - for (Iterator iter = map.values().iterator(); iter.hasNext();) { - Identity id = (Identity) iter.next(); - PluginDescriptor desc = pluginManager.getRegistry().getPluginDescriptor(id.getId()); - pluginManager.getPluginClassLoader(desc); - } - return pluginManager; - } - - private String integrityCheckReport2str(IntegrityCheckReport report) { - StringBuffer buf = new StringBuffer(); - - for (Iterator it = report.getItems().iterator(); it.hasNext();) { - IntegrityCheckReport.ReportItem item = (IntegrityCheckReport.ReportItem) it.next(); -// if (item.getSeverity() != IntegrityCheckReport.Severity.ERROR) //ReportItem.SEVERITY_ERROR) { -// { -// continue; -// } -// buf.append(item.getMessage()); -// buf.append("\n\n\n"); - } - - buf.append("full integrity check report:\r\n"); - buf.append("-------------- REPORT BEGIN -----------------\r\n"); - for (Iterator it = report.getItems().iterator(); it.hasNext();) { - IntegrityCheckReport.ReportItem item = (IntegrityCheckReport.ReportItem) it.next(); - buf.append("\tseverity=").append(item.getSeverity()).append("; code=").append(item.getCode()) - .append("; message=").append(item.getMessage()).append("; source=") - .append(item.getSource()).append("\r\n"); - } - buf.append("-------------- REPORT END -----------------"); - return buf.toString(); - } - - private Collection findPluginLocations(Properties props) throws Exception { - DefaultPluginsCollector collector = new DefaultPluginsCollector(); - ExtendedProperties eprops = new ExtendedProperties(props); - - if (props.containsKey(PLUGIN_DESCRIPTOR_PROP)) { - // treat is as the jpf xml file that holds plugin locations - eprops.put("org.java.plugin.boot.pluginsLocationsDescriptors", - props.getProperty(PLUGIN_DESCRIPTOR_PROP)); - } else { - String pluginFolder = RUNTIME_DIR_ROOT + props.getProperty(PLUGIN_FOLDER_PROP); - eprops.put("org.java.plugin.boot.pluginsRepositories", pluginFolder); - } - collector.configure(eprops); - Collection locations = collector.collectPluginLocations(); - - String exclude = props.getProperty("pluginFolders.exclude", ""); - StringTokenizer tok = new StringTokenizer(exclude, ","); - List urls = new ArrayList(); - while (tok.hasMoreTokens()) { - String loc = tok.nextToken().trim(); - try { - URL url = new File(loc).getCanonicalFile().toURI().toURL(); - urls.add(url); - } catch (IOException ex) { - center.warn("Error finding directory to exclude from plugin search", ex); - } - } - - if (urls.size() > 0) { - for (Iterator iter = locations.iterator(); iter.hasNext();) { - PluginManager.PluginLocation loc = (PluginManager.PluginLocation) iter.next(); - for (URL url : urls) { - if (loc.getContextLocation().toExternalForm().startsWith(url.toExternalForm())) - iter.remove(); - } - } - } - - return locations; - } - - public static void main(String[] args) { - Boot boot = new Boot(); - - PluginManager manager = boot.init(args); - if(manager == null) - { - System.out.println(" boot.init returned null. Ending with exit(1)"); - System.exit(1); - } - boot.run(manager, args); - } - - private static class Restriction { - - private String id; - private String val; - - private Restriction(String id, String val) { - this.id = id; - this.val = val; - } - - private boolean pass(PluginAttributes pAttribs) { - - SimpleAttribute attrib = pAttribs.getAttribute(id); - if (attrib == null) - return false; - - return attrib.getValue().equals(val); - } - } -} +package saf.core.runtime; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.StringTokenizer; + +import javax.xml.parsers.ParserConfigurationException; + +import org.java.plugin.JpfException; +import org.java.plugin.ObjectFactory; +import org.java.plugin.Plugin; +import org.java.plugin.PluginLifecycleException; +import org.java.plugin.PluginManager; +import org.java.plugin.PluginManager.PluginLocation; +import org.java.plugin.boot.DefaultPluginsCollector; +import org.java.plugin.registry.Identity; +import org.java.plugin.registry.IntegrityCheckReport; +import org.java.plugin.registry.PluginDescriptor; +import org.java.plugin.util.ExtendedProperties; +import org.xml.sax.SAXException; + +import simphony.util.messages.MessageCenter; + +/** + * Boots the plugin infrastructure. + * + * @author Nick Collier + * @version $Revision: 1.11 $ $Date: 2006/06/01 16:31:11 $ + */ +public class Boot { + + private static final String PLUGIN_FOLDER_PROP = "pluginFolders"; + private static final String PLUGIN_DESCRIPTOR_PROP = "plugin.descriptors"; + private static String RUNTIME_DIR_ROOT = "../festc_bootstrap"; + private static String PLUGIN_RESTRICT_PREFIX = "plugin.restrict."; + + private static final String CORE_PLUGIN_ID = "saf.core.runtime"; + private MessageCenter center = MessageCenter.getMessageCenter(Boot.class); + + public Boot() + { + // 2014 created default constructor + } + + public PluginManager init(String[] args) { + + // load properties + if (args.length > 1) + { + // RUNTIME_DIR_ROOT = args[1]; + } + System.setProperty("applicationRoot", RUNTIME_DIR_ROOT); + center = MessageCenter.getMessageCenter(Boot.class); + try { + Properties props = new Properties(); + File file = new File(RUNTIME_DIR_ROOT, "boot.properties"); + InputStream strm; + //System.out.println("file: " + file.exists() +System.getProperty("user.dir")); + if (file.exists()) { + strm = new FileInputStream(file); + } else { + // try as resource + strm = getClass().getClassLoader().getResourceAsStream("boot.properties"); + //System.out.println("file: " + strm); + } + try { + props.load(strm); + } finally { + strm.close(); + } + + // Publish current folder as configuration parameter + // to get it available as ${applicationRoot} variable + // when extended properties are supported + // 2014 NOTE: the following 2 lines appear to do the same thing + props.put("applicationRoot", new File(".").getCanonicalPath()); + // props.put("applicationRoot", RUNTIME_DIR_ROOT); + + return initializePluginManager(findPluginLocations(props), props); + + } catch (Exception ex) { + center.error(ex.getMessage(), ex); + } + return null; + } + + private void run(PluginManager pluginManager, String[] args) { + Plugin corePlugin; + try { + +// Plugin corePlugin = pluginManager.getPlugin(CORE_PLUGIN_ID); // 2014 NOTE: Javadoc for this function states "Note that this method will never return null." +// if (corePlugin == null) { +// throw new Exception("Cannot find core plugin");} + pluginManager.activatePlugin(CORE_PLUGIN_ID); + corePlugin = pluginManager.getPlugin(CORE_PLUGIN_ID); + } + catch (PluginLifecycleException pEx) + { + center.error(pEx.getMessage(), pEx); + return; + } + catch (IllegalArgumentException iaEx) + { + center.error(iaEx.getMessage(), iaEx); + return; + } + catch (Exception ex) + { + center.error(ex.getMessage(), ex); + return; + } + try{ + +// corePlugin.getClass().getMethod("run", String[].class).invoke(corePlugin, (Object) args); + // 2014 breaking up above statement; 1st get name of class at run-time for predetermined instantiated object + Class pClass = corePlugin.getClass(); +// Method[] someMethods = pClass.getDeclaredMethods(); +// System.out.println("Now try to list the methods"); +// for (Method aMethod : someMethods) +// { +// String methodName = aMethod.getName(); +// System.out.println("method name = " + methodName + " and its parameter types:"); +// Type[] someTypes = aMethod.getGenericParameterTypes(); +// for (Type aType : someTypes) +// { +// String myTypeString = aType.toString(); +// System.out.println("\t" + myTypeString); +// } +// } + // 2nd get name of method at run-time that belongs to class + Method aMethod = pClass.getMethod((String) "run", String[].class); + // 3rd invoke actual method of that class on an object + aMethod.invoke(corePlugin, new java.lang.Object[] {args}); + + } catch (InvocationTargetException itEx) + { + System.out.println("caught an InvocationTargetException in Boot.run; printing .getCause()"); + center.error(itEx.getCause(), itEx); + } + catch (Exception ex) { + System.out.println("Caught an Exception in Boot.java"); + center.error(ex.getMessage(), ex); + } + } + + private PluginManager initializePluginManager(Collection locations, Properties props) + throws JpfException, IOException, ParserConfigurationException, SAXException { + +// PluginManager pluginManager = ObjectFactory.newInstance(new ExtendedProperties(props)).createManager(); +// ObjectFactory fac = ObjectFactory.newInstance(new ExtendedProperties(props)); +// PluginManager pluginManager = fac.createManager(); + ExtendedProperties extProperties = new ExtendedProperties(props); // 2014 + ObjectFactory objFactory = ObjectFactory.newInstance(extProperties); + PluginManager pluginManager = objFactory.createManager(); + + List validLocations = new ArrayList(); + + List restrictions = new ArrayList(); + for (Object key : props.keySet()) { + if (key.toString().startsWith(PLUGIN_RESTRICT_PREFIX)) { + String strKey = key.toString(); + String restrictId = strKey.substring(strKey.lastIndexOf(".") + 1, strKey.length()); + String restrictVal = props.getProperty(strKey); + restrictions.add(new Restriction(restrictId, restrictVal)); + } + } + + if (restrictions.size() > 0) { + for (Iterator iter = locations.iterator(); iter.hasNext();) + { + PluginLocation location = (PluginLocation) iter.next(); + PluginReader reader = new PluginReader(location.getManifestLocation()); + PluginAttributes pluginAttribs = reader.parse(); + + boolean pass = true; + for (Restriction restriction : restrictions) { + if (!restriction.pass(pluginAttribs)) { + pass = false; + break; + } + } + + if (pass) { + validLocations.add(location); + } + } + + } else { +// validLocations.addAll(locations); // 2014 CHANGE TO ITERATE locations & ADD ONLY THOSE NOT ALREADY IN validLocations + for (Iterator anIterator = locations.iterator(); anIterator.hasNext();) + { + PluginLocation aLocation = (PluginLocation)anIterator.next(); + if(!validLocations.contains(aLocation) ) + { + // that location not already in validLocations, so add it + validLocations.add(aLocation); + } + } + } +PluginLocation[] myLocations = validLocations.toArray(new PluginManager.PluginLocation[validLocations.size()]); +//for(int i=0; i map = pluginManager.publishPlugins(myLocations); +// Map map = pluginManager.publishPlugins((PluginManager.PluginLocation[]) validLocations //.toArray()); +// .toArray(new PluginManager.PluginLocation[validLocations.size()])); // 2014 + // Check plug-in's integrity + IntegrityCheckReport integrityCheckReport = pluginManager.getRegistry().checkIntegrity( + pluginManager.getPathResolver(), true); +// if (integrityCheckReport.countErrors() > 0) { // 2014 had been != 0 +// // something wrong with the plugin set +// center.fatal(integrityCheckReport2str(integrityCheckReport), new RuntimeException("Invalid plugin configuration")); +// System.exit(1); +// } + + for (Iterator iter = map.values().iterator(); iter.hasNext();) { + Identity id = (Identity) iter.next(); + PluginDescriptor desc = pluginManager.getRegistry().getPluginDescriptor(id.getId()); + pluginManager.getPluginClassLoader(desc); + } + return pluginManager; + } + + private String integrityCheckReport2str(IntegrityCheckReport report) { + StringBuffer buf = new StringBuffer(); + + for (Iterator it = report.getItems().iterator(); it.hasNext();) { + IntegrityCheckReport.ReportItem item = (IntegrityCheckReport.ReportItem) it.next(); +// if (item.getSeverity() != IntegrityCheckReport.Severity.ERROR) //ReportItem.SEVERITY_ERROR) { +// { +// continue; +// } +// buf.append(item.getMessage()); +// buf.append("\n\n\n"); + } + + buf.append("full integrity check report:\r\n"); + buf.append("-------------- REPORT BEGIN -----------------\r\n"); + for (Iterator it = report.getItems().iterator(); it.hasNext();) { + IntegrityCheckReport.ReportItem item = (IntegrityCheckReport.ReportItem) it.next(); + buf.append("\tseverity=").append(item.getSeverity()).append("; code=").append(item.getCode()) + .append("; message=").append(item.getMessage()).append("; source=") + .append(item.getSource()).append("\r\n"); + } + buf.append("-------------- REPORT END -----------------"); + return buf.toString(); + } + + private Collection findPluginLocations(Properties props) throws Exception { + DefaultPluginsCollector collector = new DefaultPluginsCollector(); + ExtendedProperties eprops = new ExtendedProperties(props); + + if (props.containsKey(PLUGIN_DESCRIPTOR_PROP)) { + // treat is as the jpf xml file that holds plugin locations + eprops.put("org.java.plugin.boot.pluginsLocationsDescriptors", + props.getProperty(PLUGIN_DESCRIPTOR_PROP)); + } else { + String pluginFolder = RUNTIME_DIR_ROOT + props.getProperty(PLUGIN_FOLDER_PROP); + eprops.put("org.java.plugin.boot.pluginsRepositories", pluginFolder); + } + collector.configure(eprops); + Collection locations = collector.collectPluginLocations(); + + String exclude = props.getProperty("pluginFolders.exclude", ""); + StringTokenizer tok = new StringTokenizer(exclude, ","); + List urls = new ArrayList(); + while (tok.hasMoreTokens()) { + String loc = tok.nextToken().trim(); + try { + URL url = new File(loc).getCanonicalFile().toURI().toURL(); + urls.add(url); + } catch (IOException ex) { + center.warn("Error finding directory to exclude from plugin search", ex); + } + } + + if (urls.size() > 0) { + for (Iterator iter = locations.iterator(); iter.hasNext();) { + PluginManager.PluginLocation loc = (PluginManager.PluginLocation) iter.next(); + for (URL url : urls) { + if (loc.getContextLocation().toExternalForm().startsWith(url.toExternalForm())) + iter.remove(); + } + } + } + + return locations; + } + + public static void main(String[] args) { + Boot boot = new Boot(); + + PluginManager manager = boot.init(args); + if(manager == null) + { + System.out.println(" boot.init returned null. Ending with exit(1)"); + System.exit(1); + } + boot.run(manager, args); + } + + private static class Restriction { + + private String id; + private String val; + + private Restriction(String id, String val) { + this.id = id; + this.val = val; + } + + private boolean pass(PluginAttributes pAttribs) { + + SimpleAttribute attrib = pAttribs.getAttribute(id); + if (attrib == null) + return false; + + return attrib.getValue().equals(val); + } + } +} diff --git a/festc_saf_core_runtime_temp/src/saf/core/runtime/CorePlugin.java b/festc_saf_core_runtime_temp/src/saf/core/runtime/CorePlugin.java index 53fbdef..f3e0ef9 100644 --- a/festc_saf_core_runtime_temp/src/saf/core/runtime/CorePlugin.java +++ b/festc_saf_core_runtime_temp/src/saf/core/runtime/CorePlugin.java @@ -1,86 +1,86 @@ -package saf.core.runtime; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import org.java.plugin.Plugin; -import org.java.plugin.PluginLifecycleException; -import org.java.plugin.registry.Extension; -import org.java.plugin.registry.ExtensionPoint; - -import simphony.util.messages.MessageCenter; - -/** - * @author Nick Collier - * @version $Revision: 1.6 $ $Date: 2006/02/07 20:39:51 $ - */ -public class CorePlugin extends Plugin { - - private static final String APP_RUN_ID = "IApplicationRunnable"; - private IApplicationRunnable appRunner; - - protected void doStart() throws Exception { - - } - - protected void doStop() throws Exception { - - } - - - public void run(String[] args) { - try { - loadAppPlugin(); - loadUIPlugin(args); // added args - runApplicationRunnable(args); - } catch (Exception ex) { - MessageCenter.getMessageCenter(getClass()).error("Error instantiating plugins", ex); - } - } - - private void loadUIPlugin(String[] args) throws PluginLifecycleException, NoSuchMethodException, - IllegalAccessException, InvocationTargetException // added args - { - try{ - Plugin plugin = getManager().getPlugin("saf.core.ui"); - // plugin.getClass().getMethod("initialize", new Class[]{}).invoke(plugin); // 2014 - Class aClass = plugin.getClass(); - Method aMethod = aClass.getMethod((String) "initialize", new Class[]{}); - - aMethod.invoke(plugin); - - } catch(InvocationTargetException itEx) - { - System.err.println("caught an InvocationTargetException in CorePlugin.loadUIPlugin; printing .getCause()"); - System.err.print(itEx.getCause()); - } - catch(Exception ex) { - System.err.println("Caught an Exception in CorePlugin.java"); - System.err.print(ex.getCause()); - System.err.println(); - } - } - - private void loadAppPlugin() throws PluginLifecycleException, ClassNotFoundException, - IllegalAccessException, InstantiationException, PluginDefinitionException { - ExtensionPoint extPoint = getManager().getRegistry().getExtensionPoint(getDescriptor().getId(), APP_RUN_ID); - //System.out.println("number of IApplicationRunnable: " + extPoint.getConnectedExtensions().size()); - if (extPoint.getConnectedExtensions().size() != 1) { - throw new PluginDefinitionException("Plugin must implement one and only one IApplicationRunnable"); - } - Extension ext = (Extension) extPoint.getConnectedExtensions().iterator().next(); - Plugin plugin = getManager().getPlugin(ext.getDeclaringPluginDescriptor().getId()); - Class pluginCls = plugin.getClass(); - Class appRunnerClass = pluginCls.getClassLoader().loadClass(ext.getParameter("class").valueAsString()); - if (pluginCls.equals(appRunnerClass)) { - appRunner = (IApplicationRunnable) plugin; - } else { - appRunner = (IApplicationRunnable) appRunnerClass.newInstance(); - } - } - - private void runApplicationRunnable(String[] args) { - appRunner.run(args); - } -} - +package saf.core.runtime; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.java.plugin.Plugin; +import org.java.plugin.PluginLifecycleException; +import org.java.plugin.registry.Extension; +import org.java.plugin.registry.ExtensionPoint; + +import simphony.util.messages.MessageCenter; + +/** + * @author Nick Collier + * @version $Revision: 1.6 $ $Date: 2006/02/07 20:39:51 $ + */ +public class CorePlugin extends Plugin { + + private static final String APP_RUN_ID = "IApplicationRunnable"; + private IApplicationRunnable appRunner; + + protected void doStart() throws Exception { + + } + + protected void doStop() throws Exception { + + } + + + public void run(String[] args) { + try { + loadAppPlugin(); + loadUIPlugin(args); // added args + runApplicationRunnable(args); + } catch (Exception ex) { + MessageCenter.getMessageCenter(getClass()).error("Error instantiating plugins", ex); + } + } + + private void loadUIPlugin(String[] args) throws PluginLifecycleException, NoSuchMethodException, + IllegalAccessException, InvocationTargetException // added args + { + try{ + Plugin plugin = getManager().getPlugin("saf.core.ui"); + // plugin.getClass().getMethod("initialize", new Class[]{}).invoke(plugin); // 2014 + Class aClass = plugin.getClass(); + Method aMethod = aClass.getMethod((String) "initialize", new Class[]{}); + + aMethod.invoke(plugin); + + } catch(InvocationTargetException itEx) + { + System.err.println("caught an InvocationTargetException in CorePlugin.loadUIPlugin; printing .getCause()"); + System.err.print(itEx.getCause()); + } + catch(Exception ex) { + System.err.println("Caught an Exception in CorePlugin.java"); + System.err.print(ex.getCause()); + System.err.println(); + } + } + + private void loadAppPlugin() throws PluginLifecycleException, ClassNotFoundException, + IllegalAccessException, InstantiationException, PluginDefinitionException { + ExtensionPoint extPoint = getManager().getRegistry().getExtensionPoint(getDescriptor().getId(), APP_RUN_ID); + //System.out.println("number of IApplicationRunnable: " + extPoint.getConnectedExtensions().size()); + if (extPoint.getConnectedExtensions().size() != 1) { + throw new PluginDefinitionException("Plugin must implement one and only one IApplicationRunnable"); + } + Extension ext = (Extension) extPoint.getConnectedExtensions().iterator().next(); + Plugin plugin = getManager().getPlugin(ext.getDeclaringPluginDescriptor().getId()); + Class pluginCls = plugin.getClass(); + Class appRunnerClass = pluginCls.getClassLoader().loadClass(ext.getParameter("class").valueAsString()); + if (pluginCls.equals(appRunnerClass)) { + appRunner = (IApplicationRunnable) plugin; + } else { + appRunner = (IApplicationRunnable) appRunnerClass.newInstance(); + } + } + + private void runApplicationRunnable(String[] args) { + appRunner.run(args); + } +} + diff --git a/festc_saf_core_runtime_temp/src/saf/core/runtime/IApplicationRunnable.java b/festc_saf_core_runtime_temp/src/saf/core/runtime/IApplicationRunnable.java index 84b7f68..b68a3dd 100644 --- a/festc_saf_core_runtime_temp/src/saf/core/runtime/IApplicationRunnable.java +++ b/festc_saf_core_runtime_temp/src/saf/core/runtime/IApplicationRunnable.java @@ -1,21 +1,21 @@ -package saf.core.runtime; - -/** - * Interface for the application entry point. Boot will - * attempt to find a plugin class that implements this interface - * and then will call the run method. - * - * @author Nick Collier - * @version $Revision: 1.3 $ $Date: 2006/02/07 20:39:51 $ - */ -public interface IApplicationRunnable { - - /** - * Runs the application. This is the equivalent of - * main(String[] args). - * - * @param args the arguments to the application - */ - public void run(String[] args); - -} +package saf.core.runtime; + +/** + * Interface for the application entry point. Boot will + * attempt to find a plugin class that implements this interface + * and then will call the run method. + * + * @author Nick Collier + * @version $Revision: 1.3 $ $Date: 2006/02/07 20:39:51 $ + */ +public interface IApplicationRunnable { + + /** + * Runs the application. This is the equivalent of + * main(String[] args). + * + * @param args the arguments to the application + */ + public void run(String[] args); + +} diff --git a/festc_saf_core_runtime_temp/src/saf/core/runtime/PluginDefinitionException.java b/festc_saf_core_runtime_temp/src/saf/core/runtime/PluginDefinitionException.java index 8d8c2a7..baf2595 100644 --- a/festc_saf_core_runtime_temp/src/saf/core/runtime/PluginDefinitionException.java +++ b/festc_saf_core_runtime_temp/src/saf/core/runtime/PluginDefinitionException.java @@ -1,24 +1,24 @@ -package saf.core.runtime; - -/** - * @author Nick Collier - * @version $Revision: 1.2 $ $Date: 2005/11/21 18:55:38 $ - */ -public class PluginDefinitionException extends Exception { - - public PluginDefinitionException() { - super(); - } - - public PluginDefinitionException(String message) { - super(message); - } - - public PluginDefinitionException(String message, Throwable cause) { - super(message, cause); - } - - public PluginDefinitionException(Throwable cause) { - super(cause); - } -} +package saf.core.runtime; + +/** + * @author Nick Collier + * @version $Revision: 1.2 $ $Date: 2005/11/21 18:55:38 $ + */ +public class PluginDefinitionException extends Exception { + + public PluginDefinitionException() { + super(); + } + + public PluginDefinitionException(String message) { + super(message); + } + + public PluginDefinitionException(String message, Throwable cause) { + super(message, cause); + } + + public PluginDefinitionException(Throwable cause) { + super(cause); + } +} diff --git a/festc_saf_core_runtime_temp/src/saf/core/runtime/package-info.java b/festc_saf_core_runtime_temp/src/saf/core/runtime/package-info.java index 1ffea8a..9202f20 100644 --- a/festc_saf_core_runtime_temp/src/saf/core/runtime/package-info.java +++ b/festc_saf_core_runtime_temp/src/saf/core/runtime/package-info.java @@ -1,8 +1,8 @@ -/** - * - */ -/** - * @author Dongmei Yang - * - */ +/** + * + */ +/** + * @author Dongmei Yang + * + */ package saf.core.runtime; \ No newline at end of file diff --git a/festc_saf_core_runtime_temp/src/simphony/settings/SettingsIO.java b/festc_saf_core_runtime_temp/src/simphony/settings/SettingsIO.java index 0021a20..32db76b 100644 --- a/festc_saf_core_runtime_temp/src/simphony/settings/SettingsIO.java +++ b/festc_saf_core_runtime_temp/src/simphony/settings/SettingsIO.java @@ -1,90 +1,90 @@ -/*CopyrightHere*/ -package simphony.settings; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; - -import com.thoughtworks.xstream.XStream; -import com.thoughtworks.xstream.io.xml.DomDriver; - -/** - * This handles IO operations on {@link simphony.settings.SettingsRegistry}s. It does not handle - * converting between different implementations of {@link simphony.settings.SettingsRegistry}s, so - * you cannot serialize one implementation and read it in with a different implementation. - * - * @author Jerry Vos - */ -public class SettingsIO { - public static final String SETTINGS_FILE_NAME = "SettingsFileName"; - - public static boolean USE_DOM_DRIVER = false; - - private static XStream getXStream() { - if (USE_DOM_DRIVER) { - return new XStream(new DomDriver()); - } - return new XStream(); - } - - /** - * This loads from the specified file a {@link SettingsRegistry}. If the file does not exist - * this will return a new {@link SettingsRegistry} with the given id, otherwise it will load one - * from the specified file and set its id to be the specified id.

- * - * If the registry has already been loaded this will return the previously loaded one. As with - * the store methods, this will not attempt to reload the next registry in the chain. - * - * @param registryId - * the id for the registry - * @param fileName - * the name of the file that the registry may be loaded from - * @return a registry with the specified id - */ - public static SettingsRegistry loadSettings(String registryId, String fileName) { - XStream xstream = getXStream(); - - SettingsRegistry registry = null; - File settingsFile = new File(fileName); - if (!settingsFile.exists()) { - registry = new SettingsRegistry(registryId); - } else { - try { - registry = (SettingsRegistry) xstream.fromXML(new FileReader(fileName)); - } catch (FileNotFoundException ex) { - registry = new SettingsRegistry(registryId); - } - - - registry.setRegistryId(registryId); - registry.put(SETTINGS_FILE_NAME, fileName); - } - - return registry; - } - - /** - * Stores the specified registry to the specified file.

- * - * This will not store the pointer to the next registry, nor will it store the next - * registry itself. - * - * @param registry - * the registry to store - * @param fileName - * the name of the file to store the registry to - * @throws IOException - */ - public static void storeSettings(SettingsRegistry registry, String fileName) - throws IOException { - XStream xstream = getXStream(); - - SettingsRegistry nextRegistry = registry.getNext(); - - xstream.toXML(registry, new FileWriter(fileName)); - - registry.setNext(nextRegistry); - } -} +/*CopyrightHere*/ +package simphony.settings; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.DomDriver; + +/** + * This handles IO operations on {@link simphony.settings.SettingsRegistry}s. It does not handle + * converting between different implementations of {@link simphony.settings.SettingsRegistry}s, so + * you cannot serialize one implementation and read it in with a different implementation. + * + * @author Jerry Vos + */ +public class SettingsIO { + public static final String SETTINGS_FILE_NAME = "SettingsFileName"; + + public static boolean USE_DOM_DRIVER = false; + + private static XStream getXStream() { + if (USE_DOM_DRIVER) { + return new XStream(new DomDriver()); + } + return new XStream(); + } + + /** + * This loads from the specified file a {@link SettingsRegistry}. If the file does not exist + * this will return a new {@link SettingsRegistry} with the given id, otherwise it will load one + * from the specified file and set its id to be the specified id.

+ * + * If the registry has already been loaded this will return the previously loaded one. As with + * the store methods, this will not attempt to reload the next registry in the chain. + * + * @param registryId + * the id for the registry + * @param fileName + * the name of the file that the registry may be loaded from + * @return a registry with the specified id + */ + public static SettingsRegistry loadSettings(String registryId, String fileName) { + XStream xstream = getXStream(); + + SettingsRegistry registry = null; + File settingsFile = new File(fileName); + if (!settingsFile.exists()) { + registry = new SettingsRegistry(registryId); + } else { + try { + registry = (SettingsRegistry) xstream.fromXML(new FileReader(fileName)); + } catch (FileNotFoundException ex) { + registry = new SettingsRegistry(registryId); + } + + + registry.setRegistryId(registryId); + registry.put(SETTINGS_FILE_NAME, fileName); + } + + return registry; + } + + /** + * Stores the specified registry to the specified file.

+ * + * This will not store the pointer to the next registry, nor will it store the next + * registry itself. + * + * @param registry + * the registry to store + * @param fileName + * the name of the file to store the registry to + * @throws IOException + */ + public static void storeSettings(SettingsRegistry registry, String fileName) + throws IOException { + XStream xstream = getXStream(); + + SettingsRegistry nextRegistry = registry.getNext(); + + xstream.toXML(registry, new FileWriter(fileName)); + + registry.setNext(nextRegistry); + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/settings/SettingsRegistry.java b/festc_saf_core_runtime_temp/src/simphony/settings/SettingsRegistry.java index 5f93d80..67b6b5b 100644 --- a/festc_saf_core_runtime_temp/src/simphony/settings/SettingsRegistry.java +++ b/festc_saf_core_runtime_temp/src/simphony/settings/SettingsRegistry.java @@ -1,221 +1,221 @@ -/*CopyrightHere*/ -package simphony.settings; - -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; - -/** - * This is a simple class for storing settings for an application. This is at heart just a chain of - * {@link java.util.Map}s with an id assosciated to them. This stores that id in itself through the - * key {@link #REGISTRY_ID_KEY}. - * - * @author Jerry Vos - */ -public class SettingsRegistry extends Hashtable { - /** - * The key the registry id is stored under - */ - public static final String REGISTRY_ID_KEY = "SettingsRegistryId"; - - private static final long serialVersionUID = 1315247041894184896L; - - private static final Map registryMap = new HashMap(); - - private SettingsRegistry next; - - /** - * Constructs this registry with the specified key. - * - * @see #putHere(String, Object) used for storing the registry id - * - * @param registryId - * the registry's id - */ - public SettingsRegistry(String registryId) { - if (registryId != null) { - putHere(REGISTRY_ID_KEY, registryId); - } - } - - /** - * Sets this registry's id. This is the same as put(REGISTRY_ID_KEY, registryId). - * - * @see #putHere(String, Object) - * - * @param registryId - * the id for this registry - */ - public synchronized void setRegistryId(String registryId) { - putHere(REGISTRY_ID_KEY, registryId); - } - - /** - * Retrieves this registry's id. This is the same as get(REGISTRY_ID_KEY). - * - * @return the id for this registry - */ - public synchronized String getRegistryId() { - return super.get(REGISTRY_ID_KEY).toString(); - } - - /** - * This will try to find a value for the specified key in this registry, and if it cannot it - * will attempt to find one in the next registry (which also will attempt to check in itself and - * then the next, ...). - * - * @param key - * the key to search for a value for - * @return the value for the given key in the registry chain starting at this registry and - * onwards - */ - @Override - public synchronized Object get(Object key) { - Object superResult = super.get(key); - if (superResult != null) { - return superResult; - } - - if (next != null) { - return next.get(key); - } - return null; - } - - /** - * This attempts to find a registry with the given key already stored in it. If it cannot find - * one it will add the key and value to itself. If it can find one with the specified key it - * will set that value on that registry. - * - * @see #putHere(String, Object) - * @see #getNext() - * - * @param key - * the key to store the value under - * @param value - * the value to store - * @return the last value stored for the given key - */ - @Override - public synchronized Object put(String key, Object value) { - // first see if we can find a registry with the specified key - SettingsRegistry regWithKey = findRegistryWithKey(key); - if (regWithKey != null) { - return regWithKey.putHere(key, value); - } else { - // couldn't find one so add it to ourselves - return putHere(key, value); - } - - } - - /** - * Stores the given value into this registry. This is like {@link #put(String, Object)}, except - * it will not attempt to find a registry with the specified key. - * - * @param key - * the key to store - * @param value - * the value to store it under - * @return - */ - public synchronized Object putHere(String key, Object value) { - return super.put(key, value); - } - - protected SettingsRegistry findRegistryWithKey(String key) { - // if this registry has the key, return itself - if (super.get(key) != null) { - return this; - } - - // now attempt to see if down the chain something has this key - if (next == null) { - return null; - } - SettingsRegistry regWithKey = next.findRegistryWithKey(key); - if (regWithKey != null) { - return regWithKey; - } - - // nothing had the key - return null; - } - - /** - * Retrieves the next registry in the chain (the one after this one). - * - * @return the next registry - */ - public synchronized SettingsRegistry getNext() { - return next; - } - - /** - * Sets the next registry in the settings chain. - * - * @param next - * the next registry - */ - public synchronized void setNext(SettingsRegistry next) { - this.next = next; - } - - /** - * Retrives a static registry with the specified key. If another settings registry has been - * created with the specified id (using this method) that registry will be returned. If no - * registry has been created with the specified id, this will attempt to read one in using the - * specified file name. If reading the file name fails then a new SettingsRegistry will be - * created and returned. - * - * @see SettingsIO#loadSettings(String, String) - * - * @param registryId - * the id of the registry - * @param fileName - * the name of the settings file+ - * @return a SettingsRegistry - */ - public static SettingsRegistry getRegistry(String registryId, String fileName) { - SettingsRegistry registry = registryMap.get(registryId); - if (registry != null) { - return registry; - } - - try { - registry = SettingsIO.loadSettings(registryId, fileName); - } catch (Exception ex) { - registry = new SettingsRegistry(registryId); - } - return register(registry); - } - - /** - * Retrives a static registry with the specified key. If no registry has - * been created or registered with the specified id, this will return null. - * - * @see SettingsRegistry#getRegistry(String) - * @see SettingsRegistry#register(SettingsRegistry) - * - * @param registryId - * the id of the registry - * @return a SettingsRegistry - */ - public static SettingsRegistry getRegistry(String registryId) { - return registryMap.get(registryId); - } - - /** - * Registers a SettingsRegistry using its id from its {@link #getRegistryId()}. This will - * be returned from calls to {@link SettingsRegistry#getRegistry(String, String)} with - * the registry's id. - * - * @param registry the registry to register - * - * @return the passed in registry - */ - public static SettingsRegistry register(SettingsRegistry registry) { - registryMap.put(registry.getRegistryId(), registry); - return registry; - } -} +/*CopyrightHere*/ +package simphony.settings; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +/** + * This is a simple class for storing settings for an application. This is at heart just a chain of + * {@link java.util.Map}s with an id assosciated to them. This stores that id in itself through the + * key {@link #REGISTRY_ID_KEY}. + * + * @author Jerry Vos + */ +public class SettingsRegistry extends Hashtable { + /** + * The key the registry id is stored under + */ + public static final String REGISTRY_ID_KEY = "SettingsRegistryId"; + + private static final long serialVersionUID = 1315247041894184896L; + + private static final Map registryMap = new HashMap(); + + private SettingsRegistry next; + + /** + * Constructs this registry with the specified key. + * + * @see #putHere(String, Object) used for storing the registry id + * + * @param registryId + * the registry's id + */ + public SettingsRegistry(String registryId) { + if (registryId != null) { + putHere(REGISTRY_ID_KEY, registryId); + } + } + + /** + * Sets this registry's id. This is the same as put(REGISTRY_ID_KEY, registryId). + * + * @see #putHere(String, Object) + * + * @param registryId + * the id for this registry + */ + public synchronized void setRegistryId(String registryId) { + putHere(REGISTRY_ID_KEY, registryId); + } + + /** + * Retrieves this registry's id. This is the same as get(REGISTRY_ID_KEY). + * + * @return the id for this registry + */ + public synchronized String getRegistryId() { + return super.get(REGISTRY_ID_KEY).toString(); + } + + /** + * This will try to find a value for the specified key in this registry, and if it cannot it + * will attempt to find one in the next registry (which also will attempt to check in itself and + * then the next, ...). + * + * @param key + * the key to search for a value for + * @return the value for the given key in the registry chain starting at this registry and + * onwards + */ + @Override + public synchronized Object get(Object key) { + Object superResult = super.get(key); + if (superResult != null) { + return superResult; + } + + if (next != null) { + return next.get(key); + } + return null; + } + + /** + * This attempts to find a registry with the given key already stored in it. If it cannot find + * one it will add the key and value to itself. If it can find one with the specified key it + * will set that value on that registry. + * + * @see #putHere(String, Object) + * @see #getNext() + * + * @param key + * the key to store the value under + * @param value + * the value to store + * @return the last value stored for the given key + */ + @Override + public synchronized Object put(String key, Object value) { + // first see if we can find a registry with the specified key + SettingsRegistry regWithKey = findRegistryWithKey(key); + if (regWithKey != null) { + return regWithKey.putHere(key, value); + } else { + // couldn't find one so add it to ourselves + return putHere(key, value); + } + + } + + /** + * Stores the given value into this registry. This is like {@link #put(String, Object)}, except + * it will not attempt to find a registry with the specified key. + * + * @param key + * the key to store + * @param value + * the value to store it under + * @return + */ + public synchronized Object putHere(String key, Object value) { + return super.put(key, value); + } + + protected SettingsRegistry findRegistryWithKey(String key) { + // if this registry has the key, return itself + if (super.get(key) != null) { + return this; + } + + // now attempt to see if down the chain something has this key + if (next == null) { + return null; + } + SettingsRegistry regWithKey = next.findRegistryWithKey(key); + if (regWithKey != null) { + return regWithKey; + } + + // nothing had the key + return null; + } + + /** + * Retrieves the next registry in the chain (the one after this one). + * + * @return the next registry + */ + public synchronized SettingsRegistry getNext() { + return next; + } + + /** + * Sets the next registry in the settings chain. + * + * @param next + * the next registry + */ + public synchronized void setNext(SettingsRegistry next) { + this.next = next; + } + + /** + * Retrives a static registry with the specified key. If another settings registry has been + * created with the specified id (using this method) that registry will be returned. If no + * registry has been created with the specified id, this will attempt to read one in using the + * specified file name. If reading the file name fails then a new SettingsRegistry will be + * created and returned. + * + * @see SettingsIO#loadSettings(String, String) + * + * @param registryId + * the id of the registry + * @param fileName + * the name of the settings file+ + * @return a SettingsRegistry + */ + public static SettingsRegistry getRegistry(String registryId, String fileName) { + SettingsRegistry registry = registryMap.get(registryId); + if (registry != null) { + return registry; + } + + try { + registry = SettingsIO.loadSettings(registryId, fileName); + } catch (Exception ex) { + registry = new SettingsRegistry(registryId); + } + return register(registry); + } + + /** + * Retrives a static registry with the specified key. If no registry has + * been created or registered with the specified id, this will return null. + * + * @see SettingsRegistry#getRegistry(String) + * @see SettingsRegistry#register(SettingsRegistry) + * + * @param registryId + * the id of the registry + * @return a SettingsRegistry + */ + public static SettingsRegistry getRegistry(String registryId) { + return registryMap.get(registryId); + } + + /** + * Registers a SettingsRegistry using its id from its {@link #getRegistryId()}. This will + * be returned from calls to {@link SettingsRegistry#getRegistry(String, String)} with + * the registry's id. + * + * @param registry the registry to register + * + * @return the passed in registry + */ + public static SettingsRegistry register(SettingsRegistry registry) { + registryMap.put(registry.getRegistryId(), registry); + return registry; + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/ThreadUtilities.java b/festc_saf_core_runtime_temp/src/simphony/util/ThreadUtilities.java index d71d35e..f8bc767 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/ThreadUtilities.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/ThreadUtilities.java @@ -1,91 +1,91 @@ -package simphony.util; - -import simphony.util.messages.MessageCenter; - -import java.awt.*; -import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Thread related utility methods. - * - * @author Nick Collier - * @version $Revision: 1.1.2.3 $ $Date: 2007/03/14 20:28:06 $ - */ -public class ThreadUtilities { - - private static Lock rieLock = new ReentrantLock(); - private static Lock riewLock = new ReentrantLock(); - - private static class Runner { - - private Runnable runnable; - private Lock lock; - - private Runner(Lock lock, Runnable runnable) { - this.lock = lock; - this.runnable = runnable; - } - - public void run() { - lock.unlock(); - runnable.run(); - } - } - - /** - * Runs the specified runnable in the swing event thread. If the - * current thread is the event thread then this is run immediately, - * otherwise it is run via EventQueue.invokeLater - * - * @param runnable the runnable to run - */ - public static void runInEventThread(Runnable runnable) { - rieLock.lock(); - if (EventQueue.isDispatchThread()) { - new Runner(rieLock, runnable).run(); - } else { - EventQueue.invokeLater(runnable); - rieLock.unlock(); - } - } - - /** - * Posts the specified runnable to the event queue and returns. The - * runnable will run in the event queue when its turn is reached. - * - * @param runnable the runnable to run in the event queue - */ - public synchronized static void runLaterInEventThread(Runnable runnable) { - EventQueue.invokeLater(runnable); - } - - - /** - * Runs the specified runnable in the swing event thread and wait - * for it to finish executing. If the - * current thread is the event thread then this is run immediately, - * otherwise it is run via EventQueue.invokeAndWaity - * - * @param runnable the runnable to run - */ - public static void runInEventThreadAndWait(Runnable runnable) { - try { - riewLock.lock(); - if (EventQueue.isDispatchThread()) { - new Runner(riewLock, runnable).run(); - } else { - EventQueue.invokeAndWait(runnable); - riewLock.unlock(); - } - } catch (InvocationTargetException e) { - riewLock.unlock(); - MessageCenter.getMessageCenter(ThreadUtilities.class).error("Error in invokeAndWait", e); - } catch (InterruptedException e) { - riewLock.unlock(); - MessageCenter.getMessageCenter(ThreadUtilities.class).error("Error in invokeAndWait", e); - } - } -} - +package simphony.util; + +import simphony.util.messages.MessageCenter; + +import java.awt.*; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Thread related utility methods. + * + * @author Nick Collier + * @version $Revision: 1.1.2.3 $ $Date: 2007/03/14 20:28:06 $ + */ +public class ThreadUtilities { + + private static Lock rieLock = new ReentrantLock(); + private static Lock riewLock = new ReentrantLock(); + + private static class Runner { + + private Runnable runnable; + private Lock lock; + + private Runner(Lock lock, Runnable runnable) { + this.lock = lock; + this.runnable = runnable; + } + + public void run() { + lock.unlock(); + runnable.run(); + } + } + + /** + * Runs the specified runnable in the swing event thread. If the + * current thread is the event thread then this is run immediately, + * otherwise it is run via EventQueue.invokeLater + * + * @param runnable the runnable to run + */ + public static void runInEventThread(Runnable runnable) { + rieLock.lock(); + if (EventQueue.isDispatchThread()) { + new Runner(rieLock, runnable).run(); + } else { + EventQueue.invokeLater(runnable); + rieLock.unlock(); + } + } + + /** + * Posts the specified runnable to the event queue and returns. The + * runnable will run in the event queue when its turn is reached. + * + * @param runnable the runnable to run in the event queue + */ + public synchronized static void runLaterInEventThread(Runnable runnable) { + EventQueue.invokeLater(runnable); + } + + + /** + * Runs the specified runnable in the swing event thread and wait + * for it to finish executing. If the + * current thread is the event thread then this is run immediately, + * otherwise it is run via EventQueue.invokeAndWaity + * + * @param runnable the runnable to run + */ + public static void runInEventThreadAndWait(Runnable runnable) { + try { + riewLock.lock(); + if (EventQueue.isDispatchThread()) { + new Runner(riewLock, runnable).run(); + } else { + EventQueue.invokeAndWait(runnable); + riewLock.unlock(); + } + } catch (InvocationTargetException e) { + riewLock.unlock(); + MessageCenter.getMessageCenter(ThreadUtilities.class).error("Error in invokeAndWait", e); + } catch (InterruptedException e) { + riewLock.unlock(); + MessageCenter.getMessageCenter(ThreadUtilities.class).error("Error in invokeAndWait", e); + } + } +} + diff --git a/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorCenter.java b/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorCenter.java index 66bb8b5..60ab684 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorCenter.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorCenter.java @@ -1,117 +1,117 @@ -/*CopyrightHere*/ -package simphony.util.error; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * @author Jerry Vos - * @version $Revision: 1.5 $ $Date: 2005/11/14 21:58:40 $ - */ -public class ErrorCenter { - // TODO: decide about the static business - private static List errorHandlers = new ArrayList(); - - /** - * Gets an ErrorCenter. - * - * @return - */ - public static ErrorCenter getErrorCenter() { - return new ErrorCenter(); - } - - private ErrorCenter() { - } - - /** - * Fires an error event with the specified error information. - * - * @param errorCode - * a code for the error - * @param info - * information on the error - * @param error - * an error object (useful for getting a stack trace) - * @param metaData - * extra meta data about the erro - * @return if the error was handled or not by one of the ErrorHandlers - */ - public boolean error(int errorCode, Object info, Throwable error, - Object... metaData) { - return fireErrorEvent(errorCode, info, error, metaData); - } - - /** - * Fires an error event with the specified error information. - * - * @param errorCode - * a code for the error - * @param info - * information on the error - * @param error - * an error object (useful for getting a stack trace) - * @param metaData - * extra meta data about the erro - * @return if the error was handled or not by one of the ErrorHandlers - */ - public boolean fireErrorEvent(int errorCode, Object info, Throwable error, - Object... metaData) { - - ErrorEvent event = new ErrorEvent(error, errorCode, info, metaData); - - boolean handled = false; - synchronized (errorHandlers) { - for (ErrorHandler listener : errorHandlers) { - if (listener.handleError(event)) { - handled = true; - } - } - } - - if (!handled) { - if (error instanceof RuntimeException) { - throw (RuntimeException) error; - } else { - throw new RuntimeException(error); - } - } - - return handled; - } - - /** - * Adds an ErrorHandler. - * - * @param handler - * the ErrorHandler to add - */ - public void addErrorHandler(ErrorHandler handler) { - synchronized (errorHandlers) { - errorHandlers.add(handler); - } - } - - /** - * Removes an ErrorHandler. - * - * @param handler - * the ErrorHandler to remove - */ - public void removeErrorHandler(ErrorHandler handler) { - synchronized (errorHandlers) { - errorHandlers.remove(handler); - } - } - - /** - * Retrieves the ErrorHandlers this ErrorCenter contains. - * - * @return the ErrorHandlers this ErrorCenter contains - */ - public Collection getErrorHandlers() { - return Collections.unmodifiableCollection(errorHandlers); - } -} +/*CopyrightHere*/ +package simphony.util.error; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @author Jerry Vos + * @version $Revision: 1.5 $ $Date: 2005/11/14 21:58:40 $ + */ +public class ErrorCenter { + // TODO: decide about the static business + private static List errorHandlers = new ArrayList(); + + /** + * Gets an ErrorCenter. + * + * @return + */ + public static ErrorCenter getErrorCenter() { + return new ErrorCenter(); + } + + private ErrorCenter() { + } + + /** + * Fires an error event with the specified error information. + * + * @param errorCode + * a code for the error + * @param info + * information on the error + * @param error + * an error object (useful for getting a stack trace) + * @param metaData + * extra meta data about the erro + * @return if the error was handled or not by one of the ErrorHandlers + */ + public boolean error(int errorCode, Object info, Throwable error, + Object... metaData) { + return fireErrorEvent(errorCode, info, error, metaData); + } + + /** + * Fires an error event with the specified error information. + * + * @param errorCode + * a code for the error + * @param info + * information on the error + * @param error + * an error object (useful for getting a stack trace) + * @param metaData + * extra meta data about the erro + * @return if the error was handled or not by one of the ErrorHandlers + */ + public boolean fireErrorEvent(int errorCode, Object info, Throwable error, + Object... metaData) { + + ErrorEvent event = new ErrorEvent(error, errorCode, info, metaData); + + boolean handled = false; + synchronized (errorHandlers) { + for (ErrorHandler listener : errorHandlers) { + if (listener.handleError(event)) { + handled = true; + } + } + } + + if (!handled) { + if (error instanceof RuntimeException) { + throw (RuntimeException) error; + } else { + throw new RuntimeException(error); + } + } + + return handled; + } + + /** + * Adds an ErrorHandler. + * + * @param handler + * the ErrorHandler to add + */ + public void addErrorHandler(ErrorHandler handler) { + synchronized (errorHandlers) { + errorHandlers.add(handler); + } + } + + /** + * Removes an ErrorHandler. + * + * @param handler + * the ErrorHandler to remove + */ + public void removeErrorHandler(ErrorHandler handler) { + synchronized (errorHandlers) { + errorHandlers.remove(handler); + } + } + + /** + * Retrieves the ErrorHandlers this ErrorCenter contains. + * + * @return the ErrorHandlers this ErrorCenter contains + */ + public Collection getErrorHandlers() { + return Collections.unmodifiableCollection(errorHandlers); + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorEvent.java b/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorEvent.java index f1c93a9..362dd92 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorEvent.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorEvent.java @@ -1,44 +1,44 @@ -/*CopyrightHere*/ -package simphony.util.error; - -/** - * - * - * @author Jerry Vos - * @version $Revision: 1.1 $ $Date: 2005/11/07 18:42:32 $ - */ -public class ErrorEvent { - private int errorCode; - - private Object info; - - private Throwable error; - - private Object[] metaData; - - public ErrorEvent(Throwable error, int errorCode, Object info, - Object[] metaData) { - super(); - this.error = error; - this.errorCode = errorCode; - this.info = info; - this.metaData = metaData; - } - - - public Throwable getError() { - return error; - } - - public int getErrorCode() { - return errorCode; - } - - public Object getInfo() { - return info; - } - - public Object[] getMetaData() { - return metaData; - } -} +/*CopyrightHere*/ +package simphony.util.error; + +/** + * + * + * @author Jerry Vos + * @version $Revision: 1.1 $ $Date: 2005/11/07 18:42:32 $ + */ +public class ErrorEvent { + private int errorCode; + + private Object info; + + private Throwable error; + + private Object[] metaData; + + public ErrorEvent(Throwable error, int errorCode, Object info, + Object[] metaData) { + super(); + this.error = error; + this.errorCode = errorCode; + this.info = info; + this.metaData = metaData; + } + + + public Throwable getError() { + return error; + } + + public int getErrorCode() { + return errorCode; + } + + public Object getInfo() { + return info; + } + + public Object[] getMetaData() { + return metaData; + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorHandler.java b/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorHandler.java index ad776f7..d60a9b9 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorHandler.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/error/ErrorHandler.java @@ -1,19 +1,19 @@ -/*CopyrightHere*/ -package simphony.util.error; - -/** - * A handler used by {@link simphony.util.error.ErrorCenter} to handle errors. - * - * @author Jerry Vos - * @version $Revision: 1.2 $ $Date: 2005/11/10 23:24:25 $ - */ -public interface ErrorHandler { - /** - * Attempts to handle an error. - * - * @param event - * an error event with information about the error that occurred - * @return whether or not the error was handled - */ - public boolean handleError(ErrorEvent event); -} +/*CopyrightHere*/ +package simphony.util.error; + +/** + * A handler used by {@link simphony.util.error.ErrorCenter} to handle errors. + * + * @author Jerry Vos + * @version $Revision: 1.2 $ $Date: 2005/11/10 23:24:25 $ + */ +public interface ErrorHandler { + /** + * Attempts to handle an error. + * + * @param event + * an error event with information about the error that occurred + * @return whether or not the error was handled + */ + public boolean handleError(ErrorEvent event); +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/AbstractMessageListener.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/AbstractMessageListener.java index 9b420e7..c30f478 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/AbstractMessageListener.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/AbstractMessageListener.java @@ -1,132 +1,132 @@ -/*CopyrightHere*/ -package simphony.util.messages; - -import java.util.Collection; -import java.util.HashSet; - -import org.apache.log4j.Level; - -/** - * An abstract {@link simphony.util.messages.MessageEventListener} that will filter - * {@link simphony.util.messages.MessageEventListener} events if they don't have the correct - * levels set. - * - * @author Jerry Vos - * @version $Revision: 1.3 $ $Date: 2005/11/07 18:42:32 $ - */ -public abstract class AbstractMessageListener implements MessageEventListener { - private HashSet listeningLevels; - - /** - * Creates this class with no specific Levels to accept, therefore it - * accepts all of them. - */ - public AbstractMessageListener() { - this.listeningLevels = new HashSet(); - } - - /** - * Creates this class with the specified Levels to accept. Any message with - * one of these levels will be accepted and passed on to the - * {@link #handleMessage(MessageEvent)} method. - * - * @see #addListeningLevel(Level) - * @see #removeListeningLevel(Level) - * - * @param listeningLevels - * levels to accept - */ - public AbstractMessageListener(Level... listeningLevels) { - this(); - for (Level level : listeningLevels) { - this.listeningLevels.add(level); - } - } - - /** - * Creates this class with the specified Levels to accept. Any message with - * one of these levels will be accepted and passed on to the - * {@link #handleMessage(MessageEvent)} method. - * - * @see #addListeningLevel(Level) - * @see #removeListeningLevel(Level) - * - * @param listeningLevels - * levels to accept - */ - public AbstractMessageListener(Iterable listeningLevels) { - this(); - for (Level level : listeningLevels) { - this.listeningLevels.add(level); - } - } - - /** - * Recieves a {@link MessageEvent} and if either this class has no Levels - * associated with it, or if the event's Level is one of those held in this - * class, it will pass the event on to - * {@link #handleMessage(MessageEvent, Object)}. - * - * @param event - * the message event whose levels will be checked and possibly - * passed on to {@link #handleMessage(MessageEvent, Object)} - */ - public void messageReceived(MessageEvent event) { - // accept if I'm accepting everything (nothing's been set to accept) - // or it is in one of the levels I'm listening for - if (listeningLevels.size() == 0 - || listeningLevels.contains(event.getLevel())) { - handleMessage(event); - } - } - - /** - * Adds a level that this class will accept and pass on to the - * {@link #handleMessage(MessageEvent, Object)} method. - * - * @see #handleMessage(MessageEvent, Object) - * - * @param level - * a level that when found in a message event will cause that - * message to be accepted and passed on - */ - public void addListeningLevel(Level level) { - listeningLevels.add(level); - } - - /** - * Removes a level that this class will accept and pass on to the - * {@link #handleMessage(MessageEvent, Object)} method. - * - * @see #handleMessage(MessageEvent, Object) - * - * @param level - * a level that when found in a message event will cause that - * message NOT to be accepted and passed on - */ - public void removeListeningLevel(Level level) { - listeningLevels.remove(level); - } - - /** - * Retrieves the levels that this class accepts. If there are no Levels - * returned (ie the size of the collection is 0), then all Levels are - * accepted. - * - * @return the levels that this class accepts - */ - public Collection getListeningLevels() { - return listeningLevels; - } - - /** - * This is the method subclasses should (have to) override to receive - * {@link MessageEvent}s. The events passed to this method were received in - * {@link #messageReceived(MessageEvent)} and contained a Level this class - * was listening for. - * - * @param event - * the event to act on. - */ - protected abstract void handleMessage(MessageEvent event); -} +/*CopyrightHere*/ +package simphony.util.messages; + +import java.util.Collection; +import java.util.HashSet; + +import org.apache.log4j.Level; + +/** + * An abstract {@link simphony.util.messages.MessageEventListener} that will filter + * {@link simphony.util.messages.MessageEventListener} events if they don't have the correct + * levels set. + * + * @author Jerry Vos + * @version $Revision: 1.3 $ $Date: 2005/11/07 18:42:32 $ + */ +public abstract class AbstractMessageListener implements MessageEventListener { + private HashSet listeningLevels; + + /** + * Creates this class with no specific Levels to accept, therefore it + * accepts all of them. + */ + public AbstractMessageListener() { + this.listeningLevels = new HashSet(); + } + + /** + * Creates this class with the specified Levels to accept. Any message with + * one of these levels will be accepted and passed on to the + * {@link #handleMessage(MessageEvent)} method. + * + * @see #addListeningLevel(Level) + * @see #removeListeningLevel(Level) + * + * @param listeningLevels + * levels to accept + */ + public AbstractMessageListener(Level... listeningLevels) { + this(); + for (Level level : listeningLevels) { + this.listeningLevels.add(level); + } + } + + /** + * Creates this class with the specified Levels to accept. Any message with + * one of these levels will be accepted and passed on to the + * {@link #handleMessage(MessageEvent)} method. + * + * @see #addListeningLevel(Level) + * @see #removeListeningLevel(Level) + * + * @param listeningLevels + * levels to accept + */ + public AbstractMessageListener(Iterable listeningLevels) { + this(); + for (Level level : listeningLevels) { + this.listeningLevels.add(level); + } + } + + /** + * Recieves a {@link MessageEvent} and if either this class has no Levels + * associated with it, or if the event's Level is one of those held in this + * class, it will pass the event on to + * {@link #handleMessage(MessageEvent, Object)}. + * + * @param event + * the message event whose levels will be checked and possibly + * passed on to {@link #handleMessage(MessageEvent, Object)} + */ + public void messageReceived(MessageEvent event) { + // accept if I'm accepting everything (nothing's been set to accept) + // or it is in one of the levels I'm listening for + if (listeningLevels.size() == 0 + || listeningLevels.contains(event.getLevel())) { + handleMessage(event); + } + } + + /** + * Adds a level that this class will accept and pass on to the + * {@link #handleMessage(MessageEvent, Object)} method. + * + * @see #handleMessage(MessageEvent, Object) + * + * @param level + * a level that when found in a message event will cause that + * message to be accepted and passed on + */ + public void addListeningLevel(Level level) { + listeningLevels.add(level); + } + + /** + * Removes a level that this class will accept and pass on to the + * {@link #handleMessage(MessageEvent, Object)} method. + * + * @see #handleMessage(MessageEvent, Object) + * + * @param level + * a level that when found in a message event will cause that + * message NOT to be accepted and passed on + */ + public void removeListeningLevel(Level level) { + listeningLevels.remove(level); + } + + /** + * Retrieves the levels that this class accepts. If there are no Levels + * returned (ie the size of the collection is 0), then all Levels are + * accepted. + * + * @return the levels that this class accepts + */ + public Collection getListeningLevels() { + return listeningLevels; + } + + /** + * This is the method subclasses should (have to) override to receive + * {@link MessageEvent}s. The events passed to this method were received in + * {@link #messageReceived(MessageEvent)} and contained a Level this class + * was listening for. + * + * @param event + * the event to act on. + */ + protected abstract void handleMessage(MessageEvent event); +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/Log4jMessageListener.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/Log4jMessageListener.java index e70e9f8..36d8984 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/Log4jMessageListener.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/Log4jMessageListener.java @@ -1,87 +1,87 @@ -package simphony.util.messages; - -import java.io.File; -import java.util.Arrays; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -/** - * A MessageEventListener that forwards messages on to log4j. - * - * @author Jerry Vos - */ -public class Log4jMessageListener implements MessageEventListener { - - public static final String INTERNAL_ANCHOR = "MessageCenter" + "." - + "INTERNAL"; - - public static final String CONFIG_FILE_NAME = "MessageCenter.log4j.properties"; - - static { - if (new File(CONFIG_FILE_NAME).exists()) { - PropertyConfigurator.configure(CONFIG_FILE_NAME); - }/* else { - loadDefaultSettings(); - }*/ - - } - - private static Logger getLogger(String name) { - return Logger.getLogger(INTERNAL_ANCHOR + "." + name); - } - - private Logger logger; - - public Log4jMessageListener(Class clazz) { - logger = getLogger(clazz.getName()); - } - - public Log4jMessageListener(String name) { - logger = getLogger(name); - } - - public Log4jMessageListener() { - logger = Logger.getLogger(INTERNAL_ANCHOR); - } - - /** - * Sends a message to log4j with the event's level, message, and throwable - * (if it is not null). - * - * @param event - * a message event - */ - public void messageReceived(MessageEvent event) { - if (event.getThrowable() != null) { - logger.log(event.getLevel(), getMessage(event), event - .getThrowable()); - } else { - logger.log(event.getLevel(), getMessage(event)); - } - } - - protected String getMessage(MessageEvent event) { - String message = (event.getMessage() == null ? "null" : event.getMessage().toString()); - Object[] metaData = event.getMetaData(); - if (metaData != null && metaData.length > 0) { - message += " metaData=" + Arrays.toString(metaData); - } - return message; - } - - /** - * Loads the default logging settings. This sets up a console logger and a rolling file logger, - * both allowing DEBUG messages and higher. The default settings are found in the properties file - * in this package with the name {@link #CONFIG_FILE_NAME}. - */ - public static void loadDefaultSettings() { - PropertyConfigurator.configure(Log4jMessageListener.class.getResource(CONFIG_FILE_NAME)); - } - - public static void main(String[] args) { - loadDefaultSettings(); - MessageCenter.getMessageCenter(Log4jMessageListener.class).fatal("blas", null); - } - -} +package simphony.util.messages; + +import java.io.File; +import java.util.Arrays; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + +/** + * A MessageEventListener that forwards messages on to log4j. + * + * @author Jerry Vos + */ +public class Log4jMessageListener implements MessageEventListener { + + public static final String INTERNAL_ANCHOR = "MessageCenter" + "." + + "INTERNAL"; + + public static final String CONFIG_FILE_NAME = "MessageCenter.log4j.properties"; + + static { + if (new File(CONFIG_FILE_NAME).exists()) { + PropertyConfigurator.configure(CONFIG_FILE_NAME); + }/* else { + loadDefaultSettings(); + }*/ + + } + + private static Logger getLogger(String name) { + return Logger.getLogger(INTERNAL_ANCHOR + "." + name); + } + + private Logger logger; + + public Log4jMessageListener(Class clazz) { + logger = getLogger(clazz.getName()); + } + + public Log4jMessageListener(String name) { + logger = getLogger(name); + } + + public Log4jMessageListener() { + logger = Logger.getLogger(INTERNAL_ANCHOR); + } + + /** + * Sends a message to log4j with the event's level, message, and throwable + * (if it is not null). + * + * @param event + * a message event + */ + public void messageReceived(MessageEvent event) { + if (event.getThrowable() != null) { + logger.log(event.getLevel(), getMessage(event), event + .getThrowable()); + } else { + logger.log(event.getLevel(), getMessage(event)); + } + } + + protected String getMessage(MessageEvent event) { + String message = (event.getMessage() == null ? "null" : event.getMessage().toString()); + Object[] metaData = event.getMetaData(); + if (metaData != null && metaData.length > 0) { + message += " metaData=" + Arrays.toString(metaData); + } + return message; + } + + /** + * Loads the default logging settings. This sets up a console logger and a rolling file logger, + * both allowing DEBUG messages and higher. The default settings are found in the properties file + * in this package with the name {@link #CONFIG_FILE_NAME}. + */ + public static void loadDefaultSettings() { + PropertyConfigurator.configure(Log4jMessageListener.class.getResource(CONFIG_FILE_NAME)); + } + + public static void main(String[] args) { + loadDefaultSettings(); + MessageCenter.getMessageCenter(Log4jMessageListener.class).fatal("blas", null); + } + +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenter.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenter.java index 065475f..073406a 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenter.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenter.java @@ -1,182 +1,182 @@ -/*CopyrightHere*/ -package simphony.util.messages; - -import org.apache.log4j.Level; - -import java.util.*; - -/** - * A class for handling all sorts of messages. This class receives messages of different levels - * through it's different methods and passes these messages on to it's listeners.

To - * retrieve an instance of this class use {@link #getMessageCenter(Class)} or - * {@link #getMessageCenter(Class, Map)}. - * - * @author Jerry Vos - * @see #getMessageCenter(Class) - * @see #getMessageCenter(Class, Map) - * @see #addMessageListener(MessageEventListener) - * @see #removeMessageListener(MessageEventListener) - */ -public class MessageCenter { - - private static final MessageCenter msgCenter = getMessageCenter(MessageCenter.class); - - /** - * Creates a MessageCenter for the specified class. - * - * @param clazz - * @return the created MessageCenter - */ - public static MessageCenter getMessageCenter(Class clazz) { - if (clazz == null) { - RuntimeException ex = new RuntimeException( - "When creating a message center clazz must not be null"); - msgCenter - .warn( - "MessageCenter.getMessageCenter: Warning, " - + "addLogger == true but clazz == null. Cannot add a logger when the class " - + "parameter is null.", ex); - } - return getMessageCenter(clazz.getName(), true); - } - - public static MessageCenter getMessageCenter(String name) { - return getMessageCenter(name, true); - } - - /** - * TODO: fix this javadoc Creates a MessageCenter. - * - * @param name - * an id for the message center - * @param addLogger - * whether or not to add an automatic logger to the MessageCenter - * @return a created MessageCenter - * @see Log4jMessageListener - */ - public static MessageCenter getMessageCenter(String name, boolean addLogger) { - MessageCenter newMsgCenter = new MessageCenter(); - - if (addLogger) { - if (name != null) { - newMsgCenter.logListener = new Log4jMessageListener(name); - } else { - RuntimeException ex = new RuntimeException( - "When adding a logger name must not be null"); - msgCenter - .warn( - "MessageCenter.getMessageCenter: Warning, " - + "addLogger == true but name == null. Cannot add a logger when the name " - + "parameter is null.", ex); - } - } - return newMsgCenter; - } - - /** - * Currently this method is no different then {@link #getMessageCenter(Class)} but it is here in - * case at some point MessageCenter's can be setup with a variety of properties. - * - * @param clazz - * the class this message center is working for - * @param properties - * properties for creation of the MessageCenter (ignored for now) - * @return a newly created MessageCenter - * @see #getMessageCenter(Class) - */ - public static MessageCenter getMessageCenter(Class clazz, Map properties) { - return getMessageCenter(clazz); - } - - // TODO: decide about the static business - private static ArrayList listeners = new ArrayList(); - - private Log4jMessageListener logListener; - - /** - * Constructs the MessageCenter. See the static getMessageCenter(...) methods for instantiating - * MessageCenters. - * - * @see #getMessageCenter(Class) - */ - private MessageCenter() { - } - - public void info(Object info, Object... metaData) { - fireMessageEvent(Level.INFO, info, null, metaData); - } - - public void trace(Object info, Object... metaData) { - fireMessageEvent(Level.TRACE, info, null, metaData); - } - - public void debug(Object info, Object... metaData) { - fireMessageEvent(Level.DEBUG, info, null, metaData); - } - - public void warn(Object info, Object... metaData) { - fireMessageEvent(Level.WARN, info, null, metaData); - } - - public void warn(Object info, Throwable error, Object... metaData) { - fireMessageEvent(Level.WARN, info, error, metaData); - } - - public void error(Object info, Throwable error, Object... metaData) { - fireMessageEvent(Level.ERROR, info, error, metaData); - } - - public void fatal(Object info, Throwable error, Object... metaData) { - fireMessageEvent(Level.FATAL, info, error, metaData); - } - - public void fireMessageEvent(Level level, Object info, Throwable throwable, - Object... metaData) { - List list; - synchronized (listeners) { - list = (List) listeners.clone(); - } - MessageEvent event = new MessageEvent(this, level, info, throwable, metaData); - for (MessageEventListener listener : list) { - listener.messageReceived(event); - } - if (logListener != null) - logListener.messageReceived(event); - } - - public static void addMessageListener(MessageEventListener listener) { - synchronized (listeners) { - listeners.add(listener); - } - } - - public static void removeMessageListener(MessageEventListener listener) { - synchronized (listeners) { - listeners.remove(listener); - } - } - - public static Collection getMessageListeners() { - return Collections.unmodifiableCollection(listeners); - } - - /** - * Retrieves the default message listener that forwards messages to log4j. - * - * @return the logging message listener - */ - public Log4jMessageListener getLogListener() { - return logListener; - } - - /** - * Sets the default message listener that forwards messages to log4j. - * - * @param logListener - * the logging message listener (can be null, in which case no default log listener - * is set) - */ - public void setLogListener(Log4jMessageListener logListener) { - this.logListener = logListener; - } -} +/*CopyrightHere*/ +package simphony.util.messages; + +import org.apache.log4j.Level; + +import java.util.*; + +/** + * A class for handling all sorts of messages. This class receives messages of different levels + * through it's different methods and passes these messages on to it's listeners.

To + * retrieve an instance of this class use {@link #getMessageCenter(Class)} or + * {@link #getMessageCenter(Class, Map)}. + * + * @author Jerry Vos + * @see #getMessageCenter(Class) + * @see #getMessageCenter(Class, Map) + * @see #addMessageListener(MessageEventListener) + * @see #removeMessageListener(MessageEventListener) + */ +public class MessageCenter { + + private static final MessageCenter msgCenter = getMessageCenter(MessageCenter.class); + + /** + * Creates a MessageCenter for the specified class. + * + * @param clazz + * @return the created MessageCenter + */ + public static MessageCenter getMessageCenter(Class clazz) { + if (clazz == null) { + RuntimeException ex = new RuntimeException( + "When creating a message center clazz must not be null"); + msgCenter + .warn( + "MessageCenter.getMessageCenter: Warning, " + + "addLogger == true but clazz == null. Cannot add a logger when the class " + + "parameter is null.", ex); + } + return getMessageCenter(clazz.getName(), true); + } + + public static MessageCenter getMessageCenter(String name) { + return getMessageCenter(name, true); + } + + /** + * TODO: fix this javadoc Creates a MessageCenter. + * + * @param name + * an id for the message center + * @param addLogger + * whether or not to add an automatic logger to the MessageCenter + * @return a created MessageCenter + * @see Log4jMessageListener + */ + public static MessageCenter getMessageCenter(String name, boolean addLogger) { + MessageCenter newMsgCenter = new MessageCenter(); + + if (addLogger) { + if (name != null) { + newMsgCenter.logListener = new Log4jMessageListener(name); + } else { + RuntimeException ex = new RuntimeException( + "When adding a logger name must not be null"); + msgCenter + .warn( + "MessageCenter.getMessageCenter: Warning, " + + "addLogger == true but name == null. Cannot add a logger when the name " + + "parameter is null.", ex); + } + } + return newMsgCenter; + } + + /** + * Currently this method is no different then {@link #getMessageCenter(Class)} but it is here in + * case at some point MessageCenter's can be setup with a variety of properties. + * + * @param clazz + * the class this message center is working for + * @param properties + * properties for creation of the MessageCenter (ignored for now) + * @return a newly created MessageCenter + * @see #getMessageCenter(Class) + */ + public static MessageCenter getMessageCenter(Class clazz, Map properties) { + return getMessageCenter(clazz); + } + + // TODO: decide about the static business + private static ArrayList listeners = new ArrayList(); + + private Log4jMessageListener logListener; + + /** + * Constructs the MessageCenter. See the static getMessageCenter(...) methods for instantiating + * MessageCenters. + * + * @see #getMessageCenter(Class) + */ + private MessageCenter() { + } + + public void info(Object info, Object... metaData) { + fireMessageEvent(Level.INFO, info, null, metaData); + } + + public void trace(Object info, Object... metaData) { + fireMessageEvent(Level.TRACE, info, null, metaData); + } + + public void debug(Object info, Object... metaData) { + fireMessageEvent(Level.DEBUG, info, null, metaData); + } + + public void warn(Object info, Object... metaData) { + fireMessageEvent(Level.WARN, info, null, metaData); + } + + public void warn(Object info, Throwable error, Object... metaData) { + fireMessageEvent(Level.WARN, info, error, metaData); + } + + public void error(Object info, Throwable error, Object... metaData) { + fireMessageEvent(Level.ERROR, info, error, metaData); + } + + public void fatal(Object info, Throwable error, Object... metaData) { + fireMessageEvent(Level.FATAL, info, error, metaData); + } + + public void fireMessageEvent(Level level, Object info, Throwable throwable, + Object... metaData) { + List list; + synchronized (listeners) { + list = (List) listeners.clone(); + } + MessageEvent event = new MessageEvent(this, level, info, throwable, metaData); + for (MessageEventListener listener : list) { + listener.messageReceived(event); + } + if (logListener != null) + logListener.messageReceived(event); + } + + public static void addMessageListener(MessageEventListener listener) { + synchronized (listeners) { + listeners.add(listener); + } + } + + public static void removeMessageListener(MessageEventListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + } + + public static Collection getMessageListeners() { + return Collections.unmodifiableCollection(listeners); + } + + /** + * Retrieves the default message listener that forwards messages to log4j. + * + * @return the logging message listener + */ + public Log4jMessageListener getLogListener() { + return logListener; + } + + /** + * Sets the default message listener that forwards messages to log4j. + * + * @param logListener + * the logging message listener (can be null, in which case no default log listener + * is set) + */ + public void setLogListener(Log4jMessageListener logListener) { + this.logListener = logListener; + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenter.log4j.properties b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenter.log4j.properties index 2588eb0..f75bdc7 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenter.log4j.properties +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenter.log4j.properties @@ -1,17 +1,17 @@ -log4j.logger.MessageCenter.INTERNAL=info, stdout, R - -# Print only messages of level WARN or above in the package com.foo. -#log4j.logger.com.foo=WARN - -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=simphony.util.messages.MessageCenterLayout -# Pattern to output the caller's file name and line number. -log4j.appender.stdout.layout.ConversionPattern=%-5p [%t] %d{ISO8601} %c - %m%n - -log4j.appender.R=org.apache.log4j.RollingFileAppender -log4j.appender.R.File=debug.log -log4j.appender.R.MaxFileSize=100KB -# Keep one backup file -log4j.appender.R.MaxBackupIndex=1 -log4j.appender.R.layout=simphony.util.messages.MessageCenterLayout +log4j.logger.MessageCenter.INTERNAL=info, stdout, R + +# Print only messages of level WARN or above in the package com.foo. +#log4j.logger.com.foo=WARN + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=simphony.util.messages.MessageCenterLayout +# Pattern to output the caller's file name and line number. +log4j.appender.stdout.layout.ConversionPattern=%-5p [%t] %d{ISO8601} %c - %m%n + +log4j.appender.R=org.apache.log4j.RollingFileAppender +log4j.appender.R.File=debug.log +log4j.appender.R.MaxFileSize=100KB +# Keep one backup file +log4j.appender.R.MaxBackupIndex=1 +log4j.appender.R.layout=simphony.util.messages.MessageCenterLayout log4j.appender.R.layout.ConversionPattern=%-5p [%t] %d{ISO8601} %c - %m%n \ No newline at end of file diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenterLayout.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenterLayout.java index c975eee..89c08ea 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenterLayout.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageCenterLayout.java @@ -1,30 +1,30 @@ -/*CopyrightHere*/ -package simphony.util.messages; - -import org.apache.log4j.PatternLayout; -import org.apache.log4j.spi.LoggingEvent; - -/** - * This is a layout that strips from the messages the internal anchor of the message center. So a - * message goes from "[main] FATAL MessageCenter.INTERNAL.simphony.util.messages.Log4jMessageListener blas" - * to "[main] FATAL simphony.util.messages.Log4jMessageListener blas" - * - * @author Jerry Vos - */ -public class MessageCenterLayout extends PatternLayout { - public MessageCenterLayout(String pattern) { - super(pattern); - // TODO Auto-generated constructor stub - // 2014: had to do this to get rid of an Eclipse error: - // Implicit super constructor PatternLayout() is undefined for default constructor. Must define an explicit constructor. - } - - public static final String REPLACED_STRING = Log4jMessageListener.INTERNAL_ANCHOR + "."; - - @Override - public String format(LoggingEvent event) { - String superFormat = super.format(event); - - return superFormat.replace(REPLACED_STRING, ""); - } -} +/*CopyrightHere*/ +package simphony.util.messages; + +import org.apache.log4j.PatternLayout; +import org.apache.log4j.spi.LoggingEvent; + +/** + * This is a layout that strips from the messages the internal anchor of the message center. So a + * message goes from "[main] FATAL MessageCenter.INTERNAL.simphony.util.messages.Log4jMessageListener blas" + * to "[main] FATAL simphony.util.messages.Log4jMessageListener blas" + * + * @author Jerry Vos + */ +public class MessageCenterLayout extends PatternLayout { + public MessageCenterLayout(String pattern) { + super(pattern); + // TODO Auto-generated constructor stub + // 2014: had to do this to get rid of an Eclipse error: + // Implicit super constructor PatternLayout() is undefined for default constructor. Must define an explicit constructor. + } + + public static final String REPLACED_STRING = Log4jMessageListener.INTERNAL_ANCHOR + "."; + + @Override + public String format(LoggingEvent event) { + String superFormat = super.format(event); + + return superFormat.replace(REPLACED_STRING, ""); + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageEvent.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageEvent.java index 28184be..8c6e13a 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageEvent.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageEvent.java @@ -1,50 +1,50 @@ -/*CopyrightHere*/ -package simphony.util.messages; - -import org.apache.log4j.Level; - -public class MessageEvent { - private Object source; - - private Level level; - - private Object message; - - private Object[] metaData; - - private Throwable throwable; - - public MessageEvent(Object source, Level level, Object message, - Throwable throwable, Object... metaData) { - super(); - this.source = source; - this.level = level; - this.message = message; - this.metaData = metaData; - this.throwable = throwable; - } - - public MessageEvent(Object source, Level level, Object message) { - this(source, level, message, null); - } - - public Level getLevel() { - return level; - } - - public Object getMessage() { - return message; - } - - public Object[] getMetaData() { - return metaData; - } - - public Throwable getThrowable() { - return throwable; - } - - public Object getSource() { - return source; - } -} +/*CopyrightHere*/ +package simphony.util.messages; + +import org.apache.log4j.Level; + +public class MessageEvent { + private Object source; + + private Level level; + + private Object message; + + private Object[] metaData; + + private Throwable throwable; + + public MessageEvent(Object source, Level level, Object message, + Throwable throwable, Object... metaData) { + super(); + this.source = source; + this.level = level; + this.message = message; + this.metaData = metaData; + this.throwable = throwable; + } + + public MessageEvent(Object source, Level level, Object message) { + this(source, level, message, null); + } + + public Level getLevel() { + return level; + } + + public Object getMessage() { + return message; + } + + public Object[] getMetaData() { + return metaData; + } + + public Throwable getThrowable() { + return throwable; + } + + public Object getSource() { + return source; + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageEventListener.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageEventListener.java index c18ad1e..1a13bfd 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageEventListener.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/MessageEventListener.java @@ -1,20 +1,20 @@ -/*CopyrightHere*/ -package simphony.util.messages; - -/** - * This is used by {@link simphony.util.messages.MessageCenter} as a sink for - * messages it receives. When a MessageCenter recieves a message it will call - * the methods in this interface with information on the message. - * - * @author Jerry Vos - * @version $Revision: 1.2 $ $Date: 2005/11/10 23:24:25 $ - */ -public interface MessageEventListener { - /** - * Called when a message was received in the MessageCenter. - * - * @param event - * the message event - */ - void messageReceived(MessageEvent event); -} +/*CopyrightHere*/ +package simphony.util.messages; + +/** + * This is used by {@link simphony.util.messages.MessageCenter} as a sink for + * messages it receives. When a MessageCenter recieves a message it will call + * the methods in this interface with information on the message. + * + * @author Jerry Vos + * @version $Revision: 1.2 $ $Date: 2005/11/10 23:24:25 $ + */ +public interface MessageEventListener { + /** + * Called when a message was received in the MessageCenter. + * + * @param event + * the message event + */ + void messageReceived(MessageEvent event); +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/NullTaskMessage.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/NullTaskMessage.java index cbbeab8..5d34b6f 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/NullTaskMessage.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/NullTaskMessage.java @@ -1,12 +1,12 @@ -package simphony.util.messages; - -public class NullTaskMessage extends TaskMessage { - - public NullTaskMessage() { - super(TaskStatus.NULL, null, null); - } - - public String toString() { - return "NULL MESSAGE"; - } -} +package simphony.util.messages; + +public class NullTaskMessage extends TaskMessage { + + public NullTaskMessage() { + super(TaskStatus.NULL, null, null); + } + + public String toString() { + return "NULL MESSAGE"; + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/StackTaskMessageListener.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/StackTaskMessageListener.java index 25d3f2b..1397169 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/StackTaskMessageListener.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/StackTaskMessageListener.java @@ -1,62 +1,62 @@ -package simphony.util.messages; - -import java.util.HashSet; -import java.util.Set; -import java.util.Stack; - -public class StackTaskMessageListener extends TaskMessageListener { - - Stack messageStack = new Stack(); - - Set targetSet = new HashSet(); - - TaskMessageCallback callback; - - public StackTaskMessageListener(TaskMessageCallback callback) { - this.callback = callback; - } - - protected synchronized void processTaskMessage(TaskMessage message) { - if (message.getStatus().equals(TaskMessage.TaskStatus.STARTED)) { - callback.working(true, message.getMessage()); - targetSet.add(message.getKey()); - messageStack.push(message); - } else if (message.getStatus().equals(TaskMessage.TaskStatus.WORKING)) { - callback.working(true, message.getMessage()); - } else { - targetSet.remove(message.getKey()); - if (targetSet.size() == 0) { - callback.working(false, ""); - } else { - callback.working(true, nextMessage(message)); - } - } - } - - private String nextMessage(TaskMessage message) { - Object key = message.getKey(); - if (messageStack.size() > 0) { - if (messageStack.peek().getKey().equals(key)) { - messageStack.pop(); - } - while (messageStack.size() > 0) { - if (!targetSet.contains(messageStack.peek().getKey())) { - messageStack.pop(); - } else { - break; - } - } - } - if (messageStack.size() > 0) { - return messageStack.peek().getMessage(); - } else { - return null; - } - } - - public void messageReceived(MessageEvent arg0) { - if (arg0.getMessage() instanceof TaskMessage) { - processTaskMessage((TaskMessage) arg0.getMessage()); - } - } -} +package simphony.util.messages; + +import java.util.HashSet; +import java.util.Set; +import java.util.Stack; + +public class StackTaskMessageListener extends TaskMessageListener { + + Stack messageStack = new Stack(); + + Set targetSet = new HashSet(); + + TaskMessageCallback callback; + + public StackTaskMessageListener(TaskMessageCallback callback) { + this.callback = callback; + } + + protected synchronized void processTaskMessage(TaskMessage message) { + if (message.getStatus().equals(TaskMessage.TaskStatus.STARTED)) { + callback.working(true, message.getMessage()); + targetSet.add(message.getKey()); + messageStack.push(message); + } else if (message.getStatus().equals(TaskMessage.TaskStatus.WORKING)) { + callback.working(true, message.getMessage()); + } else { + targetSet.remove(message.getKey()); + if (targetSet.size() == 0) { + callback.working(false, ""); + } else { + callback.working(true, nextMessage(message)); + } + } + } + + private String nextMessage(TaskMessage message) { + Object key = message.getKey(); + if (messageStack.size() > 0) { + if (messageStack.peek().getKey().equals(key)) { + messageStack.pop(); + } + while (messageStack.size() > 0) { + if (!targetSet.contains(messageStack.peek().getKey())) { + messageStack.pop(); + } else { + break; + } + } + } + if (messageStack.size() > 0) { + return messageStack.peek().getMessage(); + } else { + return null; + } + } + + public void messageReceived(MessageEvent arg0) { + if (arg0.getMessage() instanceof TaskMessage) { + processTaskMessage((TaskMessage) arg0.getMessage()); + } + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessage.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessage.java index ff62950..d10a4ac 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessage.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessage.java @@ -1,66 +1,66 @@ -package simphony.util.messages; - -import java.io.Serializable; - -/** - * Message notifying about the start or finish of an executing task. This can be - * used to notify the GUI when the task is done so that a message can be given - * or changed. - * - * @author $Author: howe $ - * @version $Revision: 1.1 $ - * - */ -public class TaskMessage implements Serializable { - - private static final long serialVersionUID = -7988872787862424319L; - - public static enum TaskStatus { - STARTED, FINISHED, WORKING, NULL - }; - - private TaskStatus status; - - private Object key; - - private String message; - - public TaskMessage() { - - } - - public TaskMessage(TaskStatus status, Object key, String message) { - super(); - this.status = status; - this.key = key; - this.message = message; - } - - public Object getKey() { - return key; - } - - public void setKey(Object key) { - this.key = key; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public TaskStatus getStatus() { - return status; - } - - public void setStatus(TaskStatus status) { - this.status = status; - } - - public String toString() { - return key.toString() + " reports " + message; - } -} +package simphony.util.messages; + +import java.io.Serializable; + +/** + * Message notifying about the start or finish of an executing task. This can be + * used to notify the GUI when the task is done so that a message can be given + * or changed. + * + * @author $Author: howe $ + * @version $Revision: 1.1 $ + * + */ +public class TaskMessage implements Serializable { + + private static final long serialVersionUID = -7988872787862424319L; + + public static enum TaskStatus { + STARTED, FINISHED, WORKING, NULL + }; + + private TaskStatus status; + + private Object key; + + private String message; + + public TaskMessage() { + + } + + public TaskMessage(TaskStatus status, Object key, String message) { + super(); + this.status = status; + this.key = key; + this.message = message; + } + + public Object getKey() { + return key; + } + + public void setKey(Object key) { + this.key = key; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public TaskStatus getStatus() { + return status; + } + + public void setStatus(TaskStatus status) { + this.status = status; + } + + public String toString() { + return key.toString() + " reports " + message; + } +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessageCallback.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessageCallback.java index 282564a..15cac01 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessageCallback.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessageCallback.java @@ -1,7 +1,7 @@ -package simphony.util.messages; - -public interface TaskMessageCallback { - - public void working(boolean working, String message); - -} +package simphony.util.messages; + +public interface TaskMessageCallback { + + public void working(boolean working, String message); + +} diff --git a/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessageListener.java b/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessageListener.java index 35eb78e..3a319b5 100644 --- a/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessageListener.java +++ b/festc_saf_core_runtime_temp/src/simphony/util/messages/TaskMessageListener.java @@ -1,20 +1,20 @@ -package simphony.util.messages; - -/** - * Abstract implementation of a MessageEventListener that listens for task - * messages. - */ -public abstract class TaskMessageListener implements MessageEventListener { - - public TaskMessageListener() { - - } - - protected abstract void processTaskMessage(TaskMessage message); - - public void messageReceived(MessageEvent arg0) { - if (arg0.getMessage() instanceof TaskMessage) { - processTaskMessage((TaskMessage) arg0.getMessage()); - } - } -} +package simphony.util.messages; + +/** + * Abstract implementation of a MessageEventListener that listens for task + * messages. + */ +public abstract class TaskMessageListener implements MessageEventListener { + + public TaskMessageListener() { + + } + + protected abstract void processTaskMessage(TaskMessage message); + + public void messageReceived(MessageEvent arg0) { + if (arg0.getMessage() instanceof TaskMessage) { + processTaskMessage((TaskMessage) arg0.getMessage()); + } + } +} diff --git a/festc_saf_ui/plugin.xml b/festc_saf_ui/plugin.xml index 1226991..72530a0 100644 --- a/festc_saf_ui/plugin.xml +++ b/festc_saf_ui/plugin.xml @@ -1,120 +1,120 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/festc_saf_ui/saf.ui.iml b/festc_saf_ui/saf.ui.iml index d031eb6..f020b77 100644 --- a/festc_saf_ui/saf.ui.iml +++ b/festc_saf_ui/saf.ui.iml @@ -1,84 +1,84 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/festc_saf_ui/src/saf/core/ui/DefaultDockingFactory.java b/festc_saf_ui/src/saf/core/ui/DefaultDockingFactory.java index 40c23e1..d0302f3 100644 --- a/festc_saf_ui/src/saf/core/ui/DefaultDockingFactory.java +++ b/festc_saf_ui/src/saf/core/ui/DefaultDockingFactory.java @@ -1,66 +1,66 @@ -package saf.core.ui; - -import saf.core.ui.dock.*; - -import java.util.List; -import java.util.ArrayList; - -/** - * Default implementation of docking factory that uses the Docking Frames - * library for its docking behavior. - * - * @author Nick Collier - */ -public class DefaultDockingFactory implements DockingFactory { - - private DockingManager vManager; - private DefaultSAFDisplay display; - - /** - * Gets the DockingManager. If the docking manager has not - * yet been created this should create one using the - * specified barManager and perspectives. - * - * @param barManager the bar manager - * @param perspectives list of user-defined perspectives - * @return the ViewManager. - */ - public DockingManager getViewManager(GUIBarManager barManager, List perspectives) { - if (vManager == null) { - DefaultSAFDisplay disp = (DefaultSAFDisplay) getDisplay(); - List defPs = new ArrayList(); - for (Perspective p : perspectives) { - defPs.add((DefaultPerspective) p); - } - - vManager = new DefaultDockingManager(barManager, disp.getCControl(), defPs); - } - return vManager; - } - - /** - * Gets the display. - * - * @return the display. - */ - public ISAFDisplay getDisplay() { - if (display == null) { - display = new DefaultSAFDisplay(); - } - return display; - } - - - /** - * Creates a Perspective. - * - * @param id the unique id of the perspective - * @param name the name of the perspective. - * - * @return the created Perspective. - */ - public Perspective createPerspective(String id, String name) { - if (display == null) getDisplay(); - return new DefaultPerspective(id, name, display.getCControl()); - } -} +package saf.core.ui; + +import saf.core.ui.dock.*; + +import java.util.List; +import java.util.ArrayList; + +/** + * Default implementation of docking factory that uses the Docking Frames + * library for its docking behavior. + * + * @author Nick Collier + */ +public class DefaultDockingFactory implements DockingFactory { + + private DockingManager vManager; + private DefaultSAFDisplay display; + + /** + * Gets the DockingManager. If the docking manager has not + * yet been created this should create one using the + * specified barManager and perspectives. + * + * @param barManager the bar manager + * @param perspectives list of user-defined perspectives + * @return the ViewManager. + */ + public DockingManager getViewManager(GUIBarManager barManager, List perspectives) { + if (vManager == null) { + DefaultSAFDisplay disp = (DefaultSAFDisplay) getDisplay(); + List defPs = new ArrayList(); + for (Perspective p : perspectives) { + defPs.add((DefaultPerspective) p); + } + + vManager = new DefaultDockingManager(barManager, disp.getCControl(), defPs); + } + return vManager; + } + + /** + * Gets the display. + * + * @return the display. + */ + public ISAFDisplay getDisplay() { + if (display == null) { + display = new DefaultSAFDisplay(); + } + return display; + } + + + /** + * Creates a Perspective. + * + * @param id the unique id of the perspective + * @param name the name of the perspective. + * + * @return the created Perspective. + */ + public Perspective createPerspective(String id, String name) { + if (display == null) getDisplay(); + return new DefaultPerspective(id, name, display.getCControl()); + } +} diff --git a/festc_saf_ui/src/saf/core/ui/MenuOrder.java b/festc_saf_ui/src/saf/core/ui/MenuOrder.java index e216907..de27195 100644 --- a/festc_saf_ui/src/saf/core/ui/MenuOrder.java +++ b/festc_saf_ui/src/saf/core/ui/MenuOrder.java @@ -1,144 +1,144 @@ -package saf.core.ui; - -import simphony.util.messages.MessageCenter; - -import javax.swing.*; -import java.util.*; - -/** - * Encapsulates the order in which items should appear in a - * menu. - * - * @author Nick Collier - */ -public class MenuOrder { - - private static final MessageCenter msg = MessageCenter.getMessageCenter(MenuOrder.class); - - private static final String ITEM_PREFIX = "menu.order."; - private static final String MENU_KEY = "menu.order"; - private static final String SEPARATOR = "__ZZ__SEPARATOR__ZZ__"; - - // key is menu id, value is ordered list of the item ids - private Map> items = new HashMap>(); - private List menus = new ArrayList(); - - public MenuOrder() { - } - - /** - * Creates a MenuItemOrder from the specified properties. - * - * @param props the properties to create the MenuItemOrder from - */ - public MenuOrder(Properties props) { - String order = props.getProperty(MENU_KEY, "").trim(); - - if (order.length() > 0) { - StringTokenizer tok = new StringTokenizer(order, ","); - while (tok.hasMoreTokens()) { - String id = tok.nextToken().trim(); - addMenu(id); - } - } - - Enumeration names = props.propertyNames(); - while (names.hasMoreElements()) { - String name = names.nextElement().toString(); - if (name.startsWith(ITEM_PREFIX)) { - parseMenu(name, props.getProperty(name)); - } - } - } - - private void parseMenu(String propName, String propValue) { - String menuID = propName.substring(ITEM_PREFIX.length(), propName.length()); - if (menuID.length() > 0) { - StringTokenizer tok = new StringTokenizer(propValue, ",:", true); - while (tok.hasMoreTokens()) { - String token = tok.nextToken().trim(); - if (token.equals(":")) { - addItem(menuID, SEPARATOR); - } else if (!token.equals(",")) { - addItem(menuID, token); - } - } - } - } - - /** - * Adds a menu. Menu ids should be added in the - * order which they should appear. - * - * @param menuID the id to add - */ - public void addMenu(String menuID) { - menus.add(menuID); - } - - /** - * Adds an item to this MenuItemOrder. Items ids - * should be added in the order in which they should - * appear in the menu. - * - * @param menuID the menu id - * @param itemID the item id - */ - public void addItem(String menuID, String itemID) { - List list = items.get(menuID); - if (list == null) { - list = new ArrayList(); - items.put(menuID, list); - } - list.add(itemID); - } - - /** - * Orders the menus in the manager according to this - * MenuItemOrder. - * - * @param manager the manager containing the menus. - * @param windowMenuLabel label for the window menu, can be "" - */ - public void orderItems(GUIBarManager manager, String windowMenuLabel) { - if (menus.indexOf(windowMenuLabel) != -1) { - manager.createWindowMenu(); - JMenu menu = manager.getMenu(GUIConstants.WINDOW_MENU_ID); - menu.setText(windowMenuLabel); - } - - if (menus.size() > 0) { - JMenuBar menuBar = manager.getMenuBar(); - menuBar.removeAll(); - for (String id : menus) { - JMenu menu = manager.getMenu(id); - if (menu == null) menu = manager.getMenuByLabel(id); - if (menu != null) { - menuBar.add(menu); - } else { - msg.warn("Error while ordering menus. Menu '" + id + "' not found."); - } - } - } - - for (String menuID : items.keySet()) { - JMenu menu = manager.getMenu(menuID); - if (menu == null) { - msg.warn("Error while ordering menus. Menu '" + menuID + "' not found."); - } else { - menu.removeAll(); - for (String id : items.get(menuID)) { - if (id.equals(SEPARATOR)) menu.addSeparator(); - else { - JMenuItem item = manager.getMenuItem(id); - if (item == null) { - msg.warn("Error while ordering menus. MenuItem '" + id + "' not found."); - } else { - menu.add(item); - } - } - } - } - } - } -} +package saf.core.ui; + +import simphony.util.messages.MessageCenter; + +import javax.swing.*; +import java.util.*; + +/** + * Encapsulates the order in which items should appear in a + * menu. + * + * @author Nick Collier + */ +public class MenuOrder { + + private static final MessageCenter msg = MessageCenter.getMessageCenter(MenuOrder.class); + + private static final String ITEM_PREFIX = "menu.order."; + private static final String MENU_KEY = "menu.order"; + private static final String SEPARATOR = "__ZZ__SEPARATOR__ZZ__"; + + // key is menu id, value is ordered list of the item ids + private Map> items = new HashMap>(); + private List menus = new ArrayList(); + + public MenuOrder() { + } + + /** + * Creates a MenuItemOrder from the specified properties. + * + * @param props the properties to create the MenuItemOrder from + */ + public MenuOrder(Properties props) { + String order = props.getProperty(MENU_KEY, "").trim(); + + if (order.length() > 0) { + StringTokenizer tok = new StringTokenizer(order, ","); + while (tok.hasMoreTokens()) { + String id = tok.nextToken().trim(); + addMenu(id); + } + } + + Enumeration names = props.propertyNames(); + while (names.hasMoreElements()) { + String name = names.nextElement().toString(); + if (name.startsWith(ITEM_PREFIX)) { + parseMenu(name, props.getProperty(name)); + } + } + } + + private void parseMenu(String propName, String propValue) { + String menuID = propName.substring(ITEM_PREFIX.length(), propName.length()); + if (menuID.length() > 0) { + StringTokenizer tok = new StringTokenizer(propValue, ",:", true); + while (tok.hasMoreTokens()) { + String token = tok.nextToken().trim(); + if (token.equals(":")) { + addItem(menuID, SEPARATOR); + } else if (!token.equals(",")) { + addItem(menuID, token); + } + } + } + } + + /** + * Adds a menu. Menu ids should be added in the + * order which they should appear. + * + * @param menuID the id to add + */ + public void addMenu(String menuID) { + menus.add(menuID); + } + + /** + * Adds an item to this MenuItemOrder. Items ids + * should be added in the order in which they should + * appear in the menu. + * + * @param menuID the menu id + * @param itemID the item id + */ + public void addItem(String menuID, String itemID) { + List list = items.get(menuID); + if (list == null) { + list = new ArrayList(); + items.put(menuID, list); + } + list.add(itemID); + } + + /** + * Orders the menus in the manager according to this + * MenuItemOrder. + * + * @param manager the manager containing the menus. + * @param windowMenuLabel label for the window menu, can be "" + */ + public void orderItems(GUIBarManager manager, String windowMenuLabel) { + if (menus.indexOf(windowMenuLabel) != -1) { + manager.createWindowMenu(); + JMenu menu = manager.getMenu(GUIConstants.WINDOW_MENU_ID); + menu.setText(windowMenuLabel); + } + + if (menus.size() > 0) { + JMenuBar menuBar = manager.getMenuBar(); + menuBar.removeAll(); + for (String id : menus) { + JMenu menu = manager.getMenu(id); + if (menu == null) menu = manager.getMenuByLabel(id); + if (menu != null) { + menuBar.add(menu); + } else { + msg.warn("Error while ordering menus. Menu '" + id + "' not found."); + } + } + } + + for (String menuID : items.keySet()) { + JMenu menu = manager.getMenu(menuID); + if (menu == null) { + msg.warn("Error while ordering menus. Menu '" + menuID + "' not found."); + } else { + menu.removeAll(); + for (String id : items.get(menuID)) { + if (id.equals(SEPARATOR)) menu.addSeparator(); + else { + JMenuItem item = manager.getMenuItem(id); + if (item == null) { + msg.warn("Error while ordering menus. MenuItem '" + id + "' not found."); + } else { + menu.add(item); + } + } + } + } + } + } +} diff --git a/festc_saf_ui/src/saf/core/ui/ToolBarOrder.java b/festc_saf_ui/src/saf/core/ui/ToolBarOrder.java index 868c339..ab60ce6 100644 --- a/festc_saf_ui/src/saf/core/ui/ToolBarOrder.java +++ b/festc_saf_ui/src/saf/core/ui/ToolBarOrder.java @@ -1,127 +1,127 @@ -package saf.core.ui; - -import javax.swing.*; -import java.util.*; - -/** - * Encapsulates the order in which actions should appear in a toolbar. - * - * @author Nick Collier - */ -public class ToolBarOrder { - - private static final String ORDER_PROP_NAME = "toolbar.group.order"; - private static final String A_ORDER_PROP_NAME = "toolbar.group.order."; - public static final String SEPARATOR = "__ZZ__SEPARATOR__ZZ__"; - - private List groupOrder = new ArrayList(); - private Map> actionOrder = new HashMap>(); - - public ToolBarOrder() { - } - - public ToolBarOrder(Properties props) { - String gOrder = props.getProperty(ORDER_PROP_NAME); - if (gOrder != null) parseGroupOrder(gOrder); - - - Enumeration names = props.propertyNames(); - while (names.hasMoreElements()) { - String name = names.nextElement().toString(); - parsePossibleActionOrder(name, props.getProperty(name)); - } - } - - private void parseGroupOrder(String gOrder) { - StringTokenizer tok = new StringTokenizer(gOrder, ",:", true); - while (tok.hasMoreTokens()) { - String id = tok.nextToken().trim(); - if (id.equals(":")) { - addSeparator(); - } else if (!id.equals(",")) { - addGroupID(id); - } - } - } - - private void parsePossibleActionOrder(String propName, String propValue) { - String groupName = parseGroupName(propName); - if (groupName != null) { - StringTokenizer tok = new StringTokenizer(propValue, ",", false); - while (tok.hasMoreTokens()) { - String id = tok.nextToken().trim(); - addActionID(groupName, id); - } - } - } - - /** - * Gets an iterable over the ordered list of groups. - * The order of iteration matches the defined order. - * - * @return an iterable over the ordered list of groups. - */ - public Iterable groupsInOrder() { - return groupOrder; - } - - /** - * Gets an iterable over the ordered list of actions. - * for the specified group. The order of iteration - * matches the defined order. - * - * @param groupID the id of the groups whose actions we want - * - * @return an iterable over the ordered list of groups. - */ - public Iterable actionsInOrder(String groupID) { - return actionOrder.get(groupID); - } - - /** - * Adds a group id to the ordered list of groups. These should - * be added sequentially in the order in which the - * toolbar groups should be displayed. - * - * @param id the group id to add - */ - public void addGroupID(String id) { - groupOrder.add(id); - } - - /** - * Adds a separator to the ordered list of groups. - * The separator will appear after the group given - * in the most recent call to addGroupID. - */ - public void addSeparator() { - groupOrder.add(SEPARATOR); - } - - - /** - * Adds the actionID to the order list of actions for the - * specified group. These should be add sequentially in the - * order in which the actions should appear in the specified - * group. - * - * @param groupID the group to whose list of actions the actionID is added - * @param actionID the id to add - */ - public void addActionID(String groupID, String actionID) { - List actions = actionOrder.get(groupID); - if (actions == null) { - actions = new ArrayList(); - actionOrder.put(groupID, actions); - } - actions.add(actionID); - } - - private String parseGroupName(String propName) { - propName = propName.trim(); - if (propName.startsWith(A_ORDER_PROP_NAME) && propName.length() > A_ORDER_PROP_NAME.length()) { - return propName.substring(A_ORDER_PROP_NAME.length(), propName.length()); - } - return null; - } -} +package saf.core.ui; + +import javax.swing.*; +import java.util.*; + +/** + * Encapsulates the order in which actions should appear in a toolbar. + * + * @author Nick Collier + */ +public class ToolBarOrder { + + private static final String ORDER_PROP_NAME = "toolbar.group.order"; + private static final String A_ORDER_PROP_NAME = "toolbar.group.order."; + public static final String SEPARATOR = "__ZZ__SEPARATOR__ZZ__"; + + private List groupOrder = new ArrayList(); + private Map> actionOrder = new HashMap>(); + + public ToolBarOrder() { + } + + public ToolBarOrder(Properties props) { + String gOrder = props.getProperty(ORDER_PROP_NAME); + if (gOrder != null) parseGroupOrder(gOrder); + + + Enumeration names = props.propertyNames(); + while (names.hasMoreElements()) { + String name = names.nextElement().toString(); + parsePossibleActionOrder(name, props.getProperty(name)); + } + } + + private void parseGroupOrder(String gOrder) { + StringTokenizer tok = new StringTokenizer(gOrder, ",:", true); + while (tok.hasMoreTokens()) { + String id = tok.nextToken().trim(); + if (id.equals(":")) { + addSeparator(); + } else if (!id.equals(",")) { + addGroupID(id); + } + } + } + + private void parsePossibleActionOrder(String propName, String propValue) { + String groupName = parseGroupName(propName); + if (groupName != null) { + StringTokenizer tok = new StringTokenizer(propValue, ",", false); + while (tok.hasMoreTokens()) { + String id = tok.nextToken().trim(); + addActionID(groupName, id); + } + } + } + + /** + * Gets an iterable over the ordered list of groups. + * The order of iteration matches the defined order. + * + * @return an iterable over the ordered list of groups. + */ + public Iterable groupsInOrder() { + return groupOrder; + } + + /** + * Gets an iterable over the ordered list of actions. + * for the specified group. The order of iteration + * matches the defined order. + * + * @param groupID the id of the groups whose actions we want + * + * @return an iterable over the ordered list of groups. + */ + public Iterable actionsInOrder(String groupID) { + return actionOrder.get(groupID); + } + + /** + * Adds a group id to the ordered list of groups. These should + * be added sequentially in the order in which the + * toolbar groups should be displayed. + * + * @param id the group id to add + */ + public void addGroupID(String id) { + groupOrder.add(id); + } + + /** + * Adds a separator to the ordered list of groups. + * The separator will appear after the group given + * in the most recent call to addGroupID. + */ + public void addSeparator() { + groupOrder.add(SEPARATOR); + } + + + /** + * Adds the actionID to the order list of actions for the + * specified group. These should be add sequentially in the + * order in which the actions should appear in the specified + * group. + * + * @param groupID the group to whose list of actions the actionID is added + * @param actionID the id to add + */ + public void addActionID(String groupID, String actionID) { + List actions = actionOrder.get(groupID); + if (actions == null) { + actions = new ArrayList(); + actionOrder.put(groupID, actions); + } + actions.add(actionID); + } + + private String parseGroupName(String propName) { + propName = propName.trim(); + if (propName.startsWith(A_ORDER_PROP_NAME) && propName.length() > A_ORDER_PROP_NAME.length()) { + return propName.substring(A_ORDER_PROP_NAME.length(), propName.length()); + } + return null; + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/AbstractGroup.java b/festc_saf_ui/src/saf/core/ui/dock/AbstractGroup.java index d34bfbe..64d8d8e 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/AbstractGroup.java +++ b/festc_saf_ui/src/saf/core/ui/dock/AbstractGroup.java @@ -1,85 +1,85 @@ -package saf.core.ui.dock; - -import java.util.ArrayList; -import java.util.List; - -import bibliothek.gui.dock.common.intern.DefaultCDockable; -import bibliothek.gui.dock.common.mode.ExtendedMode; - -/** - * Abstract implemention of Group. - * @author Nick Collier - * Date: Jul 10, 2008 4:42:12 PM - */ -public abstract class AbstractGroup implements Group { - - private String id; - private List dockables = new ArrayList(); - - public AbstractGroup(String id) { - this.id = id; - } - - /** - * Gets the first "normal" Dockable in this group, - * if any. - * - * @return the first "normal" Dockable in this group, - * if any. - */ - public DockableFrame getNormalDockable() { - for (DockableFrame frame : dockables) { - DefaultCDockable cDockable = ((DefaultDockableFrame)frame).getDockable(); - if (cDockable.getExtendedMode().equals(ExtendedMode.NORMALIZED)) return frame; - } - return null; - } - - /** - * Adds a dockable to this group. - * - * @param dockable the dockable to add - */ - public void add(DockableFrame dockable) { - dockables.add(dockable); - } - - /** - * Adds the dockables in this group to the specified list. - * - * @param frames the list to add to - * @return the new list - */ - public List addTo(List frames) { - frames.addAll(dockables); - return frames; - } - - /** - * Gets the dockables in this Group. - * - * @return the dockables in this Group. - */ - public List getDockables() { - return new ArrayList(dockables); - } - - /** - * Removes the specified dockable from this group. - * - * @param dockable the dockable to remove - * @return true if the the dockable was removed, otherwise false - */ - public boolean removeDockable(DockableFrame dockable) { - return dockables.remove(dockable); - } - - /** - * Gets the id of this Group. - * - * @return the id of this Group. - */ - public String getID() { - return id; - } -} +package saf.core.ui.dock; + +import java.util.ArrayList; +import java.util.List; + +import bibliothek.gui.dock.common.intern.DefaultCDockable; +import bibliothek.gui.dock.common.mode.ExtendedMode; + +/** + * Abstract implemention of Group. + * @author Nick Collier + * Date: Jul 10, 2008 4:42:12 PM + */ +public abstract class AbstractGroup implements Group { + + private String id; + private List dockables = new ArrayList(); + + public AbstractGroup(String id) { + this.id = id; + } + + /** + * Gets the first "normal" Dockable in this group, + * if any. + * + * @return the first "normal" Dockable in this group, + * if any. + */ + public DockableFrame getNormalDockable() { + for (DockableFrame frame : dockables) { + DefaultCDockable cDockable = ((DefaultDockableFrame)frame).getDockable(); + if (cDockable.getExtendedMode().equals(ExtendedMode.NORMALIZED)) return frame; + } + return null; + } + + /** + * Adds a dockable to this group. + * + * @param dockable the dockable to add + */ + public void add(DockableFrame dockable) { + dockables.add(dockable); + } + + /** + * Adds the dockables in this group to the specified list. + * + * @param frames the list to add to + * @return the new list + */ + public List addTo(List frames) { + frames.addAll(dockables); + return frames; + } + + /** + * Gets the dockables in this Group. + * + * @return the dockables in this Group. + */ + public List getDockables() { + return new ArrayList(dockables); + } + + /** + * Removes the specified dockable from this group. + * + * @param dockable the dockable to remove + * @return true if the the dockable was removed, otherwise false + */ + public boolean removeDockable(DockableFrame dockable) { + return dockables.remove(dockable); + } + + /** + * Gets the id of this Group. + * + * @return the id of this Group. + */ + public String getID() { + return id; + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/ActivationCommand.java b/festc_saf_ui/src/saf/core/ui/dock/ActivationCommand.java index 382c08f..c11397c 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/ActivationCommand.java +++ b/festc_saf_ui/src/saf/core/ui/dock/ActivationCommand.java @@ -1,14 +1,14 @@ -package saf.core.ui.dock; - -/** - * Interface for commands that activate a perspective. - * - * @author Nick Collier - */ -public interface ActivationCommand { - - /** - * Performs the activation. - */ - void activate(); -} +package saf.core.ui.dock; + +/** + * Interface for commands that activate a perspective. + * + * @author Nick Collier + */ +public interface ActivationCommand { + + /** + * Performs the activation. + */ + void activate(); +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/DefaultDockableFrame.java b/festc_saf_ui/src/saf/core/ui/dock/DefaultDockableFrame.java index 0db27bf..ee83c45 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/DefaultDockableFrame.java +++ b/festc_saf_ui/src/saf/core/ui/dock/DefaultDockableFrame.java @@ -1,234 +1,234 @@ -package saf.core.ui.dock; - - -import java.awt.BorderLayout; -import java.awt.GridLayout; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JToolBar; - -import bibliothek.gui.dock.common.DefaultSingleCDockable; -import bibliothek.gui.dock.common.intern.DefaultCDockable; -import bibliothek.gui.dock.common.mode.ExtendedMode; - -/** - * Default implementation of a dockable frame delegating to - * a Docking Frames' CDockable. - * - * @author Nick Collier - */ -public class DefaultDockableFrame implements DockableFrame { - - private DefaultCDockable dockable; - private StateChanger changer; - private String id; - private JPanel panel, contentPane; - private JToolBar bar; - - // client property map - private Map propMap = new HashMap(); - - /** - * Creates a DefaultDockingFrame that will display - * the specified component. This will create a DefaultSingleCDockable - * and adapt that the DockableFrame interface. - * - * @param id this DefaultDockableFrame's unique id. - * @param comp the component to display in this frame - * @param changer the StateChanger to use when changing the - * dockable's state - */ - public DefaultDockableFrame(String id, JComponent comp, StateChanger changer) { - this.changer = changer; - this.id = id; - panel = new JPanel(new BorderLayout()); - contentPane = new JPanel(new GridLayout(1, 1)); - contentPane.add(comp); - panel.add(contentPane, BorderLayout.CENTER); - dockable = new DefaultSingleCDockable(id, panel); - } - - /** - * Gets the panel that contains the component - * displayed in this frame. By default this component - * can be retrieved by calling getComponent(0) on the - * returned panel.

- * - * Note that this panel should not contain the toolbar. - * - * @return the panel that contains the component - * displayed in this frame. - */ - public JPanel getContentPane() { - return contentPane; - } - - /** - * Adds a toolbar to this frame. - * - * @param bar the toolbar to add - */ - public void addToolBar(JToolBar bar) { - this.bar = bar; - panel.add(bar, BorderLayout.NORTH); - } - - /** - * Gets the toolbar, if any, for this frame. - * - * @return the toolbar for this frame if one exists, otherwise null. - */ - public JToolBar getToolBar() { - return bar; - } - - /** - * Gets the wrapped DefaultCDockable. - * - * @return the wrapped DefaultCDockable. - */ - protected DefaultCDockable getDockable() { - return dockable; - } - - - /** - * Gets whether or not this DockableFrame is minimized. - * - * @return true if this DockableFrame is minimized, otherwise false. - */ - public boolean isMinimized() { - return dockable.getExtendedMode().equals(ExtendedMode.MINIMIZED); - } - - /** - * Gets whether or not this DockableFrame is maximized. - * - * @return true if this DockableFrame is maximized, otherwise false. - */ - public boolean isMaximized() { - return dockable.getExtendedMode().equals(ExtendedMode.MAXIMIZED); - } - - /** - * Gets whether or not this DockableFrame is floating. - * - * @return true if this DockableFrame is floating, otherwise false. - */ - public boolean isFloating() { - return dockable.getExtendedMode().equals(ExtendedMode.EXTERNALIZED); - } - - /** - * Gets the unique id for this DockableFrame. - * - * @return the unique id for this DockableFrame. - */ - public String getID() { - return id; - } - - /** - * Gets the title text for this DockableFrame. - * - * @return the title text for this DockableFrame. - */ - public String getTitle() { - return dockable.getTitleText(); - } - - /** - * Sets the title text for this DockableFrame. - * - * @param title the title text for this DockableFrame. - */ - - public void setToolTip(String title) { - dockable.intern().setTitleToolTip(title); - } - - public void setTitle(String title) { - dockable.intern().setTitleText(title); - } - - /** - * Floats this DockableFrame. - */ - public void doFloat() { - if (!isFloating()) changer.floatDockable(dockable); - } - - /** - * Close this dockable. Assumes the dockable is - * in the current perspective. - */ - public void close() { - changer.closeDockable(dockable); - } - - /** - * Closes this dockable in the specified perspective. - * - * @param perspectiveID the id of the perspective to close - * the dockable in. - */ - public void close(String perspectiveID) { - changer.closeDockable(perspectiveID, dockable); - } - - /** - * Maximizes this DockableFrame. - */ - public void maximize() { - changer.maximizeDockable(dockable); - } - - /** - * Minimizes this DockableFrame. - * - * @param location the location to minimize to - */ - public void minimize(DockingManager.MinimizeLocation location) { - changer.minimizeDockable(dockable, location); - } - - /** - * Restores this DockableFrame. - */ - public void restore() { - changer.restoreDockable(dockable); - } - - /** - * Selects this DockableFrame. - */ - public void toFront() { - changer.fixFocusPolicy(this); - dockable.toFront(); - } - - /** - * Returns the value of the property with the specified key. - * Only properties added with putClientProperty will return a non-null value. - * - * @param key the property key whose value should be returned. - * @return the value of the property with the specified key. - */ - public Object getClientProperty(Object key) { - return propMap.get(key); - } - - /** - * Adds an arbitrary key/value "client property" to this component. - * - * @param key the new client property key - * @param value the new client property value; if this is null the property will be removed - */ - public void putClientProperty(Object key, Object value) { - if (value == null) propMap.remove(key); - else propMap.put(key, value); - } -} +package saf.core.ui.dock; + + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JToolBar; + +import bibliothek.gui.dock.common.DefaultSingleCDockable; +import bibliothek.gui.dock.common.intern.DefaultCDockable; +import bibliothek.gui.dock.common.mode.ExtendedMode; + +/** + * Default implementation of a dockable frame delegating to + * a Docking Frames' CDockable. + * + * @author Nick Collier + */ +public class DefaultDockableFrame implements DockableFrame { + + private DefaultCDockable dockable; + private StateChanger changer; + private String id; + private JPanel panel, contentPane; + private JToolBar bar; + + // client property map + private Map propMap = new HashMap(); + + /** + * Creates a DefaultDockingFrame that will display + * the specified component. This will create a DefaultSingleCDockable + * and adapt that the DockableFrame interface. + * + * @param id this DefaultDockableFrame's unique id. + * @param comp the component to display in this frame + * @param changer the StateChanger to use when changing the + * dockable's state + */ + public DefaultDockableFrame(String id, JComponent comp, StateChanger changer) { + this.changer = changer; + this.id = id; + panel = new JPanel(new BorderLayout()); + contentPane = new JPanel(new GridLayout(1, 1)); + contentPane.add(comp); + panel.add(contentPane, BorderLayout.CENTER); + dockable = new DefaultSingleCDockable(id, panel); + } + + /** + * Gets the panel that contains the component + * displayed in this frame. By default this component + * can be retrieved by calling getComponent(0) on the + * returned panel.

+ * + * Note that this panel should not contain the toolbar. + * + * @return the panel that contains the component + * displayed in this frame. + */ + public JPanel getContentPane() { + return contentPane; + } + + /** + * Adds a toolbar to this frame. + * + * @param bar the toolbar to add + */ + public void addToolBar(JToolBar bar) { + this.bar = bar; + panel.add(bar, BorderLayout.NORTH); + } + + /** + * Gets the toolbar, if any, for this frame. + * + * @return the toolbar for this frame if one exists, otherwise null. + */ + public JToolBar getToolBar() { + return bar; + } + + /** + * Gets the wrapped DefaultCDockable. + * + * @return the wrapped DefaultCDockable. + */ + protected DefaultCDockable getDockable() { + return dockable; + } + + + /** + * Gets whether or not this DockableFrame is minimized. + * + * @return true if this DockableFrame is minimized, otherwise false. + */ + public boolean isMinimized() { + return dockable.getExtendedMode().equals(ExtendedMode.MINIMIZED); + } + + /** + * Gets whether or not this DockableFrame is maximized. + * + * @return true if this DockableFrame is maximized, otherwise false. + */ + public boolean isMaximized() { + return dockable.getExtendedMode().equals(ExtendedMode.MAXIMIZED); + } + + /** + * Gets whether or not this DockableFrame is floating. + * + * @return true if this DockableFrame is floating, otherwise false. + */ + public boolean isFloating() { + return dockable.getExtendedMode().equals(ExtendedMode.EXTERNALIZED); + } + + /** + * Gets the unique id for this DockableFrame. + * + * @return the unique id for this DockableFrame. + */ + public String getID() { + return id; + } + + /** + * Gets the title text for this DockableFrame. + * + * @return the title text for this DockableFrame. + */ + public String getTitle() { + return dockable.getTitleText(); + } + + /** + * Sets the title text for this DockableFrame. + * + * @param title the title text for this DockableFrame. + */ + + public void setToolTip(String title) { + dockable.intern().setTitleToolTip(title); + } + + public void setTitle(String title) { + dockable.intern().setTitleText(title); + } + + /** + * Floats this DockableFrame. + */ + public void doFloat() { + if (!isFloating()) changer.floatDockable(dockable); + } + + /** + * Close this dockable. Assumes the dockable is + * in the current perspective. + */ + public void close() { + changer.closeDockable(dockable); + } + + /** + * Closes this dockable in the specified perspective. + * + * @param perspectiveID the id of the perspective to close + * the dockable in. + */ + public void close(String perspectiveID) { + changer.closeDockable(perspectiveID, dockable); + } + + /** + * Maximizes this DockableFrame. + */ + public void maximize() { + changer.maximizeDockable(dockable); + } + + /** + * Minimizes this DockableFrame. + * + * @param location the location to minimize to + */ + public void minimize(DockingManager.MinimizeLocation location) { + changer.minimizeDockable(dockable, location); + } + + /** + * Restores this DockableFrame. + */ + public void restore() { + changer.restoreDockable(dockable); + } + + /** + * Selects this DockableFrame. + */ + public void toFront() { + changer.fixFocusPolicy(this); + dockable.toFront(); + } + + /** + * Returns the value of the property with the specified key. + * Only properties added with putClientProperty will return a non-null value. + * + * @param key the property key whose value should be returned. + * @return the value of the property with the specified key. + */ + public Object getClientProperty(Object key) { + return propMap.get(key); + } + + /** + * Adds an arbitrary key/value "client property" to this component. + * + * @param key the new client property key + * @param value the new client property value; if this is null the property will be removed + */ + public void putClientProperty(Object key, Object value) { + if (value == null) propMap.remove(key); + else propMap.put(key, value); + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/DefaultPerspective.java b/festc_saf_ui/src/saf/core/ui/dock/DefaultPerspective.java index b7daaa2..b18140e 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/DefaultPerspective.java +++ b/festc_saf_ui/src/saf/core/ui/dock/DefaultPerspective.java @@ -1,735 +1,735 @@ -package saf.core.ui.dock; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.prefs.Preferences; - -import org.apache.logging.log4j.LogManager; // 2014 -import org.apache.logging.log4j.Logger; // 2014 replacing System.out.println with logger messages - -import saf.core.ui.AppPreferences; -import simphony.util.messages.MessageCenter; -import bibliothek.gui.DockStation; -import bibliothek.gui.Dockable; -import bibliothek.gui.dock.common.CControl; -import bibliothek.gui.dock.common.CLocation; -import bibliothek.gui.dock.common.CStation; -import bibliothek.gui.dock.common.CWorkingArea; -import bibliothek.gui.dock.common.SingleCDockable; -import bibliothek.gui.dock.common.intern.CDockable; -import bibliothek.gui.dock.common.intern.DefaultCDockable; -import bibliothek.gui.dock.common.location.AbstractTreeLocation; -import bibliothek.gui.dock.common.location.CBaseLocation; -import bibliothek.gui.dock.common.location.CStackLocation; -import bibliothek.gui.dock.common.mode.ExtendedMode; -import bibliothek.util.xml.XElement; -import bibliothek.util.xml.XIO; - -/** - * Default implementation of a perspective. This uses the DockingFrames library - * for docking. - * - * @author Nick Collier - */ -public class DefaultPerspective implements Perspective { - static final Logger Logger = LogManager.getLogger(DefaultPerspective.class.getName()); - - static MessageCenter msg = MessageCenter.getMessageCenter(Perspective.class); - - private String name; - - private String id; - private CControl control; - private GroupPathCreator pathCreator = new GroupPathCreator(); - private CWorkingArea workingArea; - // key is group id - private Map groupData = new HashMap(); - private String rootGroupID; - private List activations = new ArrayList(); - private boolean isActive = false, initialized = false; - private CDockable selectedDockable; - private File layoutFile = null; - - private XElement savedLayout; - - /** - * Creates a DefaultPerspective. - * - * @param name - * the name of the perspective - * @param id - * the unique id of the perspective - * @param control - * the CControl used for the docking of the frame's within the - * perspective - */ - public DefaultPerspective(String id, String name, CControl control) { - this.name = name; - this.id = id; - this.control = control; - } - - private void initializeGroupData() { - groupData.put(rootGroupID, new RootGroup(rootGroupID)); - List locPaths = pathCreator.createPaths(rootGroupID); - for (GroupLocationPath path : locPaths) { - groupData.put(path.getId(), new NonRootGroup(path.getId(), path)); - } - } - - /** - * Gets whether or not this Perspective is the active perspective. - * - * @return true if this perspective is active, otherwise false. - */ - public boolean isActive() { - return isActive; - } - - /** - * Adds the specified DockableFrame into the specified group. - * - * @param groupId - * the id of the group - * @param dockable - * the DockableFrame to add - * @param show - * whether or not to display the frame - */ - public void addDockableFrame(String groupId, DockableFrame dockable, boolean show) { - Logger.debug("in DefaultPerspective.addDockableFrame, groupData.size() = " + groupData.size()); - if (groupData.size() == 0) - { - initializeGroupData(); - Logger.debug("just called initializeGroupData"); - } - - Group data = groupData.get(groupId); - if (data == null) { - msg.error("Error adding dockable: Group '" + groupId + "' does not exist.", - new IllegalArgumentException("Group does not exist")); - return; - } - Logger.debug("data was not null, continuing by instantiating DockableActivation"); - DockableActivation activation = new DockableActivation(dockable, data); - if (workingArea != null) { - Logger.debug("workingArea was not null, continuing by calling activation.activate()"); - activation.activate(); - Logger.debug("back from activate, ready to call .getDockable().toFront()"); - ((DefaultDockableFrame) dockable).getDockable().toFront(); - Logger.debug("done with that, now ready to return from member function addDockableFrame"); - } else - { - Logger.debug("workingArea was null, so into else: call activations.add(activation)"); - activations.add(activation); - Logger.debug("done with add, returning from member function addDockableFrame"); - } - } - - /** - * Attempts to dock the specified dockable to the target, stacking the - * dockable on top of the target. This will do nothing if the target is - * minimized or the dockable has not been added to a group. - * - * @param dockable - * the dockable to dock - * @param target - * the target to dock to - */ - public void dock(DockableFrame dockable, DockableFrame target) { - StackActivation activation = new StackActivation(dockable, target); - if (isActive) - activation.activate(); - else - activations.add(activation); - } - - /** - * Attempts to dock the specified dockable in some location relative to - * another dockable. This will not work if relativeTo is minimized or - * maximized, or if the dockable hasn't been added to a group yet. - * - * @param dockable - * the dockable to dock - * @param relativeTo - * the dockable to dock relative to - * @param location - * the relative location - * @param fillPercent - * the fill percent that the dockable should take up - */ - public void dock(DockableFrame dockable, DockableFrame relativeTo, Location location, - float fillPercent) { - DockingActivation activation = new DockingActivation(dockable, relativeTo, location, - fillPercent); - if (isActive) - activation.activate(); - else - activations.add(activation); - } - - /** - * Creates group with the specified parameters. - * - * @param id - * the id of the group - * @param location - * the location of the group - * @param relativeTo - * the id of the parent of the created group - * @param fillPercentage - * the fill percentage of the created group. - */ - public void createGroup(String id, Location location, String relativeTo, float fillPercentage) { - pathCreator.definePath(id, location, relativeTo, fillPercentage); - } - - /** - * Creates the root or main group of this Perspective. The root group will - * have the specified id. - * - * @param id - * the id of the root group - */ - public void createRootGroup(String id) { - rootGroupID = id; - activations.add(0, new WorkingAreaActivation(id)); - } - - /** - * Activates this Perspective. - */ - public void activate() { - if (!isActive) { - isActive = true; - savedLayout = null; - - if (groupData.size() == 0) - initializeGroupData(); - - for (DockableCommand command : activations) { - command.activate(); - } - - // load the stored layout - if (!initialized && layoutFile != null) { - reset(layoutFile); - layoutFile = null; - } - - activations.clear(); - initialized = true; - } - } - - /** - * Resets the layout from a layout stored in a file. - * - * @param file the file to reset the layout from. - */ - public boolean reset(File file) { - try { - return reset(new FileInputStream(file)); - } catch (FileNotFoundException ex) { - msg.error("Error reseting layout from file", ex); - return false; - } - } - - /** - * Resets the layout from a layout stored in a stream. - * - * @param stream the stream to reset the layout from. - */ - public boolean reset(InputStream stream) { - boolean success = false; - try { - // System.out.printf("Reading: %s%n", file.getAbsolutePath()); - BufferedInputStream in = new BufferedInputStream(stream); - XElement element = XIO.readUTF(in); - in.close(); - control.readXML(element); - } catch (Exception ex) { - control.delete(id); - msg.warn("Error reading saved layout for perspective '" + id + "'", ex); - return false; - } - - try { - control.load(id); - - // this is to insure that any dockables that are not - // part of the loaded layout, but should be added to - // the perspective, are made visible. - for (int i = 0, n = control.getCDockableCount(); i < n; i++) { - CDockable dockable = control.getCDockable(i); - if (!dockable.isVisible()) { - dockable.setVisible(true); - dockable.setExtendedMode(ExtendedMode.NORMALIZED); - } - } - success = true; - } catch (Exception ex) { - control.delete(id); - msg.warn("Error loading layout for perspective '" + id + "'", ex); - } - - return success; - } - - private CDockable findSelectedDockable() { - // we do this because the selected dockable may not correspond - // to a DockableFrame. - Dockable dockable = control.intern().getController().getFocusedDockable(); - for (DockableFrame frame : getDockables()) { - DefaultCDockable cDockable = ((DefaultDockableFrame) frame).getDockable(); - if (cDockable.intern().equals(dockable)) - return cDockable; - } - - return null; - } - - /** - * Deactivates this Perspective. - */ - public void deactivate() { - if (isActive) { - isActive = false; - selectedDockable = findSelectedDockable(); - - WorkingAreaActivation waActivation = new WorkingAreaActivation(rootGroupID); - activations.add(waActivation); - - for (Group group : groupData.values()) { - for (DockableFrame frame : group.getDockables()) { - DefaultCDockable dockable = ((DefaultDockableFrame) frame).getDockable(); - activations.add(new AddActivation(frame, group, dockable.getExtendedMode())); - } - } - - // work-around for bug in dockingFrames where floating dockables - // don't save - normalizeExtDockables(); - control.save(id); - savedLayout = new XElement("root"); - control.writeXML(savedLayout); - // this activation needs to occur before the - // the select activation so selections that - // occur during the layout are not the final - // selections - activations.add(new LayoutActivation()); - - for (DockableFrame frame : groupData.get(rootGroupID).getDockables()) { - activations.add(new ModeSetActivation(frame)); - } - - for (DockableFrame frame : getDockables()) { - DefaultCDockable dockable = ((DefaultDockableFrame) frame).getDockable(); - control.remove((SingleCDockable) dockable); - } - - if (selectedDockable != null) - activations.add(new SelectActivation()); - - control.remove((SingleCDockable) workingArea); - control.remove((CStation) workingArea); - workingArea = null; - } - } - - /** - * Gets all the DockableFrames currently in this perspective. - * - * @return all the DockableFrames currently in this perspective. - */ - public List getDockables() { - List dockables = new ArrayList(); - for (Group data : groupData.values()) { - dockables = data.addTo(dockables); - } - - return dockables; - } - - /** - * Gets all the DockableFrames in the specified group. - * - * @param groupID - * the id of the group whose dockables should be returned - * @return all the DockableFrames in the specified group. - */ - public Set getDockables(String groupID) { - Group data = groupData.get(groupID); - if (data == null) { - msg.error("Error getting dockables for group: Group '" + groupID + "does not exist.", - new IllegalArgumentException("Group does not exist")); - return null; - } - - return new HashSet(data.getDockables()); - } - - /** - * Gets the ids of all the groups in this Perspective. - * - * @return the ids of all the groups in this Perspective. - */ - public Set getGroupIDs() { - return new HashSet(groupData.keySet()); - } - - /** - * Gets the id of this Perspective. - * - * @return the id of this Perspective. - */ - public String getID() { - return id; - } - - /** - * Gets the name of this Perspective. - * - * @return the name of this Perspective. - */ - public String getName() { - return name; - } - - /** - * Loads a layout. Depending on whether this Perspective uses the Preferences - * to store the layout, the prefs object may contain the layout data. - * - * @param prefs - * repository of the layout data - */ - public void loadLayout(Preferences prefs) { - File file = createFileName(prefs, false); - if (file.exists()) { - layoutFile = file; - } else { - // use the default layout if one exists - file = new File(System.getProperty("applicationRoot") + "/props", "default_" + id + ".layout"); - if (file.exists()) - layoutFile = file; - } - } - - private File createFileName(Preferences prefs, boolean mkdir) { - String path = prefs.get(AppPreferences.SAVE_PATH_KEY, "").trim(); - File file; - if (path.length() == 0) { - String home = System.getProperty("user.home"); - file = new File(home + "/." + prefs.name() + "/"); - } else { - file = new File(path); - } - if (mkdir && !file.exists()) - file.mkdirs(); - return new File(file, id + ".layout"); - } - - /* - * Normalizes any externalized dockables - */ - private void normalizeExtDockables() { - for (DockableFrame frame : getDockables()) { - if (frame.isFloating()) - frame.restore(); - } - } - - /** - * Saves the frame layout. - * - * @param prefs - * optional preferences repository where the layout can be saved - */ - public void saveLayout(Preferences prefs) { - // the perspective may have never been - // activated so there may not be any layout info for it - File file = createFileName(prefs, true); - saveLayout(file); - } - - /* (non-Javadoc) - * @see saf.core.ui.dock.Perspective#saveLayout(java.io.File) - */ - @Override - public void saveLayout(File file) { - if (initialized) { - // only save if active otherwise save the setting - // the control saved in deactivate - if (isActive) { - normalizeExtDockables(); - control.save(id); - } - try { - if (savedLayout == null) - control.writeXML(file); - else { - // write the layout that was saved to an XElement on deactivation - BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); - XIO.writeUTF(savedLayout, out); - out.close(); - } - // control.intern().write(new DataOutputStream(new - // FileOutputStream(file))); - } catch (IOException ex) { - msg.warn("Error while saving layout for perspective '" + id + "'", ex); - } - } - } - - /** - * Removes the specified dockable from this Perspective. - * - * @param dockable - * the dockable to remove - */ - public void removeDockable(DockableFrame dockable) { - if (isActive) { - for (Group group : groupData.values()) { - if (group.removeDockable(dockable)) - break; - } - control.remove((SingleCDockable) ((DefaultDockableFrame) dockable).getDockable()); - } else { - for (Iterator iter = activations.iterator(); iter.hasNext();) { - DockableCommand act = iter.next(); - if (act.getSubjects().contains(dockable)) - iter.remove(); - } - } - if (selectedDockable != null - && ((DefaultDockableFrame) dockable).getDockable().equals(selectedDockable)) - selectedDockable = null; - } - - private DockableFrame findFrame(CDockable cDockable) { - if (cDockable != null) { - for (DockableFrame frame : getDockables()) { - DefaultCDockable dockable = ((DefaultDockableFrame) frame).getDockable(); - if (dockable.equals(cDockable)) - return frame; - } - } - - return null; - - } - - class LayoutActivation implements DockableCommand { - - public void activate() { - control.load(id); - } - - public List getSubjects() { - return new ArrayList(); - } - } - - class SelectActivation implements DockableCommand { - - public void activate() { - DockableFrame frame = findFrame(selectedDockable); - if (frame != null) - frame.toFront(); - } - - public List getSubjects() { - DockableFrame frame = findFrame(selectedDockable); - if (frame != null) - return DockUtilities.createList(frame); - return new ArrayList(); - } - } - - class WorkingAreaActivation implements DockableCommand { - - private String id; - - WorkingAreaActivation(String id) { - this.id = id; - } - - public void activate() { - workingArea = control.createWorkingArea(id); - workingArea.setLocation(CLocation.base().normalRectangle(0, 0, 1, 1)); - ((RootGroup) groupData.get(id)).initWorkingArea(workingArea); - workingArea.setVisible(true); - } - - public List getSubjects() { - return new ArrayList(); - } - } - - class DockableActivation implements DockableCommand { - - DockableFrame dockable; - Group data; - - DockableActivation(DockableFrame dockable, Group data) { - this.dockable = dockable; - this.data = data; - } - - public void activate() { - DefaultCDockable cDockable = ((DefaultDockableFrame) dockable).getDockable(); - CLocation location; - DockableFrame other = data.getNormalDockable(); - if (other == null) - location = data.getLocation(); - else - location = ((DefaultDockableFrame) other).getDockable().getBaseLocation(); - cDockable.setLocation(location); - data.add(dockable); - if (data.getID().equals(rootGroupID)) { - workingArea.add((SingleCDockable) cDockable); - } else { - control.add((SingleCDockable) cDockable); - } - cDockable.setVisible(true); - } - - public List getSubjects() { - return DockUtilities.createList(dockable); - } - } - - class StackActivation implements DockableCommand { - - DockableFrame dockable, target; - - StackActivation(DockableFrame dockable, DockableFrame target) { - this.dockable = dockable; - this.target = target; - } - - public void activate() { - if (!target.isMinimized() && getDockables().contains(dockable)) { - DefaultCDockable cTarget = ((DefaultDockableFrame) target).getDockable(); - CLocation location = cTarget.getBaseLocation(); - DefaultCDockable cDockable = ((DefaultDockableFrame) dockable).getDockable(); - cDockable.setLocation(location); - } - } - - public List getSubjects() { - return DockUtilities.createList(dockable, target); - } - } - - // re-adds dockables - class AddActivation implements DockableCommand { - DockableFrame dockable; - ExtendedMode mode; - Group data; - - AddActivation(DockableFrame dockable, Group data, ExtendedMode mode) { - this.dockable = dockable; - this.mode = mode; - this.data = data; - } - - public void activate() { - DefaultCDockable cDockable = ((DefaultDockableFrame) dockable).getDockable(); - if (data.getID().equals(rootGroupID)) { - workingArea.add((SingleCDockable) cDockable); - } else { - control.add((SingleCDockable) cDockable); - } - cDockable.setExtendedMode(mode); - cDockable.setVisible(true); - } - - public List getSubjects() { - return DockUtilities.createList(dockable); - } - } - - class DockingActivation implements DockableCommand { - - DockableFrame dockable, target; - Location location; - float fill; - - DockingActivation(DockableFrame dockable, DockableFrame target, Location location, float fill) { - this.dockable = dockable; - this.target = target; - this.location = location; - this.fill = fill; - } - - public void activate() { - if (!(target.isMinimized() || target.isMaximized()) && getDockables().contains(dockable)) { - CLocation rLocation = ((DefaultDockableFrame) target).getDockable().getBaseLocation(); - if (rLocation instanceof AbstractTreeLocation) { - AbstractTreeLocation treeLoc = (AbstractTreeLocation) rLocation; - ((DefaultDockableFrame) dockable).getDockable().setLocation( - location.createPath(treeLoc, fill)); - - } else if (rLocation instanceof CBaseLocation) { - CBaseLocation baseLoc = (CBaseLocation) rLocation; - ((DefaultDockableFrame) dockable).getDockable().setLocation( - location.createPath(baseLoc, fill)); - } else if (rLocation instanceof CStackLocation) { - DefaultCDockable parent = ((DefaultDockableFrame) target).getDockable(); - DockStation parentStation = parent.intern().getDockParent(); - CLocation stationLoc = control.getLocationManager().getLocation( - parentStation.asDockable()); - if (stationLoc != null) { - ((DefaultDockableFrame) dockable).getDockable().setLocation( - location.createPath((AbstractTreeLocation) stationLoc, fill)); - } - } - } - } - - public List getSubjects() { - return DockUtilities.createList(dockable, target); - } - } - - // this is necessary because the working area frames - // don't seem to respect their location / mode when re-laid out - class ModeSetActivation implements DockableCommand { - - CDockable dockable; - ExtendedMode mode; - CLocation location; - - ModeSetActivation(DockableFrame frame) { - dockable = ((DefaultDockableFrame) frame).getDockable(); - this.mode = dockable.getExtendedMode(); - this.location = dockable.getBaseLocation(); - } - - public void activate() { - dockable.setExtendedMode(mode); - dockable.setLocation(location); - } - - public List getSubjects() { - DockableFrame frame = findFrame(dockable); - return DockUtilities.createList(frame); - } - - } -} +package saf.core.ui.dock; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.prefs.Preferences; + +import org.apache.logging.log4j.LogManager; // 2014 +import org.apache.logging.log4j.Logger; // 2014 replacing System.out.println with logger messages + +import saf.core.ui.AppPreferences; +import simphony.util.messages.MessageCenter; +import bibliothek.gui.DockStation; +import bibliothek.gui.Dockable; +import bibliothek.gui.dock.common.CControl; +import bibliothek.gui.dock.common.CLocation; +import bibliothek.gui.dock.common.CStation; +import bibliothek.gui.dock.common.CWorkingArea; +import bibliothek.gui.dock.common.SingleCDockable; +import bibliothek.gui.dock.common.intern.CDockable; +import bibliothek.gui.dock.common.intern.DefaultCDockable; +import bibliothek.gui.dock.common.location.AbstractTreeLocation; +import bibliothek.gui.dock.common.location.CBaseLocation; +import bibliothek.gui.dock.common.location.CStackLocation; +import bibliothek.gui.dock.common.mode.ExtendedMode; +import bibliothek.util.xml.XElement; +import bibliothek.util.xml.XIO; + +/** + * Default implementation of a perspective. This uses the DockingFrames library + * for docking. + * + * @author Nick Collier + */ +public class DefaultPerspective implements Perspective { + static final Logger Logger = LogManager.getLogger(DefaultPerspective.class.getName()); + + static MessageCenter msg = MessageCenter.getMessageCenter(Perspective.class); + + private String name; + + private String id; + private CControl control; + private GroupPathCreator pathCreator = new GroupPathCreator(); + private CWorkingArea workingArea; + // key is group id + private Map groupData = new HashMap(); + private String rootGroupID; + private List activations = new ArrayList(); + private boolean isActive = false, initialized = false; + private CDockable selectedDockable; + private File layoutFile = null; + + private XElement savedLayout; + + /** + * Creates a DefaultPerspective. + * + * @param name + * the name of the perspective + * @param id + * the unique id of the perspective + * @param control + * the CControl used for the docking of the frame's within the + * perspective + */ + public DefaultPerspective(String id, String name, CControl control) { + this.name = name; + this.id = id; + this.control = control; + } + + private void initializeGroupData() { + groupData.put(rootGroupID, new RootGroup(rootGroupID)); + List locPaths = pathCreator.createPaths(rootGroupID); + for (GroupLocationPath path : locPaths) { + groupData.put(path.getId(), new NonRootGroup(path.getId(), path)); + } + } + + /** + * Gets whether or not this Perspective is the active perspective. + * + * @return true if this perspective is active, otherwise false. + */ + public boolean isActive() { + return isActive; + } + + /** + * Adds the specified DockableFrame into the specified group. + * + * @param groupId + * the id of the group + * @param dockable + * the DockableFrame to add + * @param show + * whether or not to display the frame + */ + public void addDockableFrame(String groupId, DockableFrame dockable, boolean show) { + Logger.debug("in DefaultPerspective.addDockableFrame, groupData.size() = " + groupData.size()); + if (groupData.size() == 0) + { + initializeGroupData(); + Logger.debug("just called initializeGroupData"); + } + + Group data = groupData.get(groupId); + if (data == null) { + msg.error("Error adding dockable: Group '" + groupId + "' does not exist.", + new IllegalArgumentException("Group does not exist")); + return; + } + Logger.debug("data was not null, continuing by instantiating DockableActivation"); + DockableActivation activation = new DockableActivation(dockable, data); + if (workingArea != null) { + Logger.debug("workingArea was not null, continuing by calling activation.activate()"); + activation.activate(); + Logger.debug("back from activate, ready to call .getDockable().toFront()"); + ((DefaultDockableFrame) dockable).getDockable().toFront(); + Logger.debug("done with that, now ready to return from member function addDockableFrame"); + } else + { + Logger.debug("workingArea was null, so into else: call activations.add(activation)"); + activations.add(activation); + Logger.debug("done with add, returning from member function addDockableFrame"); + } + } + + /** + * Attempts to dock the specified dockable to the target, stacking the + * dockable on top of the target. This will do nothing if the target is + * minimized or the dockable has not been added to a group. + * + * @param dockable + * the dockable to dock + * @param target + * the target to dock to + */ + public void dock(DockableFrame dockable, DockableFrame target) { + StackActivation activation = new StackActivation(dockable, target); + if (isActive) + activation.activate(); + else + activations.add(activation); + } + + /** + * Attempts to dock the specified dockable in some location relative to + * another dockable. This will not work if relativeTo is minimized or + * maximized, or if the dockable hasn't been added to a group yet. + * + * @param dockable + * the dockable to dock + * @param relativeTo + * the dockable to dock relative to + * @param location + * the relative location + * @param fillPercent + * the fill percent that the dockable should take up + */ + public void dock(DockableFrame dockable, DockableFrame relativeTo, Location location, + float fillPercent) { + DockingActivation activation = new DockingActivation(dockable, relativeTo, location, + fillPercent); + if (isActive) + activation.activate(); + else + activations.add(activation); + } + + /** + * Creates group with the specified parameters. + * + * @param id + * the id of the group + * @param location + * the location of the group + * @param relativeTo + * the id of the parent of the created group + * @param fillPercentage + * the fill percentage of the created group. + */ + public void createGroup(String id, Location location, String relativeTo, float fillPercentage) { + pathCreator.definePath(id, location, relativeTo, fillPercentage); + } + + /** + * Creates the root or main group of this Perspective. The root group will + * have the specified id. + * + * @param id + * the id of the root group + */ + public void createRootGroup(String id) { + rootGroupID = id; + activations.add(0, new WorkingAreaActivation(id)); + } + + /** + * Activates this Perspective. + */ + public void activate() { + if (!isActive) { + isActive = true; + savedLayout = null; + + if (groupData.size() == 0) + initializeGroupData(); + + for (DockableCommand command : activations) { + command.activate(); + } + + // load the stored layout + if (!initialized && layoutFile != null) { + reset(layoutFile); + layoutFile = null; + } + + activations.clear(); + initialized = true; + } + } + + /** + * Resets the layout from a layout stored in a file. + * + * @param file the file to reset the layout from. + */ + public boolean reset(File file) { + try { + return reset(new FileInputStream(file)); + } catch (FileNotFoundException ex) { + msg.error("Error reseting layout from file", ex); + return false; + } + } + + /** + * Resets the layout from a layout stored in a stream. + * + * @param stream the stream to reset the layout from. + */ + public boolean reset(InputStream stream) { + boolean success = false; + try { + // System.out.printf("Reading: %s%n", file.getAbsolutePath()); + BufferedInputStream in = new BufferedInputStream(stream); + XElement element = XIO.readUTF(in); + in.close(); + control.readXML(element); + } catch (Exception ex) { + control.delete(id); + msg.warn("Error reading saved layout for perspective '" + id + "'", ex); + return false; + } + + try { + control.load(id); + + // this is to insure that any dockables that are not + // part of the loaded layout, but should be added to + // the perspective, are made visible. + for (int i = 0, n = control.getCDockableCount(); i < n; i++) { + CDockable dockable = control.getCDockable(i); + if (!dockable.isVisible()) { + dockable.setVisible(true); + dockable.setExtendedMode(ExtendedMode.NORMALIZED); + } + } + success = true; + } catch (Exception ex) { + control.delete(id); + msg.warn("Error loading layout for perspective '" + id + "'", ex); + } + + return success; + } + + private CDockable findSelectedDockable() { + // we do this because the selected dockable may not correspond + // to a DockableFrame. + Dockable dockable = control.intern().getController().getFocusedDockable(); + for (DockableFrame frame : getDockables()) { + DefaultCDockable cDockable = ((DefaultDockableFrame) frame).getDockable(); + if (cDockable.intern().equals(dockable)) + return cDockable; + } + + return null; + } + + /** + * Deactivates this Perspective. + */ + public void deactivate() { + if (isActive) { + isActive = false; + selectedDockable = findSelectedDockable(); + + WorkingAreaActivation waActivation = new WorkingAreaActivation(rootGroupID); + activations.add(waActivation); + + for (Group group : groupData.values()) { + for (DockableFrame frame : group.getDockables()) { + DefaultCDockable dockable = ((DefaultDockableFrame) frame).getDockable(); + activations.add(new AddActivation(frame, group, dockable.getExtendedMode())); + } + } + + // work-around for bug in dockingFrames where floating dockables + // don't save + normalizeExtDockables(); + control.save(id); + savedLayout = new XElement("root"); + control.writeXML(savedLayout); + // this activation needs to occur before the + // the select activation so selections that + // occur during the layout are not the final + // selections + activations.add(new LayoutActivation()); + + for (DockableFrame frame : groupData.get(rootGroupID).getDockables()) { + activations.add(new ModeSetActivation(frame)); + } + + for (DockableFrame frame : getDockables()) { + DefaultCDockable dockable = ((DefaultDockableFrame) frame).getDockable(); + control.remove((SingleCDockable) dockable); + } + + if (selectedDockable != null) + activations.add(new SelectActivation()); + + control.remove((SingleCDockable) workingArea); + control.remove((CStation) workingArea); + workingArea = null; + } + } + + /** + * Gets all the DockableFrames currently in this perspective. + * + * @return all the DockableFrames currently in this perspective. + */ + public List getDockables() { + List dockables = new ArrayList(); + for (Group data : groupData.values()) { + dockables = data.addTo(dockables); + } + + return dockables; + } + + /** + * Gets all the DockableFrames in the specified group. + * + * @param groupID + * the id of the group whose dockables should be returned + * @return all the DockableFrames in the specified group. + */ + public Set getDockables(String groupID) { + Group data = groupData.get(groupID); + if (data == null) { + msg.error("Error getting dockables for group: Group '" + groupID + "does not exist.", + new IllegalArgumentException("Group does not exist")); + return null; + } + + return new HashSet(data.getDockables()); + } + + /** + * Gets the ids of all the groups in this Perspective. + * + * @return the ids of all the groups in this Perspective. + */ + public Set getGroupIDs() { + return new HashSet(groupData.keySet()); + } + + /** + * Gets the id of this Perspective. + * + * @return the id of this Perspective. + */ + public String getID() { + return id; + } + + /** + * Gets the name of this Perspective. + * + * @return the name of this Perspective. + */ + public String getName() { + return name; + } + + /** + * Loads a layout. Depending on whether this Perspective uses the Preferences + * to store the layout, the prefs object may contain the layout data. + * + * @param prefs + * repository of the layout data + */ + public void loadLayout(Preferences prefs) { + File file = createFileName(prefs, false); + if (file.exists()) { + layoutFile = file; + } else { + // use the default layout if one exists + file = new File(System.getProperty("applicationRoot") + "/props", "default_" + id + ".layout"); + if (file.exists()) + layoutFile = file; + } + } + + private File createFileName(Preferences prefs, boolean mkdir) { + String path = prefs.get(AppPreferences.SAVE_PATH_KEY, "").trim(); + File file; + if (path.length() == 0) { + String home = System.getProperty("user.home"); + file = new File(home + "/." + prefs.name() + "/"); + } else { + file = new File(path); + } + if (mkdir && !file.exists()) + file.mkdirs(); + return new File(file, id + ".layout"); + } + + /* + * Normalizes any externalized dockables + */ + private void normalizeExtDockables() { + for (DockableFrame frame : getDockables()) { + if (frame.isFloating()) + frame.restore(); + } + } + + /** + * Saves the frame layout. + * + * @param prefs + * optional preferences repository where the layout can be saved + */ + public void saveLayout(Preferences prefs) { + // the perspective may have never been + // activated so there may not be any layout info for it + File file = createFileName(prefs, true); + saveLayout(file); + } + + /* (non-Javadoc) + * @see saf.core.ui.dock.Perspective#saveLayout(java.io.File) + */ + @Override + public void saveLayout(File file) { + if (initialized) { + // only save if active otherwise save the setting + // the control saved in deactivate + if (isActive) { + normalizeExtDockables(); + control.save(id); + } + try { + if (savedLayout == null) + control.writeXML(file); + else { + // write the layout that was saved to an XElement on deactivation + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + XIO.writeUTF(savedLayout, out); + out.close(); + } + // control.intern().write(new DataOutputStream(new + // FileOutputStream(file))); + } catch (IOException ex) { + msg.warn("Error while saving layout for perspective '" + id + "'", ex); + } + } + } + + /** + * Removes the specified dockable from this Perspective. + * + * @param dockable + * the dockable to remove + */ + public void removeDockable(DockableFrame dockable) { + if (isActive) { + for (Group group : groupData.values()) { + if (group.removeDockable(dockable)) + break; + } + control.remove((SingleCDockable) ((DefaultDockableFrame) dockable).getDockable()); + } else { + for (Iterator iter = activations.iterator(); iter.hasNext();) { + DockableCommand act = iter.next(); + if (act.getSubjects().contains(dockable)) + iter.remove(); + } + } + if (selectedDockable != null + && ((DefaultDockableFrame) dockable).getDockable().equals(selectedDockable)) + selectedDockable = null; + } + + private DockableFrame findFrame(CDockable cDockable) { + if (cDockable != null) { + for (DockableFrame frame : getDockables()) { + DefaultCDockable dockable = ((DefaultDockableFrame) frame).getDockable(); + if (dockable.equals(cDockable)) + return frame; + } + } + + return null; + + } + + class LayoutActivation implements DockableCommand { + + public void activate() { + control.load(id); + } + + public List getSubjects() { + return new ArrayList(); + } + } + + class SelectActivation implements DockableCommand { + + public void activate() { + DockableFrame frame = findFrame(selectedDockable); + if (frame != null) + frame.toFront(); + } + + public List getSubjects() { + DockableFrame frame = findFrame(selectedDockable); + if (frame != null) + return DockUtilities.createList(frame); + return new ArrayList(); + } + } + + class WorkingAreaActivation implements DockableCommand { + + private String id; + + WorkingAreaActivation(String id) { + this.id = id; + } + + public void activate() { + workingArea = control.createWorkingArea(id); + workingArea.setLocation(CLocation.base().normalRectangle(0, 0, 1, 1)); + ((RootGroup) groupData.get(id)).initWorkingArea(workingArea); + workingArea.setVisible(true); + } + + public List getSubjects() { + return new ArrayList(); + } + } + + class DockableActivation implements DockableCommand { + + DockableFrame dockable; + Group data; + + DockableActivation(DockableFrame dockable, Group data) { + this.dockable = dockable; + this.data = data; + } + + public void activate() { + DefaultCDockable cDockable = ((DefaultDockableFrame) dockable).getDockable(); + CLocation location; + DockableFrame other = data.getNormalDockable(); + if (other == null) + location = data.getLocation(); + else + location = ((DefaultDockableFrame) other).getDockable().getBaseLocation(); + cDockable.setLocation(location); + data.add(dockable); + if (data.getID().equals(rootGroupID)) { + workingArea.add((SingleCDockable) cDockable); + } else { + control.add((SingleCDockable) cDockable); + } + cDockable.setVisible(true); + } + + public List getSubjects() { + return DockUtilities.createList(dockable); + } + } + + class StackActivation implements DockableCommand { + + DockableFrame dockable, target; + + StackActivation(DockableFrame dockable, DockableFrame target) { + this.dockable = dockable; + this.target = target; + } + + public void activate() { + if (!target.isMinimized() && getDockables().contains(dockable)) { + DefaultCDockable cTarget = ((DefaultDockableFrame) target).getDockable(); + CLocation location = cTarget.getBaseLocation(); + DefaultCDockable cDockable = ((DefaultDockableFrame) dockable).getDockable(); + cDockable.setLocation(location); + } + } + + public List getSubjects() { + return DockUtilities.createList(dockable, target); + } + } + + // re-adds dockables + class AddActivation implements DockableCommand { + DockableFrame dockable; + ExtendedMode mode; + Group data; + + AddActivation(DockableFrame dockable, Group data, ExtendedMode mode) { + this.dockable = dockable; + this.mode = mode; + this.data = data; + } + + public void activate() { + DefaultCDockable cDockable = ((DefaultDockableFrame) dockable).getDockable(); + if (data.getID().equals(rootGroupID)) { + workingArea.add((SingleCDockable) cDockable); + } else { + control.add((SingleCDockable) cDockable); + } + cDockable.setExtendedMode(mode); + cDockable.setVisible(true); + } + + public List getSubjects() { + return DockUtilities.createList(dockable); + } + } + + class DockingActivation implements DockableCommand { + + DockableFrame dockable, target; + Location location; + float fill; + + DockingActivation(DockableFrame dockable, DockableFrame target, Location location, float fill) { + this.dockable = dockable; + this.target = target; + this.location = location; + this.fill = fill; + } + + public void activate() { + if (!(target.isMinimized() || target.isMaximized()) && getDockables().contains(dockable)) { + CLocation rLocation = ((DefaultDockableFrame) target).getDockable().getBaseLocation(); + if (rLocation instanceof AbstractTreeLocation) { + AbstractTreeLocation treeLoc = (AbstractTreeLocation) rLocation; + ((DefaultDockableFrame) dockable).getDockable().setLocation( + location.createPath(treeLoc, fill)); + + } else if (rLocation instanceof CBaseLocation) { + CBaseLocation baseLoc = (CBaseLocation) rLocation; + ((DefaultDockableFrame) dockable).getDockable().setLocation( + location.createPath(baseLoc, fill)); + } else if (rLocation instanceof CStackLocation) { + DefaultCDockable parent = ((DefaultDockableFrame) target).getDockable(); + DockStation parentStation = parent.intern().getDockParent(); + CLocation stationLoc = control.getLocationManager().getLocation( + parentStation.asDockable()); + if (stationLoc != null) { + ((DefaultDockableFrame) dockable).getDockable().setLocation( + location.createPath((AbstractTreeLocation) stationLoc, fill)); + } + } + } + } + + public List getSubjects() { + return DockUtilities.createList(dockable, target); + } + } + + // this is necessary because the working area frames + // don't seem to respect their location / mode when re-laid out + class ModeSetActivation implements DockableCommand { + + CDockable dockable; + ExtendedMode mode; + CLocation location; + + ModeSetActivation(DockableFrame frame) { + dockable = ((DefaultDockableFrame) frame).getDockable(); + this.mode = dockable.getExtendedMode(); + this.location = dockable.getBaseLocation(); + } + + public void activate() { + dockable.setExtendedMode(mode); + dockable.setLocation(location); + } + + public List getSubjects() { + DockableFrame frame = findFrame(dockable); + return DockUtilities.createList(frame); + } + + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/DockUtilities.java b/festc_saf_ui/src/saf/core/ui/dock/DockUtilities.java index a18c34f..791b449 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/DockUtilities.java +++ b/festc_saf_ui/src/saf/core/ui/dock/DockUtilities.java @@ -1,23 +1,23 @@ -package saf.core.ui.dock; - -import java.util.List; -import java.util.Arrays; - -/** - * Static utility methods for DockableFrames. - * - * @author Nick Collier - */ -public class DockUtilities { - - /** - * Creates a list of dockable frames from the specified frames. - * - * @param frames the frames to add to the list - * - * @return a list of dockable frames from the specified frames. - */ - public static List createList(DockableFrame... frames) { - return Arrays.asList(frames); - } -} +package saf.core.ui.dock; + +import java.util.List; +import java.util.Arrays; + +/** + * Static utility methods for DockableFrames. + * + * @author Nick Collier + */ +public class DockUtilities { + + /** + * Creates a list of dockable frames from the specified frames. + * + * @param frames the frames to add to the list + * + * @return a list of dockable frames from the specified frames. + */ + public static List createList(DockableFrame... frames) { + return Arrays.asList(frames); + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/DockableCommand.java b/festc_saf_ui/src/saf/core/ui/dock/DockableCommand.java index 839aa42..e4dcf20 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/DockableCommand.java +++ b/festc_saf_ui/src/saf/core/ui/dock/DockableCommand.java @@ -1,25 +1,25 @@ -package saf.core.ui.dock; - -import java.util.List; - -/** - * Interface for commands that operate on a Dockable. - * - * @author Nick Collier - */ -public interface DockableCommand { - - /** - * Performs the activation. - */ - void activate(); - - /** - * Gets the DockableFrame(s) that are the subjects - * of this command. - * - * @return the DockableFrame(s) that are the subjects - * of this command. - */ - List getSubjects(); -} +package saf.core.ui.dock; + +import java.util.List; + +/** + * Interface for commands that operate on a Dockable. + * + * @author Nick Collier + */ +public interface DockableCommand { + + /** + * Performs the activation. + */ + void activate(); + + /** + * Gets the DockableFrame(s) that are the subjects + * of this command. + * + * @return the DockableFrame(s) that are the subjects + * of this command. + */ + List getSubjects(); +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/DockableFrame.java b/festc_saf_ui/src/saf/core/ui/dock/DockableFrame.java index 7ede533..1787ddc 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/DockableFrame.java +++ b/festc_saf_ui/src/saf/core/ui/dock/DockableFrame.java @@ -1,137 +1,137 @@ -package saf.core.ui.dock; - -import javax.swing.*; - -/** - * Interface for classes that implement a dockable frame. - */ -public interface DockableFrame { - - /** - * Adds an arbitrary key/value "client property" to this component. - * - * @param key the new client property key - * @param value the new client property value; if this is null the property will be removed - */ - void putClientProperty(Object key, Object value); - - /** - * Returns the value of the property with the specified key. - * Only properties added with putClientProperty will return a non-null value. - * - * @param key the property key whose value should be returned. - * - * @return the value of the property with the specified key. - */ - Object getClientProperty(Object key); - - /** - * Gets the toolbar, if any, for this frame. - * - * @return the toolbar for this frame if one exists, otherwise null. - */ - JToolBar getToolBar(); - - /** - * Adds a toolbar to this frame. - * - * @param bar the toolbar to add - */ - void addToolBar(JToolBar bar); - - /** - * Gets the panel that contains the component - * displayed in this frame. By default this component - * can be retrieved by calling getComponent(0) on the - * returned panel.

- *

- * Note that this panel should not contain the toolbar. - * - * @return the panel that contains the component - * displayed in this frame. - */ - JPanel getContentPane(); - - /** - * Gets whether or not this DockableFrame is minimized. - * - * @return true if this DockableFrame is minimized, otherwise false. - */ - boolean isMinimized(); - - /** - * Gets whether or not this DockableFrame is maximized. - * - * @return true if this DockableFrame is maximized, otherwise false. - */ - boolean isMaximized(); - - /** - * Gets whether or not this DockableFrame is floating. - * - * @return true if this DockableFrame is floating, otherwise false. - */ - boolean isFloating(); - - /** - * Gets the unique id for this DockableFrame. - * - * @return the unique id for this DockableFrame. - */ - String getID(); - - /** - * Gets the title text for this DockableFrame. - * - * @return the title text for this DockableFrame. - */ - String getTitle(); - - /** - * Sets the title text for this DockableFrame. - * - * @param title the title text for this DockableFrame. - */ - void setTitle(String title); - - /** - * Selects this DockableFrame. - */ - void toFront(); - - /** - * Restores this DockableFrame. - */ - void restore(); - - /** - * Minimizes this DockableFrame. - * - * @param location the location to minimize to - */ - void minimize(DockingManager.MinimizeLocation location); - - /** - * Maximizes this DockableFrame. - */ - void maximize(); - - /** - * Floats this DockableFrame. - */ - void doFloat(); - - /** - * Close this dockable. Assumes the dockable is - * in the current perspective. - */ - void close(); - - /** - * Closes this dockable in the specified perspective. - * - * @param perspectiveID the id of the perspective to close - * the dockable in. - */ - void close(String perspectiveID); -} +package saf.core.ui.dock; + +import javax.swing.*; + +/** + * Interface for classes that implement a dockable frame. + */ +public interface DockableFrame { + + /** + * Adds an arbitrary key/value "client property" to this component. + * + * @param key the new client property key + * @param value the new client property value; if this is null the property will be removed + */ + void putClientProperty(Object key, Object value); + + /** + * Returns the value of the property with the specified key. + * Only properties added with putClientProperty will return a non-null value. + * + * @param key the property key whose value should be returned. + * + * @return the value of the property with the specified key. + */ + Object getClientProperty(Object key); + + /** + * Gets the toolbar, if any, for this frame. + * + * @return the toolbar for this frame if one exists, otherwise null. + */ + JToolBar getToolBar(); + + /** + * Adds a toolbar to this frame. + * + * @param bar the toolbar to add + */ + void addToolBar(JToolBar bar); + + /** + * Gets the panel that contains the component + * displayed in this frame. By default this component + * can be retrieved by calling getComponent(0) on the + * returned panel.

+ *

+ * Note that this panel should not contain the toolbar. + * + * @return the panel that contains the component + * displayed in this frame. + */ + JPanel getContentPane(); + + /** + * Gets whether or not this DockableFrame is minimized. + * + * @return true if this DockableFrame is minimized, otherwise false. + */ + boolean isMinimized(); + + /** + * Gets whether or not this DockableFrame is maximized. + * + * @return true if this DockableFrame is maximized, otherwise false. + */ + boolean isMaximized(); + + /** + * Gets whether or not this DockableFrame is floating. + * + * @return true if this DockableFrame is floating, otherwise false. + */ + boolean isFloating(); + + /** + * Gets the unique id for this DockableFrame. + * + * @return the unique id for this DockableFrame. + */ + String getID(); + + /** + * Gets the title text for this DockableFrame. + * + * @return the title text for this DockableFrame. + */ + String getTitle(); + + /** + * Sets the title text for this DockableFrame. + * + * @param title the title text for this DockableFrame. + */ + void setTitle(String title); + + /** + * Selects this DockableFrame. + */ + void toFront(); + + /** + * Restores this DockableFrame. + */ + void restore(); + + /** + * Minimizes this DockableFrame. + * + * @param location the location to minimize to + */ + void minimize(DockingManager.MinimizeLocation location); + + /** + * Maximizes this DockableFrame. + */ + void maximize(); + + /** + * Floats this DockableFrame. + */ + void doFloat(); + + /** + * Close this dockable. Assumes the dockable is + * in the current perspective. + */ + void close(); + + /** + * Closes this dockable in the specified perspective. + * + * @param perspectiveID the id of the perspective to close + * the dockable in. + */ + void close(String perspectiveID); +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/DockingFactory.java b/festc_saf_ui/src/saf/core/ui/dock/DockingFactory.java index 75ccd44..8e7b810 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/DockingFactory.java +++ b/festc_saf_ui/src/saf/core/ui/dock/DockingFactory.java @@ -1,41 +1,41 @@ -package saf.core.ui.dock; - -import saf.core.ui.GUIBarManager; -import saf.core.ui.ISAFDisplay; - -import java.util.List; - -/** - * Interface for classes that create the basic docking components. - * - */ -public interface DockingFactory { - - /** - * Gets the ViewManager. If the view manager has not - * yet been created this should create one using the - * specified barManager and perspectives. - * - * @param barManager the bar manager - * @param perspectives list of user-defined perspectives - * - * @return the ViewManager. - */ - DockingManager getViewManager(GUIBarManager barManager, List perspectives); - - /** - * Gets the display. - * - * @return the display. - */ - ISAFDisplay getDisplay(); - - /** - * Creates a Perspective. - * - * @return the created Perspective. - * @param id the id of the perspective - * @param name the name of the perspective - */ - Perspective createPerspective(String id, String name); -} +package saf.core.ui.dock; + +import saf.core.ui.GUIBarManager; +import saf.core.ui.ISAFDisplay; + +import java.util.List; + +/** + * Interface for classes that create the basic docking components. + * + */ +public interface DockingFactory { + + /** + * Gets the ViewManager. If the view manager has not + * yet been created this should create one using the + * specified barManager and perspectives. + * + * @param barManager the bar manager + * @param perspectives list of user-defined perspectives + * + * @return the ViewManager. + */ + DockingManager getViewManager(GUIBarManager barManager, List perspectives); + + /** + * Gets the display. + * + * @return the display. + */ + ISAFDisplay getDisplay(); + + /** + * Creates a Perspective. + * + * @return the created Perspective. + * @param id the id of the perspective + * @param name the name of the perspective + */ + Perspective createPerspective(String id, String name); +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/DockingManager.java b/festc_saf_ui/src/saf/core/ui/dock/DockingManager.java index a62081c..16642ff 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/DockingManager.java +++ b/festc_saf_ui/src/saf/core/ui/dock/DockingManager.java @@ -1,218 +1,218 @@ -package saf.core.ui.dock; - - -import saf.core.ui.GUIBarManager; -import saf.core.ui.event.DockableFrameListener; -import saf.core.ui.event.DockableSelectionListener; -import saf.core.ui.event.PerspectiveSelectionListener; - -import javax.swing.*; -import java.util.List; -import java.util.Set; - -/** - * Interface for classes that manage dockable frames. - */ -public interface DockingManager { - - - public enum MinimizeLocation { - UNSPECIFIED, LEFT, RIGHT, BOTTOM, TOP - } - - int CLOSE = 1; - int MINIMIZE = 2; - int MAXIMIZE = 4; - int FLOAT = 8; - - /** - * Gets the bar manager that manages the tool, menu and status bars. - * - * @return the bar manager that manages the tool, menu and status bars. - */ - GUIBarManager getBarManager(); - - /** - * Attempts to dock the specified dockable to the target, stacking the - * dockable on top of the target. This will do nothing if the - * target is minimized or the dockable has not been added to a group. - * - * @param dockable the dockable to dock - * @param target the target to dock to - */ - void dock(DockableFrame dockable, DockableFrame target); - - /** - * Attempts to dock the specified dockable in some location relative - * to another dockable. This will not work if relativeTo is minimized or - * maximized, or if the dockable hasn't been added to a group yet. - * - * @param dockable the dockable to dock - * @param relativeTo the dockable to dock relative to - * @param location the relative location - * @param fillPercent the fill percent that the dockable should take up - */ - void dock(DockableFrame dockable, DockableFrame relativeTo, Location location, - float fillPercent); - - /** - * Adds the specified dockable to the specified group in the specified perspective. - * - * @param perspectiveID the id of the perspective to add the dockable to - * @param groupID the id of the group to add the dockable to - * @param dockable the dockable to add - */ - void addDockableToGroup(String perspectiveID, String groupID, DockableFrame dockable); - - /** - * Gets the group ids of the groups in the specified perspective. - * - * @param perspectiveID the perspective whose groups are of interest - * @return group ids of the groups in the specified perspective - */ - Set getGroupIDs(String perspectiveID); - - /** - * Gets all the dockables in the specified group in the specified perspective. - * - * @param perspectiveID the id of the perspective - * @param groupID the id the group - * @return all the dockables in the specified group in the specified perspective. - */ - List getDockableFrames(String perspectiveID, String groupID); - - /** - * Creates a Dockable with the specified id containing the specified component. This only creates - * the dockable. To add a created dockable into a window use the - * {@link #addDockableToGroup(String,String,DockableFrame) addDockableToGroup} method. - * - * @param id the id that uniquely identifies the created Dockable - * @param comp the component displayed by the dockable - * @return the created dockable - * @see #addDockableToGroup - */ - DockableFrame createDockable(String id, JComponent comp); - - /** - * Creates a dockable with the specified id, hide location and containing the specified component. - * This only creates the dockable. To add a created dockable into a window use the - * {@link #addDockableToGroup(String,String,DockableFrame) addDockableToGroup} method.

- * - * @param id the id that uniquely identifies the created Dockable - * @param comp the component displayed by the dockable - * @param hideLocation the location where the dockable is minimized to - * @return the created dockable - */ - DockableFrame createDockable(String id, JComponent comp, MinimizeLocation hideLocation); - - /** - * Creates a dockable with the specified id, hide location, window controls and - * containing the specified component. This only creates the dockable. To add a created dockable - * into a window use the - * {@link #addDockableToGroup(String,String,DockableFrame) addDockableToGroup} method.

- *

- * The dockable controls are: - *

    - *
  • DockingManager.CLOSE
  • - *
  • DockingManager.HIDE
  • - *
  • DockingManager.MAXIMIZE
  • - *
  • DockingManager.FLOAT
  • - *
- * These can be logically or'ed together. - * - * @param id the id that uniquely identifies the created Dockable - * @param comp the component displayed by the dockable - * @param location the location where the dockable is minimized to - * @param dockableControls specifies what controls (close, maximize, float etc.) - * are displayed on the dockable's title bar - * @return the created dockable - */ - DockableFrame createDockable(String id, JComponent comp, MinimizeLocation location, int dockableControls); - - /** - * Initializes the docking manger by activitating the current perpspective. - */ - void init(); - - /** - * Sets the specified perspective as the currently active perspective. - * - * @param perspectiveID the id of the perspective to set - */ - void setPerspective(String perspectiveID); - - /** - * Gets a list of all the perspective ids. - * - * @return a list of all the perspective ids. - */ - List getPerspectiveIDs(); - - /** - * Gets the specified perspective. - * - * @param id the id of the perspective to get - * @return the specified perspective. - */ - Perspective getPerspective(String id); - - /** - * Gets the current perspective. - * - * @return the current perspective - */ - Perspective getPerspective(); - - /** - * Gets the specified dockable by its id. - * - * @param id the id of the dockable to get - * @return the specified dockable by its id. - */ - DockableFrame getDockable(String id); - - /** - * Adds a dockable listener to this DockingManager to listen for dockable events. - * - * @param listener the listener to add. - */ - void addDockableListener(DockableFrameListener listener); - - /** - * Removes the specified dockable listener. - * - * @param listener the listener to remove - */ - void removeDockableListener(DockableFrameListener listener); - - /** - * Adds a dockable selection listener to this DockingManager to listen for dockable - * selection events. - * - * @param listener the listener to add. - */ - void addDockableSelectionListener(DockableSelectionListener listener); - - /** - * Removes the specified dockable selection listener. - * - * @param listener the listener to remove - */ - void removeDockableSelectionListener(DockableSelectionListener listener); - - /** - * Adds a perspective selection listener to this DockingManager to listen for perspective - * selection events. - * - * @param listener the listener to add. - */ - void addPerspectiveSelectionListener(PerspectiveSelectionListener listener); - - /** - * Removes the specified perspective selection listener. - * - * @param listener the listener to remove - */ - void removePerspectiveSelectionListener(PerspectiveSelectionListener listener); - -} +package saf.core.ui.dock; + + +import saf.core.ui.GUIBarManager; +import saf.core.ui.event.DockableFrameListener; +import saf.core.ui.event.DockableSelectionListener; +import saf.core.ui.event.PerspectiveSelectionListener; + +import javax.swing.*; +import java.util.List; +import java.util.Set; + +/** + * Interface for classes that manage dockable frames. + */ +public interface DockingManager { + + + public enum MinimizeLocation { + UNSPECIFIED, LEFT, RIGHT, BOTTOM, TOP + } + + int CLOSE = 1; + int MINIMIZE = 2; + int MAXIMIZE = 4; + int FLOAT = 8; + + /** + * Gets the bar manager that manages the tool, menu and status bars. + * + * @return the bar manager that manages the tool, menu and status bars. + */ + GUIBarManager getBarManager(); + + /** + * Attempts to dock the specified dockable to the target, stacking the + * dockable on top of the target. This will do nothing if the + * target is minimized or the dockable has not been added to a group. + * + * @param dockable the dockable to dock + * @param target the target to dock to + */ + void dock(DockableFrame dockable, DockableFrame target); + + /** + * Attempts to dock the specified dockable in some location relative + * to another dockable. This will not work if relativeTo is minimized or + * maximized, or if the dockable hasn't been added to a group yet. + * + * @param dockable the dockable to dock + * @param relativeTo the dockable to dock relative to + * @param location the relative location + * @param fillPercent the fill percent that the dockable should take up + */ + void dock(DockableFrame dockable, DockableFrame relativeTo, Location location, + float fillPercent); + + /** + * Adds the specified dockable to the specified group in the specified perspective. + * + * @param perspectiveID the id of the perspective to add the dockable to + * @param groupID the id of the group to add the dockable to + * @param dockable the dockable to add + */ + void addDockableToGroup(String perspectiveID, String groupID, DockableFrame dockable); + + /** + * Gets the group ids of the groups in the specified perspective. + * + * @param perspectiveID the perspective whose groups are of interest + * @return group ids of the groups in the specified perspective + */ + Set getGroupIDs(String perspectiveID); + + /** + * Gets all the dockables in the specified group in the specified perspective. + * + * @param perspectiveID the id of the perspective + * @param groupID the id the group + * @return all the dockables in the specified group in the specified perspective. + */ + List getDockableFrames(String perspectiveID, String groupID); + + /** + * Creates a Dockable with the specified id containing the specified component. This only creates + * the dockable. To add a created dockable into a window use the + * {@link #addDockableToGroup(String,String,DockableFrame) addDockableToGroup} method. + * + * @param id the id that uniquely identifies the created Dockable + * @param comp the component displayed by the dockable + * @return the created dockable + * @see #addDockableToGroup + */ + DockableFrame createDockable(String id, JComponent comp); + + /** + * Creates a dockable with the specified id, hide location and containing the specified component. + * This only creates the dockable. To add a created dockable into a window use the + * {@link #addDockableToGroup(String,String,DockableFrame) addDockableToGroup} method.

+ * + * @param id the id that uniquely identifies the created Dockable + * @param comp the component displayed by the dockable + * @param hideLocation the location where the dockable is minimized to + * @return the created dockable + */ + DockableFrame createDockable(String id, JComponent comp, MinimizeLocation hideLocation); + + /** + * Creates a dockable with the specified id, hide location, window controls and + * containing the specified component. This only creates the dockable. To add a created dockable + * into a window use the + * {@link #addDockableToGroup(String,String,DockableFrame) addDockableToGroup} method.

+ *

+ * The dockable controls are: + *

    + *
  • DockingManager.CLOSE
  • + *
  • DockingManager.HIDE
  • + *
  • DockingManager.MAXIMIZE
  • + *
  • DockingManager.FLOAT
  • + *
+ * These can be logically or'ed together. + * + * @param id the id that uniquely identifies the created Dockable + * @param comp the component displayed by the dockable + * @param location the location where the dockable is minimized to + * @param dockableControls specifies what controls (close, maximize, float etc.) + * are displayed on the dockable's title bar + * @return the created dockable + */ + DockableFrame createDockable(String id, JComponent comp, MinimizeLocation location, int dockableControls); + + /** + * Initializes the docking manger by activitating the current perpspective. + */ + void init(); + + /** + * Sets the specified perspective as the currently active perspective. + * + * @param perspectiveID the id of the perspective to set + */ + void setPerspective(String perspectiveID); + + /** + * Gets a list of all the perspective ids. + * + * @return a list of all the perspective ids. + */ + List getPerspectiveIDs(); + + /** + * Gets the specified perspective. + * + * @param id the id of the perspective to get + * @return the specified perspective. + */ + Perspective getPerspective(String id); + + /** + * Gets the current perspective. + * + * @return the current perspective + */ + Perspective getPerspective(); + + /** + * Gets the specified dockable by its id. + * + * @param id the id of the dockable to get + * @return the specified dockable by its id. + */ + DockableFrame getDockable(String id); + + /** + * Adds a dockable listener to this DockingManager to listen for dockable events. + * + * @param listener the listener to add. + */ + void addDockableListener(DockableFrameListener listener); + + /** + * Removes the specified dockable listener. + * + * @param listener the listener to remove + */ + void removeDockableListener(DockableFrameListener listener); + + /** + * Adds a dockable selection listener to this DockingManager to listen for dockable + * selection events. + * + * @param listener the listener to add. + */ + void addDockableSelectionListener(DockableSelectionListener listener); + + /** + * Removes the specified dockable selection listener. + * + * @param listener the listener to remove + */ + void removeDockableSelectionListener(DockableSelectionListener listener); + + /** + * Adds a perspective selection listener to this DockingManager to listen for perspective + * selection events. + * + * @param listener the listener to add. + */ + void addPerspectiveSelectionListener(PerspectiveSelectionListener listener); + + /** + * Removes the specified perspective selection listener. + * + * @param listener the listener to remove + */ + void removePerspectiveSelectionListener(PerspectiveSelectionListener listener); + +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/Group.java b/festc_saf_ui/src/saf/core/ui/dock/Group.java index e81f537..2e9ed44 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/Group.java +++ b/festc_saf_ui/src/saf/core/ui/dock/Group.java @@ -1,71 +1,71 @@ -package saf.core.ui.dock; - -import bibliothek.gui.dock.common.CLocation; -import bibliothek.gui.dock.common.intern.DefaultCDockable; - -import java.util.List; - -/** - * A docking group. - * - * @author Nick Collier - */ -public interface Group { - - /** - * Gets the first "normal" Dockable in this group, - * if any. - * - * @return the first "normal" Dockable in this group, - * if any. - */ - DockableFrame getNormalDockable(); - - /** - * Gets the default location of this Group. - * - * @return the location of this Group. - */ - CLocation getLocation(); - - /** - * Adds the dockables in this group to the specified list. - * - * @param frames the list to add to - * - * @return the new list - * - */ - List addTo(List frames); - - /** - * Gets the dockables in this Group. - * - * @return the dockables in this Group. - */ - List getDockables(); - - /** - * Adds a dockable to this group. - * - * @param dockable the dockable to add - */ - void add(DockableFrame dockable); - - /** - * Gets the id of this Group. - * - * @return the id of this Group. - */ - String getID(); - - /** - * Removes the specified dockable from this group. - * - * @param dockable the dockable to remove - * - * @return true if the the dockable was removed, otherwise false - */ - boolean removeDockable(DockableFrame dockable); - -} +package saf.core.ui.dock; + +import bibliothek.gui.dock.common.CLocation; +import bibliothek.gui.dock.common.intern.DefaultCDockable; + +import java.util.List; + +/** + * A docking group. + * + * @author Nick Collier + */ +public interface Group { + + /** + * Gets the first "normal" Dockable in this group, + * if any. + * + * @return the first "normal" Dockable in this group, + * if any. + */ + DockableFrame getNormalDockable(); + + /** + * Gets the default location of this Group. + * + * @return the location of this Group. + */ + CLocation getLocation(); + + /** + * Adds the dockables in this group to the specified list. + * + * @param frames the list to add to + * + * @return the new list + * + */ + List addTo(List frames); + + /** + * Gets the dockables in this Group. + * + * @return the dockables in this Group. + */ + List getDockables(); + + /** + * Adds a dockable to this group. + * + * @param dockable the dockable to add + */ + void add(DockableFrame dockable); + + /** + * Gets the id of this Group. + * + * @return the id of this Group. + */ + String getID(); + + /** + * Removes the specified dockable from this group. + * + * @param dockable the dockable to remove + * + * @return true if the the dockable was removed, otherwise false + */ + boolean removeDockable(DockableFrame dockable); + +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/GroupLocationPath.java b/festc_saf_ui/src/saf/core/ui/dock/GroupLocationPath.java index 4a1aa2c..0cc2486 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/GroupLocationPath.java +++ b/festc_saf_ui/src/saf/core/ui/dock/GroupLocationPath.java @@ -1,80 +1,80 @@ -package saf.core.ui.dock; - -import bibliothek.gui.dock.common.CLocation; -import bibliothek.gui.dock.common.location.CBaseLocation; -import bibliothek.gui.dock.common.location.AbstractTreeLocation; - -import java.util.List; -import java.util.ArrayList; - -/** - * The location path of a group relative to the root group. - * - * @author Nick Collier - */ -public class GroupLocationPath { - - private String id; - private List elements; - - /** - * Creates a GroupLocation path for the specified group id with the specified path. - * - * @param id the group of that this is the path for - * @param path the list of PathElements that constitute the path. - */ - public GroupLocationPath(String id, List path) { - this.id = id; - this.elements = new ArrayList(path); - } - - /** - * Creates a new GroupLocationPath for the specified group with a single - * element path. - * - * @param id the id of the group this is the path for - * @param element the single element that constitutes the path - */ - public GroupLocationPath(String id, GroupPathElement element) { - this.id = id; - this.elements = new ArrayList(); - this.elements.add(element); - } - - /** - * Creates a GroupLocationPath for the specified group. The path will be - * the parent path plus the element. - * - * @param id the id of the group this is the path for - * @param element the element to append to the parent path - * @param parentPath the parent path of this GroupLocation path - */ - public GroupLocationPath(String id, GroupPathElement element, GroupLocationPath parentPath) { - this(id, parentPath.elements); - elements.add(element); - } - - /** - * Gets the id of the group that this is the path for. - * - * @return the id of the group that this is the path for. - */ - public String getId() { - return id; - } - - /** - * Gets the CLocation for this path. - * - * @return the CLocation for this path. - */ - public CLocation getLocation() { - CBaseLocation basePath = CLocation.base(); - AbstractTreeLocation path = elements.get(0).createPath(basePath); - for (int i = 1, n = elements.size(); i < n; i++) { - path = elements.get(i).createPath(path); - } - - return path; - } -} +package saf.core.ui.dock; + +import bibliothek.gui.dock.common.CLocation; +import bibliothek.gui.dock.common.location.CBaseLocation; +import bibliothek.gui.dock.common.location.AbstractTreeLocation; + +import java.util.List; +import java.util.ArrayList; + +/** + * The location path of a group relative to the root group. + * + * @author Nick Collier + */ +public class GroupLocationPath { + + private String id; + private List elements; + + /** + * Creates a GroupLocation path for the specified group id with the specified path. + * + * @param id the group of that this is the path for + * @param path the list of PathElements that constitute the path. + */ + public GroupLocationPath(String id, List path) { + this.id = id; + this.elements = new ArrayList(path); + } + + /** + * Creates a new GroupLocationPath for the specified group with a single + * element path. + * + * @param id the id of the group this is the path for + * @param element the single element that constitutes the path + */ + public GroupLocationPath(String id, GroupPathElement element) { + this.id = id; + this.elements = new ArrayList(); + this.elements.add(element); + } + + /** + * Creates a GroupLocationPath for the specified group. The path will be + * the parent path plus the element. + * + * @param id the id of the group this is the path for + * @param element the element to append to the parent path + * @param parentPath the parent path of this GroupLocation path + */ + public GroupLocationPath(String id, GroupPathElement element, GroupLocationPath parentPath) { + this(id, parentPath.elements); + elements.add(element); + } + + /** + * Gets the id of the group that this is the path for. + * + * @return the id of the group that this is the path for. + */ + public String getId() { + return id; + } + + /** + * Gets the CLocation for this path. + * + * @return the CLocation for this path. + */ + public CLocation getLocation() { + CBaseLocation basePath = CLocation.base(); + AbstractTreeLocation path = elements.get(0).createPath(basePath); + for (int i = 1, n = elements.size(); i < n; i++) { + path = elements.get(i).createPath(path); + } + + return path; + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/GroupPathCreator.java b/festc_saf_ui/src/saf/core/ui/dock/GroupPathCreator.java index cdd8e8f..017c82f 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/GroupPathCreator.java +++ b/festc_saf_ui/src/saf/core/ui/dock/GroupPathCreator.java @@ -1,87 +1,87 @@ -package saf.core.ui.dock; - -import java.util.*; - -/** - * Factory for creating GroupLocationPaths. This takes - * descriptions (relative location etc.) of single path - * elements and produces a list of GroupLocationPaths. - * - * @author Nick Collier - */ -public class GroupPathCreator { - - private static class PathData { - Location location; - String parent, id; - float fill; - - private PathData(String id, String parent, Location location, float fill) { - this.id = id; - this.parent = parent; - this.location = location; - this.fill = fill; - } - } - - private List data = new ArrayList(); - - /** - * Defines a path with the specified parameters. - * - * @param id the id of the group - * @param location the relative location of the group - * @param parent the id of the group this group is located relative to - * @param fillPercentage the percentage of space this group takes up relative to its parent - */ - public void definePath(String id, Location location, String parent, float fillPercentage) { - data.add(new PathData(id, parent, location, fillPercentage)); - } - - /** - * Creates a List of GroupLocationPaths consisting of the paths that have - * been defined. - * - * @param rootID the id of the root group. - * @return a List of GroupLocationPaths consisting of the paths that have - * been defined. - */ - public List createPaths(String rootID) { - Map paths = new HashMap(); - List parents = new ArrayList(); - - // find all the paths whose parent is root - for (Iterator iter = data.iterator(); iter.hasNext();) { - PathData pathData = iter.next(); - if (pathData.parent.equals(rootID)) { - iter.remove(); - GroupPathElement element = new GroupPathElement(pathData.id, pathData.location, pathData.fill); - GroupLocationPath path = new GroupLocationPath(pathData.id, element); - paths.put(pathData.id, path); - parents.add(pathData.id); - } - } - - findPaths(parents, paths); - - return new ArrayList(paths.values()); - } - - private void findPaths(List parents, Map paths) { - List newParents = new ArrayList(); - for (String parent : parents) { - for (Iterator iter = data.iterator(); iter.hasNext();) { - PathData pathData = iter.next(); - if (pathData.parent.equals(parent)) { - iter.remove(); - GroupPathElement element = new GroupPathElement(pathData.id, pathData.location, pathData.fill); - GroupLocationPath path = new GroupLocationPath(pathData.id, element, paths.get(parent)); - paths.put(pathData.id, path); - newParents.add(pathData.id); - } - } - } - - if (newParents.size() > 0) findPaths(newParents, paths); - } -} +package saf.core.ui.dock; + +import java.util.*; + +/** + * Factory for creating GroupLocationPaths. This takes + * descriptions (relative location etc.) of single path + * elements and produces a list of GroupLocationPaths. + * + * @author Nick Collier + */ +public class GroupPathCreator { + + private static class PathData { + Location location; + String parent, id; + float fill; + + private PathData(String id, String parent, Location location, float fill) { + this.id = id; + this.parent = parent; + this.location = location; + this.fill = fill; + } + } + + private List data = new ArrayList(); + + /** + * Defines a path with the specified parameters. + * + * @param id the id of the group + * @param location the relative location of the group + * @param parent the id of the group this group is located relative to + * @param fillPercentage the percentage of space this group takes up relative to its parent + */ + public void definePath(String id, Location location, String parent, float fillPercentage) { + data.add(new PathData(id, parent, location, fillPercentage)); + } + + /** + * Creates a List of GroupLocationPaths consisting of the paths that have + * been defined. + * + * @param rootID the id of the root group. + * @return a List of GroupLocationPaths consisting of the paths that have + * been defined. + */ + public List createPaths(String rootID) { + Map paths = new HashMap(); + List parents = new ArrayList(); + + // find all the paths whose parent is root + for (Iterator iter = data.iterator(); iter.hasNext();) { + PathData pathData = iter.next(); + if (pathData.parent.equals(rootID)) { + iter.remove(); + GroupPathElement element = new GroupPathElement(pathData.id, pathData.location, pathData.fill); + GroupLocationPath path = new GroupLocationPath(pathData.id, element); + paths.put(pathData.id, path); + parents.add(pathData.id); + } + } + + findPaths(parents, paths); + + return new ArrayList(paths.values()); + } + + private void findPaths(List parents, Map paths) { + List newParents = new ArrayList(); + for (String parent : parents) { + for (Iterator iter = data.iterator(); iter.hasNext();) { + PathData pathData = iter.next(); + if (pathData.parent.equals(parent)) { + iter.remove(); + GroupPathElement element = new GroupPathElement(pathData.id, pathData.location, pathData.fill); + GroupLocationPath path = new GroupLocationPath(pathData.id, element, paths.get(parent)); + paths.put(pathData.id, path); + newParents.add(pathData.id); + } + } + } + + if (newParents.size() > 0) findPaths(newParents, paths); + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/GroupPathElement.java b/festc_saf_ui/src/saf/core/ui/dock/GroupPathElement.java index 0517d8c..6462cd9 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/GroupPathElement.java +++ b/festc_saf_ui/src/saf/core/ui/dock/GroupPathElement.java @@ -1,62 +1,62 @@ -package saf.core.ui.dock; - -import bibliothek.gui.dock.common.location.CBaseLocation; -import bibliothek.gui.dock.common.location.TreeLocationNode; -import bibliothek.gui.dock.common.location.TreeLocationRoot; -import bibliothek.gui.dock.common.location.AbstractTreeLocation; - -/** - * An element in a GroupPath. This defines the location - * and size of a group space with respect to its parent and can produce - * the correct CLocation. - * - * @author Nick Collier - */ -public class GroupPathElement { - - private Location groupLocation; - private float fill; - private String id; - - /** - * Creates a GroupPathElement with the specified location and fill. - * - * @param id the id of the group - * @param location the relative location of the group - * @param fill the fill percentage of this group - */ - public GroupPathElement(String id, Location location, float fill) { - this.groupLocation = location; - this.fill = fill; - this.id = id; - } - - /** - * Gets the id for the group that this is a path element for. - * - * @return the id for the group that this is a path element for. - */ - public String getID() { - return id; - } - - /** - * Adds to the path encapsulated by the specified CBaseLocation. - * - * @param location the CBaseLocation to create the path from - * @return a TreeLocationRoot that encapsulates the new path - */ - public TreeLocationRoot createPath(CBaseLocation location) { - return groupLocation.createPath(location, fill); - } - - /** - * Adds to the path encapsulated by the specified AbstractTreeLocation. - * - * @param location the AbstractTreeLocation to create the path from - * @return a new TreeLocationNode that encapsulates the new path - */ - public TreeLocationNode createPath(AbstractTreeLocation location) { - return groupLocation.createPath(location, fill); - } -} +package saf.core.ui.dock; + +import bibliothek.gui.dock.common.location.CBaseLocation; +import bibliothek.gui.dock.common.location.TreeLocationNode; +import bibliothek.gui.dock.common.location.TreeLocationRoot; +import bibliothek.gui.dock.common.location.AbstractTreeLocation; + +/** + * An element in a GroupPath. This defines the location + * and size of a group space with respect to its parent and can produce + * the correct CLocation. + * + * @author Nick Collier + */ +public class GroupPathElement { + + private Location groupLocation; + private float fill; + private String id; + + /** + * Creates a GroupPathElement with the specified location and fill. + * + * @param id the id of the group + * @param location the relative location of the group + * @param fill the fill percentage of this group + */ + public GroupPathElement(String id, Location location, float fill) { + this.groupLocation = location; + this.fill = fill; + this.id = id; + } + + /** + * Gets the id for the group that this is a path element for. + * + * @return the id for the group that this is a path element for. + */ + public String getID() { + return id; + } + + /** + * Adds to the path encapsulated by the specified CBaseLocation. + * + * @param location the CBaseLocation to create the path from + * @return a TreeLocationRoot that encapsulates the new path + */ + public TreeLocationRoot createPath(CBaseLocation location) { + return groupLocation.createPath(location, fill); + } + + /** + * Adds to the path encapsulated by the specified AbstractTreeLocation. + * + * @param location the AbstractTreeLocation to create the path from + * @return a new TreeLocationNode that encapsulates the new path + */ + public TreeLocationNode createPath(AbstractTreeLocation location) { + return groupLocation.createPath(location, fill); + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/Location.java b/festc_saf_ui/src/saf/core/ui/dock/Location.java index 68d0fe3..802ca80 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/Location.java +++ b/festc_saf_ui/src/saf/core/ui/dock/Location.java @@ -1,75 +1,75 @@ -package saf.core.ui.dock; - -import bibliothek.gui.dock.common.location.CBaseLocation; -import bibliothek.gui.dock.common.location.TreeLocationNode; -import bibliothek.gui.dock.common.location.TreeLocationRoot; -import bibliothek.gui.dock.common.location.AbstractTreeLocation; - -/** - * Enum describing a relative group location. - * - * @author Nick Collier - */ -public enum Location { - - NORTH() { - public TreeLocationRoot createPath(CBaseLocation location, float fill) { - return location.normalNorth(fill); - } - - public TreeLocationNode createPath(AbstractTreeLocation location, float fill) { - return location.north(fill); - } - }, - - SOUTH() { - public TreeLocationRoot createPath(CBaseLocation location, float fill) { - return location.normalSouth(fill); - } - - public TreeLocationNode createPath(AbstractTreeLocation location, float fill) { - return location.south(fill); - } - }, - - EAST() { - public TreeLocationRoot createPath(CBaseLocation location, float fill) { - return location.normalEast(fill); - } - - public TreeLocationNode createPath(AbstractTreeLocation location, float fill) { - return location.east(fill); - } - }, - - WEST() { - public TreeLocationRoot createPath(CBaseLocation location, float fill) { - return location.normalWest(fill); - } - - public TreeLocationNode createPath(AbstractTreeLocation location, float fill) { - return location.west(fill); - } - }; - - /** - * Create TreeLocationRoot using the CBaseLocation and the fill - * - * @param location the CBaseLocation to create the TreeLocationRoot from - * @param fill the percent fill - * @return a TreeLocationRoot - */ - public abstract TreeLocationRoot createPath(CBaseLocation location, float fill); - - - /** - * Adds to the path encapsulateed by the specified TreeLocationNode. - * - * @param location the TreeLocationNode to create the path from - * @param fill the percent fill - * @return a new TreeLocationNode that encapsulates the new path - */ - public abstract TreeLocationNode createPath(AbstractTreeLocation location, float fill); - - -} +package saf.core.ui.dock; + +import bibliothek.gui.dock.common.location.CBaseLocation; +import bibliothek.gui.dock.common.location.TreeLocationNode; +import bibliothek.gui.dock.common.location.TreeLocationRoot; +import bibliothek.gui.dock.common.location.AbstractTreeLocation; + +/** + * Enum describing a relative group location. + * + * @author Nick Collier + */ +public enum Location { + + NORTH() { + public TreeLocationRoot createPath(CBaseLocation location, float fill) { + return location.normalNorth(fill); + } + + public TreeLocationNode createPath(AbstractTreeLocation location, float fill) { + return location.north(fill); + } + }, + + SOUTH() { + public TreeLocationRoot createPath(CBaseLocation location, float fill) { + return location.normalSouth(fill); + } + + public TreeLocationNode createPath(AbstractTreeLocation location, float fill) { + return location.south(fill); + } + }, + + EAST() { + public TreeLocationRoot createPath(CBaseLocation location, float fill) { + return location.normalEast(fill); + } + + public TreeLocationNode createPath(AbstractTreeLocation location, float fill) { + return location.east(fill); + } + }, + + WEST() { + public TreeLocationRoot createPath(CBaseLocation location, float fill) { + return location.normalWest(fill); + } + + public TreeLocationNode createPath(AbstractTreeLocation location, float fill) { + return location.west(fill); + } + }; + + /** + * Create TreeLocationRoot using the CBaseLocation and the fill + * + * @param location the CBaseLocation to create the TreeLocationRoot from + * @param fill the percent fill + * @return a TreeLocationRoot + */ + public abstract TreeLocationRoot createPath(CBaseLocation location, float fill); + + + /** + * Adds to the path encapsulateed by the specified TreeLocationNode. + * + * @param location the TreeLocationNode to create the path from + * @param fill the percent fill + * @return a new TreeLocationNode that encapsulates the new path + */ + public abstract TreeLocationNode createPath(AbstractTreeLocation location, float fill); + + +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/NonRootGroup.java b/festc_saf_ui/src/saf/core/ui/dock/NonRootGroup.java index e1ff000..6b6ca51 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/NonRootGroup.java +++ b/festc_saf_ui/src/saf/core/ui/dock/NonRootGroup.java @@ -1,32 +1,32 @@ -package saf.core.ui.dock; - -import bibliothek.gui.dock.common.CLocation; - -/** - * Encapsulates a perspective's non-root Group. - * @author Nick Collier - */ -public class NonRootGroup extends AbstractGroup { - - private GroupLocationPath path; - - /** - * Creates a NonRootGroup. - * - * @param id the id of the group - * @param path the default location path of the group - */ - public NonRootGroup(String id, GroupLocationPath path) { - super(id); - this.path = path; - } - - /** - * Gets the default location of this Group. - * - * @return the location of this Group. - */ - public CLocation getLocation() { - return path.getLocation(); - } -} +package saf.core.ui.dock; + +import bibliothek.gui.dock.common.CLocation; + +/** + * Encapsulates a perspective's non-root Group. + * @author Nick Collier + */ +public class NonRootGroup extends AbstractGroup { + + private GroupLocationPath path; + + /** + * Creates a NonRootGroup. + * + * @param id the id of the group + * @param path the default location path of the group + */ + public NonRootGroup(String id, GroupLocationPath path) { + super(id); + this.path = path; + } + + /** + * Gets the default location of this Group. + * + * @return the location of this Group. + */ + public CLocation getLocation() { + return path.getLocation(); + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/Perspective.java b/festc_saf_ui/src/saf/core/ui/dock/Perspective.java index 232dc3b..9a5078d 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/Perspective.java +++ b/festc_saf_ui/src/saf/core/ui/dock/Perspective.java @@ -1,144 +1,144 @@ -package saf.core.ui.dock; - -import java.io.File; -import java.io.InputStream; -import java.util.List; -import java.util.Set; -import java.util.prefs.Preferences; - -/** - * Interface for a SAF perspective. A perspective is essentially - * a spatially arranged collection of dockable frames. - * - * @author Nick Collier - */ -public interface Perspective { - - /** - * Gets whether or not this Perspective is the active - * perspective. - * - * @return true if this perspective is active, otherwise false. - */ - boolean isActive(); - - /** - * Loads a layout. Depending on whether this Perspective uses - * the Preferences to store the layout, the prefs object - * may contain the layout data. - * - * @param prefs repository of the layout data - */ - void loadLayout(Preferences prefs); - - /** - * Saves the frame layout. - * - * @param prefs optional preferences repository specifying where the layout can be saved - */ - void saveLayout(Preferences prefs); - - /** - * Saves the current layout to the specified file. - * - * @param file the file to save the layout to - */ - void saveLayout(File file); - - /** - * Removes the specified dockable from this Perspective. - * - * @param dockable the dockable to remove - */ - void removeDockable(DockableFrame dockable); - - /** - * Gets all the DockableFrames in the specified group. - * - * @param groupID the id of the group whose dockables should be returned - * @return all the DockableFrames in the specified group. - */ - Set getDockables(String groupID); - - /** - * Gets the ids of all the groups in this Perspective. - * - * @return the ids of all the groups in this Perspective. - */ - Set getGroupIDs(); - - - /** - * Gets the id of this Perspective. - * - * @return the id of this Perspective. - */ - String getID(); - - /** - * Gets the name of this Perspective. - * - * @return the name of this Perspective. - */ - String getName(); - - /** - * Creates the root or main group of this Perspective. The root - * group will have the specified id. - * - * @param id the id of the root group - */ - void createRootGroup(String id); - - /** - * Creates group with the specified parameters. - * - * @param id the id of the group - * @param location the location of the group - * @param relativeTo the id of the parent of the created group - * @param fillPercentage the fill percentage of the created group. - */ - void createGroup(String id, Location location, String relativeTo, float fillPercentage); - - /** - * Adds the specified DockableFrame into the specified group. - * - * @param groupId the id of the group - * @param dockable the DockableFrame to add - * @param show whether or not to display the frame - */ - void addDockableFrame(String groupId, DockableFrame dockable, boolean show); - - /** - * Deactivates this Perspective. - */ - void deactivate(); - - /** - * Activates this Perspective. - */ - void activate(); - - - /** - * Gets all the DockableFrames currently in this perspective. - * - * @return all the DockableFrames currently in this perspective. - */ - List getDockables(); - - /** - * Resets the layout of the perspective to match the given file - * @param file the file containing the desired layout - * @return whether or not the layout change was successful - */ - public boolean reset(File file); - - /** - * Resets the layout of the perspective to match the given stream - * @param stream the stream containing the desired layout - * @return whether or not the layout change was successful - */ - public boolean reset(InputStream stream); - -} +package saf.core.ui.dock; + +import java.io.File; +import java.io.InputStream; +import java.util.List; +import java.util.Set; +import java.util.prefs.Preferences; + +/** + * Interface for a SAF perspective. A perspective is essentially + * a spatially arranged collection of dockable frames. + * + * @author Nick Collier + */ +public interface Perspective { + + /** + * Gets whether or not this Perspective is the active + * perspective. + * + * @return true if this perspective is active, otherwise false. + */ + boolean isActive(); + + /** + * Loads a layout. Depending on whether this Perspective uses + * the Preferences to store the layout, the prefs object + * may contain the layout data. + * + * @param prefs repository of the layout data + */ + void loadLayout(Preferences prefs); + + /** + * Saves the frame layout. + * + * @param prefs optional preferences repository specifying where the layout can be saved + */ + void saveLayout(Preferences prefs); + + /** + * Saves the current layout to the specified file. + * + * @param file the file to save the layout to + */ + void saveLayout(File file); + + /** + * Removes the specified dockable from this Perspective. + * + * @param dockable the dockable to remove + */ + void removeDockable(DockableFrame dockable); + + /** + * Gets all the DockableFrames in the specified group. + * + * @param groupID the id of the group whose dockables should be returned + * @return all the DockableFrames in the specified group. + */ + Set getDockables(String groupID); + + /** + * Gets the ids of all the groups in this Perspective. + * + * @return the ids of all the groups in this Perspective. + */ + Set getGroupIDs(); + + + /** + * Gets the id of this Perspective. + * + * @return the id of this Perspective. + */ + String getID(); + + /** + * Gets the name of this Perspective. + * + * @return the name of this Perspective. + */ + String getName(); + + /** + * Creates the root or main group of this Perspective. The root + * group will have the specified id. + * + * @param id the id of the root group + */ + void createRootGroup(String id); + + /** + * Creates group with the specified parameters. + * + * @param id the id of the group + * @param location the location of the group + * @param relativeTo the id of the parent of the created group + * @param fillPercentage the fill percentage of the created group. + */ + void createGroup(String id, Location location, String relativeTo, float fillPercentage); + + /** + * Adds the specified DockableFrame into the specified group. + * + * @param groupId the id of the group + * @param dockable the DockableFrame to add + * @param show whether or not to display the frame + */ + void addDockableFrame(String groupId, DockableFrame dockable, boolean show); + + /** + * Deactivates this Perspective. + */ + void deactivate(); + + /** + * Activates this Perspective. + */ + void activate(); + + + /** + * Gets all the DockableFrames currently in this perspective. + * + * @return all the DockableFrames currently in this perspective. + */ + List getDockables(); + + /** + * Resets the layout of the perspective to match the given file + * @param file the file containing the desired layout + * @return whether or not the layout change was successful + */ + public boolean reset(File file); + + /** + * Resets the layout of the perspective to match the given stream + * @param stream the stream containing the desired layout + * @return whether or not the layout change was successful + */ + public boolean reset(InputStream stream); + +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/RootGroup.java b/festc_saf_ui/src/saf/core/ui/dock/RootGroup.java index 76f196c..2c6a6db 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/RootGroup.java +++ b/festc_saf_ui/src/saf/core/ui/dock/RootGroup.java @@ -1,37 +1,37 @@ -package saf.core.ui.dock; - -import bibliothek.gui.dock.common.CWorkingArea; -import bibliothek.gui.dock.common.CLocation; - -/** - * Encapsulates a perspective's root group. - * - * @author Nick Collier - */ -public class RootGroup extends AbstractGroup { - - private CWorkingArea workingArea; - - /** - * Creates a RootGroup with the specified id. - * - * @param id the id of the root group. - */ - public RootGroup(String id) { - super(id); - } - - // intializes the working area - void initWorkingArea(CWorkingArea workingArea) { - this.workingArea = workingArea; - } - - /** - * Gets the default location of this Group. - * - * @return the location of this Group. - */ - public CLocation getLocation() { - return CLocation.working(workingArea).rectangle(0, 0, 1, 1); - } -} +package saf.core.ui.dock; + +import bibliothek.gui.dock.common.CWorkingArea; +import bibliothek.gui.dock.common.CLocation; + +/** + * Encapsulates a perspective's root group. + * + * @author Nick Collier + */ +public class RootGroup extends AbstractGroup { + + private CWorkingArea workingArea; + + /** + * Creates a RootGroup with the specified id. + * + * @param id the id of the root group. + */ + public RootGroup(String id) { + super(id); + } + + // intializes the working area + void initWorkingArea(CWorkingArea workingArea) { + this.workingArea = workingArea; + } + + /** + * Gets the default location of this Group. + * + * @return the location of this Group. + */ + public CLocation getLocation() { + return CLocation.working(workingArea).rectangle(0, 0, 1, 1); + } +} diff --git a/festc_saf_ui/src/saf/core/ui/dock/StateChanger.java b/festc_saf_ui/src/saf/core/ui/dock/StateChanger.java index a9234fe..464e777 100644 --- a/festc_saf_ui/src/saf/core/ui/dock/StateChanger.java +++ b/festc_saf_ui/src/saf/core/ui/dock/StateChanger.java @@ -1,340 +1,340 @@ -package saf.core.ui.dock; - -import static saf.core.ui.dock.DockingManager.MinimizeLocation.BOTTOM; -import static saf.core.ui.dock.DockingManager.MinimizeLocation.LEFT; -import static saf.core.ui.dock.DockingManager.MinimizeLocation.RIGHT; -import static saf.core.ui.dock.DockingManager.MinimizeLocation.TOP; -import static saf.core.ui.event.DockableFrameEvent.Type.CLOSE; -import static saf.core.ui.event.DockableFrameEvent.Type.FLOAT; -import static saf.core.ui.event.DockableFrameEvent.Type.MAX; -import static saf.core.ui.event.DockableFrameEvent.Type.MIN; -import static saf.core.ui.event.DockableFrameEvent.Type.RESTORE; - -import java.awt.Component; -import java.awt.Container; -import java.awt.FocusTraversalPolicy; -import java.awt.Point; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.LayoutFocusTraversalPolicy; -import javax.swing.SwingUtilities; - -import saf.core.ui.event.DockableFrameEvent; -import saf.core.ui.event.DockableFrameListener; -import bibliothek.gui.dock.common.CControl; -import bibliothek.gui.dock.common.CLocation; -import bibliothek.gui.dock.common.action.predefined.CCloseAction; -import bibliothek.gui.dock.common.intern.CDockable; -import bibliothek.gui.dock.common.location.CFlapIndexLocation; -import bibliothek.gui.dock.common.mode.ExtendedMode; -import bibliothek.gui.dock.displayer.DisplayerFocusTraversalPolicy; -import bibliothek.gui.dock.focus.DockFocusTraversalPolicy; -import bibliothek.gui.dock.station.DockableDisplayer; -import bibliothek.gui.dock.themes.basic.BasicDockableDisplayer; - -/** - * Changes a dockable's state -- minimized, normalized, etc. - * - * @author Nick Collier - */ -public class StateChanger { - - // a functor passed to the fire method - // to call the appropriate listener method - private static interface Fire { - void fire(DockableFrameListener listener, DockableFrameEvent evt); - } - - private CCloseAction closeAction; - private DefaultDockingManager dockingManager; - private List listeners = new ArrayList(); - - /** - * Creates a StateChanger that uses the specified control to effect the - * state changes. - * - * @param control - * the control to use to change the state - * @param dockingManager - * the dockingManger used by this StateChanger - */ - public StateChanger(CControl control, DefaultDockingManager dockingManager) { - this.dockingManager = dockingManager; - closeAction = new CCloseAction(control); - } - - /** - * Adds the specified DockableFrameListener to listener for state changes - * fired by this StateChanger. - * - * @param listener - * the listener to add - */ - public void addDockableFrameListener(DockableFrameListener listener) { - listeners.add(listener); - } - - /** - * Removes the specified DockableFrameListener. - * - * @param listener - * the listener to remove - */ - public void removeDockableFrameListener(DockableFrameListener listener) { - listeners.remove(listener); - } - - /** - * Attempts to close the specified dockable in the specified perspective. - * - * @param perspectiveID - * the perspective id - * @param dockable - * the dockable to close - */ - public void closeDockable(String perspectiveID, CDockable dockable) { - DockableFrameEvent evt = createEvent(dockable, CLOSE); - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableClosing(evt); - } - }); - - if (!evt.isHandled()) { - // rarely the focus policy get screwed up - // leading to StackOverflow and hanging - fixFocusPolicy(evt.getDockable()); - closeAction.close(dockable); - dockingManager.removeDockable(perspectiveID, dockable); - - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableClosed(evt); - } - }); - } - - } - - /** - * Attempts to close the specified dockable in the current perspective. - * - * @param dockable - * the dockable to close - */ - public void closeDockable(CDockable dockable) { - - DockableFrameEvent evt = createEvent(dockable, CLOSE); - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableClosing(evt); - } - }); - - if (!evt.isHandled()) { - // rarely the focus policy get screwed up - // leading to StackOverflow and hanging - fixFocusPolicy(evt.getDockable()); - closeAction.close(dockable); - dockingManager.removeDockable(dockingManager.getPerspective() - .getID(), dockable); - - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableClosed(evt); - } - }); - } - - } - - /** - * Fixes the focus policy of any components in the frame's container - * hierarchy, if necessary. This works around an error arising from - * Swing's focus policies interacting with the dockable frames library. - * - * @param frame the frame that may need fixing - */ - public void fixFocusPolicy(DockableFrame frame) { - Container parent = frame.getContentPane(); - while (parent != null) { - FocusTraversalPolicy policy = parent.getFocusTraversalPolicy(); - if (policy != null - && policy.getClass().getName().equals( - "javax.swing.LegacyGlueFocusTraversalPolicy")) { - - if (parent instanceof BasicDockableDisplayer) { - parent.setFocusTraversalPolicy(new DockFocusTraversalPolicy( - new DisplayerFocusTraversalPolicy((DockableDisplayer)parent),true)); - } else { - parent.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); - } - break; - } - parent = parent.getParent(); - } - } - - /** - * Attempts to restore the specified dockable. - * - * @param dockable - * the dockable to restore - */ - public void restoreDockable(CDockable dockable) { - DockableFrameEvent evt = createEvent(dockable, RESTORE); - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableRestoring(evt); - } - }); - - if (!evt.isHandled()) { - // rarely the focus policy get screwed up - // leading to StackOverflow and hanging - fixFocusPolicy(evt.getDockable()); - dockable.setExtendedMode(ExtendedMode.NORMALIZED); - - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableRestored(evt); - } - }); - } - } - - /** - * Attempts to float the specified dockable. - * - * @param dockable - * the dockable to float - */ - public void floatDockable(CDockable dockable) { - DockableFrameEvent evt = createEvent(dockable, FLOAT); - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableFloating(evt); - } - }); - - if (!evt.isHandled()) { - // dockable.setExtendedMode(CDockable.ExtendedMode.EXTERNALIZED); - - // make sure the dockables location is on top of where it was - // but now externalized - // rarely the focus policy get screwed up - // leading to StackOverflow and hanging - fixFocusPolicy(evt.getDockable()); - Point corner = new Point(); - Component comp = dockable.intern().getComponent(); - SwingUtilities.convertPointToScreen(corner, comp); - dockable.setLocation(CLocation.external(corner.x, corner.y, comp - .getWidth(), comp.getHeight())); - - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableFloated(evt); - } - }); - } - } - - /** - * Attempts to maximize the specified dockable. - * - * @param dockable - * the dockable to maximize - */ - public void maximizeDockable(CDockable dockable) { - DockableFrameEvent evt = createEvent(dockable, MAX); - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableMaximizing(evt); - } - }); - - if (!evt.isHandled()) { - // rarely the focus policy get screwed up - // leading to StackOverflow and hanging - fixFocusPolicy(evt.getDockable()); - dockable.setExtendedMode(ExtendedMode.MAXIMIZED); - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableMaximized(evt); - } - }); - } - } - - /** - * Attempts to minimize the specified dockable to the specified location. - * - * @param dockable - * the dockable to minimize - * @param minLocation - * the location to minimize to - */ - public void minimizeDockable(CDockable dockable, - DockingManager.MinimizeLocation minLocation) { - - DockableFrameEvent evt = createEvent(dockable, MIN); - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableMinimizing(evt); - } - }); - - if (!evt.isHandled()) { - // rarely the focus policy get screwed up - // leading to StackOverflow and hanging - fixFocusPolicy(evt.getDockable()); - - CFlapIndexLocation loc; - if (minLocation == TOP) - loc = CLocation.base().minimalNorth(); - else if (minLocation == BOTTOM) - loc = CLocation.base().minimalSouth(); - else if (minLocation == LEFT) - loc = CLocation.base().minimalWest(); - else if (minLocation == RIGHT) - loc = CLocation.base().minimalEast(); - else - loc = CLocation.base().minimalSouth(); - dockable.setLocation(loc); - - fire(evt, new Fire() { - public void fire(DockableFrameListener listener, - DockableFrameEvent evt) { - listener.dockableMinimized(evt); - } - }); - } - - } - - private DockableFrameEvent createEvent(CDockable dockable, - DockableFrameEvent.Type type) { - DockableFrame frame = dockingManager.getDockableFrameFor(dockable); - return new DockableFrameEvent(type, frame); - } - - // this is a bit of trick to avoid having to type this loop - // over and over again - private void fire(DockableFrameEvent evt, Fire fire) { - for (DockableFrameListener listener : listeners) { - fire.fire(listener, evt); - } - } -} +package saf.core.ui.dock; + +import static saf.core.ui.dock.DockingManager.MinimizeLocation.BOTTOM; +import static saf.core.ui.dock.DockingManager.MinimizeLocation.LEFT; +import static saf.core.ui.dock.DockingManager.MinimizeLocation.RIGHT; +import static saf.core.ui.dock.DockingManager.MinimizeLocation.TOP; +import static saf.core.ui.event.DockableFrameEvent.Type.CLOSE; +import static saf.core.ui.event.DockableFrameEvent.Type.FLOAT; +import static saf.core.ui.event.DockableFrameEvent.Type.MAX; +import static saf.core.ui.event.DockableFrameEvent.Type.MIN; +import static saf.core.ui.event.DockableFrameEvent.Type.RESTORE; + +import java.awt.Component; +import java.awt.Container; +import java.awt.FocusTraversalPolicy; +import java.awt.Point; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.LayoutFocusTraversalPolicy; +import javax.swing.SwingUtilities; + +import saf.core.ui.event.DockableFrameEvent; +import saf.core.ui.event.DockableFrameListener; +import bibliothek.gui.dock.common.CControl; +import bibliothek.gui.dock.common.CLocation; +import bibliothek.gui.dock.common.action.predefined.CCloseAction; +import bibliothek.gui.dock.common.intern.CDockable; +import bibliothek.gui.dock.common.location.CFlapIndexLocation; +import bibliothek.gui.dock.common.mode.ExtendedMode; +import bibliothek.gui.dock.displayer.DisplayerFocusTraversalPolicy; +import bibliothek.gui.dock.focus.DockFocusTraversalPolicy; +import bibliothek.gui.dock.station.DockableDisplayer; +import bibliothek.gui.dock.themes.basic.BasicDockableDisplayer; + +/** + * Changes a dockable's state -- minimized, normalized, etc. + * + * @author Nick Collier + */ +public class StateChanger { + + // a functor passed to the fire method + // to call the appropriate listener method + private static interface Fire { + void fire(DockableFrameListener listener, DockableFrameEvent evt); + } + + private CCloseAction closeAction; + private DefaultDockingManager dockingManager; + private List listeners = new ArrayList(); + + /** + * Creates a StateChanger that uses the specified control to effect the + * state changes. + * + * @param control + * the control to use to change the state + * @param dockingManager + * the dockingManger used by this StateChanger + */ + public StateChanger(CControl control, DefaultDockingManager dockingManager) { + this.dockingManager = dockingManager; + closeAction = new CCloseAction(control); + } + + /** + * Adds the specified DockableFrameListener to listener for state changes + * fired by this StateChanger. + * + * @param listener + * the listener to add + */ + public void addDockableFrameListener(DockableFrameListener listener) { + listeners.add(listener); + } + + /** + * Removes the specified DockableFrameListener. + * + * @param listener + * the listener to remove + */ + public void removeDockableFrameListener(DockableFrameListener listener) { + listeners.remove(listener); + } + + /** + * Attempts to close the specified dockable in the specified perspective. + * + * @param perspectiveID + * the perspective id + * @param dockable + * the dockable to close + */ + public void closeDockable(String perspectiveID, CDockable dockable) { + DockableFrameEvent evt = createEvent(dockable, CLOSE); + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableClosing(evt); + } + }); + + if (!evt.isHandled()) { + // rarely the focus policy get screwed up + // leading to StackOverflow and hanging + fixFocusPolicy(evt.getDockable()); + closeAction.close(dockable); + dockingManager.removeDockable(perspectiveID, dockable); + + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableClosed(evt); + } + }); + } + + } + + /** + * Attempts to close the specified dockable in the current perspective. + * + * @param dockable + * the dockable to close + */ + public void closeDockable(CDockable dockable) { + + DockableFrameEvent evt = createEvent(dockable, CLOSE); + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableClosing(evt); + } + }); + + if (!evt.isHandled()) { + // rarely the focus policy get screwed up + // leading to StackOverflow and hanging + fixFocusPolicy(evt.getDockable()); + closeAction.close(dockable); + dockingManager.removeDockable(dockingManager.getPerspective() + .getID(), dockable); + + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableClosed(evt); + } + }); + } + + } + + /** + * Fixes the focus policy of any components in the frame's container + * hierarchy, if necessary. This works around an error arising from + * Swing's focus policies interacting with the dockable frames library. + * + * @param frame the frame that may need fixing + */ + public void fixFocusPolicy(DockableFrame frame) { + Container parent = frame.getContentPane(); + while (parent != null) { + FocusTraversalPolicy policy = parent.getFocusTraversalPolicy(); + if (policy != null + && policy.getClass().getName().equals( + "javax.swing.LegacyGlueFocusTraversalPolicy")) { + + if (parent instanceof BasicDockableDisplayer) { + parent.setFocusTraversalPolicy(new DockFocusTraversalPolicy( + new DisplayerFocusTraversalPolicy((DockableDisplayer)parent),true)); + } else { + parent.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); + } + break; + } + parent = parent.getParent(); + } + } + + /** + * Attempts to restore the specified dockable. + * + * @param dockable + * the dockable to restore + */ + public void restoreDockable(CDockable dockable) { + DockableFrameEvent evt = createEvent(dockable, RESTORE); + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableRestoring(evt); + } + }); + + if (!evt.isHandled()) { + // rarely the focus policy get screwed up + // leading to StackOverflow and hanging + fixFocusPolicy(evt.getDockable()); + dockable.setExtendedMode(ExtendedMode.NORMALIZED); + + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableRestored(evt); + } + }); + } + } + + /** + * Attempts to float the specified dockable. + * + * @param dockable + * the dockable to float + */ + public void floatDockable(CDockable dockable) { + DockableFrameEvent evt = createEvent(dockable, FLOAT); + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableFloating(evt); + } + }); + + if (!evt.isHandled()) { + // dockable.setExtendedMode(CDockable.ExtendedMode.EXTERNALIZED); + + // make sure the dockables location is on top of where it was + // but now externalized + // rarely the focus policy get screwed up + // leading to StackOverflow and hanging + fixFocusPolicy(evt.getDockable()); + Point corner = new Point(); + Component comp = dockable.intern().getComponent(); + SwingUtilities.convertPointToScreen(corner, comp); + dockable.setLocation(CLocation.external(corner.x, corner.y, comp + .getWidth(), comp.getHeight())); + + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableFloated(evt); + } + }); + } + } + + /** + * Attempts to maximize the specified dockable. + * + * @param dockable + * the dockable to maximize + */ + public void maximizeDockable(CDockable dockable) { + DockableFrameEvent evt = createEvent(dockable, MAX); + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableMaximizing(evt); + } + }); + + if (!evt.isHandled()) { + // rarely the focus policy get screwed up + // leading to StackOverflow and hanging + fixFocusPolicy(evt.getDockable()); + dockable.setExtendedMode(ExtendedMode.MAXIMIZED); + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableMaximized(evt); + } + }); + } + } + + /** + * Attempts to minimize the specified dockable to the specified location. + * + * @param dockable + * the dockable to minimize + * @param minLocation + * the location to minimize to + */ + public void minimizeDockable(CDockable dockable, + DockingManager.MinimizeLocation minLocation) { + + DockableFrameEvent evt = createEvent(dockable, MIN); + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableMinimizing(evt); + } + }); + + if (!evt.isHandled()) { + // rarely the focus policy get screwed up + // leading to StackOverflow and hanging + fixFocusPolicy(evt.getDockable()); + + CFlapIndexLocation loc; + if (minLocation == TOP) + loc = CLocation.base().minimalNorth(); + else if (minLocation == BOTTOM) + loc = CLocation.base().minimalSouth(); + else if (minLocation == LEFT) + loc = CLocation.base().minimalWest(); + else if (minLocation == RIGHT) + loc = CLocation.base().minimalEast(); + else + loc = CLocation.base().minimalSouth(); + dockable.setLocation(loc); + + fire(evt, new Fire() { + public void fire(DockableFrameListener listener, + DockableFrameEvent evt) { + listener.dockableMinimized(evt); + } + }); + } + + } + + private DockableFrameEvent createEvent(CDockable dockable, + DockableFrameEvent.Type type) { + DockableFrame frame = dockingManager.getDockableFrameFor(dockable); + return new DockableFrameEvent(type, frame); + } + + // this is a bit of trick to avoid having to type this loop + // over and over again + private void fire(DockableFrameEvent evt, Fire fire) { + for (DockableFrameListener listener : listeners) { + fire.fire(listener, evt); + } + } +} diff --git a/festc_saf_ui/src/saf/core/ui/event/DockableFrameAdapter.java b/festc_saf_ui/src/saf/core/ui/event/DockableFrameAdapter.java index 59457c1..7930c5b 100644 --- a/festc_saf_ui/src/saf/core/ui/event/DockableFrameAdapter.java +++ b/festc_saf_ui/src/saf/core/ui/event/DockableFrameAdapter.java @@ -1,115 +1,115 @@ -package saf.core.ui.event; - -import saf.core.ui.event.DockableFrameEvent; - -/** - * Emtpy adapter style implementation of DockableFrameListener. This is useful - * when you want a DockableFrameListener but do not want to implement all the - * methos. - * - * @author Nick Collier - */ -public class DockableFrameAdapter implements DockableFrameListener { - - /** - * Invoked when a dockable is closed. - * - * @param evt the detailes of the close event - */ - - public void dockableClosed(DockableFrameEvent evt) { - - } - - /** - * Invoked when a dockable receives a close request. The - * close can be overriden by setting the events - * handled property to true. - * - * @param evt details the close request - */ - public void dockableClosing(DockableFrameEvent evt) { - - } - - /** - * Invoked when a dockable is floated. - * - * @param evt details of the event - */ - public void dockableFloated(DockableFrameEvent evt) { - - } - - /** - * Invoked when a dockable receives a float request. The - * float can be overriden by setting the events - * handled property to true. - * - * @param evt details the float request - */ - public void dockableFloating(DockableFrameEvent evt) { - - } - - /** - * Invoked when a dockable is maximized. - * - * @param evt details of the event - */ - public void dockableMaximized(DockableFrameEvent evt) { - - } - - /** - * Invoked when a dockable receives a maxmizing - * request. The maximize can be overriden by setting the events - * handled property to true. - * - * @param evt details the maximize request - */ - public void dockableMaximizing(DockableFrameEvent evt) { - - } - - /** - * Invoked when a dockable is minimized. - * - * @param evt details of the event - */ - public void dockableMinimized(DockableFrameEvent evt) { - - } - - /** - * Invoked when a dockable receives a minimizing - * request. The minimize can be overriden by setting the events - * handled property to true. - * - * @param evt details the minimize request - */ - public void dockableMinimizing(DockableFrameEvent evt) { - - } - - /** - * Invoked when a dockable is restored to its default docking position - * from a floated, minimized, or maximized state. - * - * @param evt details of the event - */ - public void dockableRestored(DockableFrameEvent evt) { - - } - - /** - * Invoked when a dockable receives a restore request. The - * restore can be overriden by setting the events - * handled property to true. - * - * @param evt details the restore request - */ - public void dockableRestoring(DockableFrameEvent evt) { - - } -} +package saf.core.ui.event; + +import saf.core.ui.event.DockableFrameEvent; + +/** + * Emtpy adapter style implementation of DockableFrameListener. This is useful + * when you want a DockableFrameListener but do not want to implement all the + * methos. + * + * @author Nick Collier + */ +public class DockableFrameAdapter implements DockableFrameListener { + + /** + * Invoked when a dockable is closed. + * + * @param evt the detailes of the close event + */ + + public void dockableClosed(DockableFrameEvent evt) { + + } + + /** + * Invoked when a dockable receives a close request. The + * close can be overriden by setting the events + * handled property to true. + * + * @param evt details the close request + */ + public void dockableClosing(DockableFrameEvent evt) { + + } + + /** + * Invoked when a dockable is floated. + * + * @param evt details of the event + */ + public void dockableFloated(DockableFrameEvent evt) { + + } + + /** + * Invoked when a dockable receives a float request. The + * float can be overriden by setting the events + * handled property to true. + * + * @param evt details the float request + */ + public void dockableFloating(DockableFrameEvent evt) { + + } + + /** + * Invoked when a dockable is maximized. + * + * @param evt details of the event + */ + public void dockableMaximized(DockableFrameEvent evt) { + + } + + /** + * Invoked when a dockable receives a maxmizing + * request. The maximize can be overriden by setting the events + * handled property to true. + * + * @param evt details the maximize request + */ + public void dockableMaximizing(DockableFrameEvent evt) { + + } + + /** + * Invoked when a dockable is minimized. + * + * @param evt details of the event + */ + public void dockableMinimized(DockableFrameEvent evt) { + + } + + /** + * Invoked when a dockable receives a minimizing + * request. The minimize can be overriden by setting the events + * handled property to true. + * + * @param evt details the minimize request + */ + public void dockableMinimizing(DockableFrameEvent evt) { + + } + + /** + * Invoked when a dockable is restored to its default docking position + * from a floated, minimized, or maximized state. + * + * @param evt details of the event + */ + public void dockableRestored(DockableFrameEvent evt) { + + } + + /** + * Invoked when a dockable receives a restore request. The + * restore can be overriden by setting the events + * handled property to true. + * + * @param evt details the restore request + */ + public void dockableRestoring(DockableFrameEvent evt) { + + } +} diff --git a/festc_saf_ui/src/saf/core/ui/event/DockableSelectionSupport.java b/festc_saf_ui/src/saf/core/ui/event/DockableSelectionSupport.java index 38e5743..04ad9da 100644 --- a/festc_saf_ui/src/saf/core/ui/event/DockableSelectionSupport.java +++ b/festc_saf_ui/src/saf/core/ui/event/DockableSelectionSupport.java @@ -1,75 +1,75 @@ -package saf.core.ui.event; - -import bibliothek.gui.dock.common.event.CFocusListener; -import bibliothek.gui.dock.common.intern.CDockable; -import saf.core.ui.dock.DefaultDockingManager; -import saf.core.ui.dock.DockableFrame; - -import java.util.ArrayList; -import java.util.List; - -/** - * Utility support class for managing dockable frame - * selection events. For this to be effective it must be - * added as CFocusListener to a CControl. - * - * @author Nick Collier - */ -public class DockableSelectionSupport implements CFocusListener { - - private DefaultDockingManager manager; - - public DockableSelectionSupport(DefaultDockingManager manager) { - this.manager = manager; - } - - private List listeners = new ArrayList(); - - public void addSelectionListener(DockableSelectionListener listener) { - listeners.add(listener); - } - - public void removeSelectionListener(DockableSelectionListener listener) { - listeners.remove(listener); - } - - /** - * Called when a dockable gains focus. - * - * @param dockable the dockable that gained focus - */ - public void focusGained(CDockable dockable) { - DockableSelectionEvent evt = createEvent(dockable, DockableSelectionEvent.Type.GAINED); - DockableFrame frame = evt.getDockable(); - // frame can be null if its the "invisible" working area that gets - // the focus - if (frame != null) { - manager.getBarManager().selectMenuItem(frame.getID()); - for (DockableSelectionListener listener : listeners) { - listener.selectionGained(evt); - } - } - } - - /** - * Called when a dockable looses focus. - * - * @param dockable the dockable that has lost focus - */ - public void focusLost(CDockable dockable) { - DockableSelectionEvent evt = createEvent(dockable, DockableSelectionEvent.Type.LOST); - // frame can be null if its the "invisible" working area that gets - // the focus - if (evt.getDockable() != null) { - for (DockableSelectionListener listener : listeners) { - listener.selectionLost(evt); - } - } - - } - - private DockableSelectionEvent createEvent(CDockable dockable, DockableSelectionEvent.Type type) { - DockableFrame frame = manager.getDockableFrameFor(dockable); - return new DockableSelectionEvent(frame, type); - } -} +package saf.core.ui.event; + +import bibliothek.gui.dock.common.event.CFocusListener; +import bibliothek.gui.dock.common.intern.CDockable; +import saf.core.ui.dock.DefaultDockingManager; +import saf.core.ui.dock.DockableFrame; + +import java.util.ArrayList; +import java.util.List; + +/** + * Utility support class for managing dockable frame + * selection events. For this to be effective it must be + * added as CFocusListener to a CControl. + * + * @author Nick Collier + */ +public class DockableSelectionSupport implements CFocusListener { + + private DefaultDockingManager manager; + + public DockableSelectionSupport(DefaultDockingManager manager) { + this.manager = manager; + } + + private List listeners = new ArrayList(); + + public void addSelectionListener(DockableSelectionListener listener) { + listeners.add(listener); + } + + public void removeSelectionListener(DockableSelectionListener listener) { + listeners.remove(listener); + } + + /** + * Called when a dockable gains focus. + * + * @param dockable the dockable that gained focus + */ + public void focusGained(CDockable dockable) { + DockableSelectionEvent evt = createEvent(dockable, DockableSelectionEvent.Type.GAINED); + DockableFrame frame = evt.getDockable(); + // frame can be null if its the "invisible" working area that gets + // the focus + if (frame != null) { + manager.getBarManager().selectMenuItem(frame.getID()); + for (DockableSelectionListener listener : listeners) { + listener.selectionGained(evt); + } + } + } + + /** + * Called when a dockable looses focus. + * + * @param dockable the dockable that has lost focus + */ + public void focusLost(CDockable dockable) { + DockableSelectionEvent evt = createEvent(dockable, DockableSelectionEvent.Type.LOST); + // frame can be null if its the "invisible" working area that gets + // the focus + if (evt.getDockable() != null) { + for (DockableSelectionListener listener : listeners) { + listener.selectionLost(evt); + } + } + + } + + private DockableSelectionEvent createEvent(CDockable dockable, DockableSelectionEvent.Type type) { + DockableFrame frame = manager.getDockableFrameFor(dockable); + return new DockableSelectionEvent(frame, type); + } +} diff --git a/festc_saf_ui/src/saf/core/ui/event/PerspectiveSelectionSupport.java b/festc_saf_ui/src/saf/core/ui/event/PerspectiveSelectionSupport.java index ffa667d..e13268b 100644 --- a/festc_saf_ui/src/saf/core/ui/event/PerspectiveSelectionSupport.java +++ b/festc_saf_ui/src/saf/core/ui/event/PerspectiveSelectionSupport.java @@ -1,75 +1,75 @@ -package saf.core.ui.event; - -import saf.core.ui.dock.Perspective; -import saf.core.ui.dock.DockingManager; - -import java.util.List; -import java.util.ArrayList; - -/** - * Utility support class for firing perspective related events - * to perspective selection listeners. - * - * @author Nick Collier - */ -public class PerspectiveSelectionSupport { - - private List listeners = new ArrayList(); - private DockingManager manager; - - /** - * Creates a PerspectiveSelectionSupport that will support the - * selection of perspectives manager by the specified manager. - * - * @param manager the manager whose perspectives this class works with - */ - public PerspectiveSelectionSupport(DockingManager manager) { - this.manager = manager; - } - - /** - * Adds a PerspectiveSelectionListener to the list of listeners to notify - * when the perspective changes. - * - * @param listener the listener to add - */ - public void addPerspectiveListener(PerspectiveSelectionListener listener) { - listeners.add(listener); - } - - /** - * Removes a PerspectiveSelectionListener from the list of listeners to notify - * when the perspective changes. - * - * @param listener the listener to remove - */ - public void removePerspectiveListener(PerspectiveSelectionListener listener) { - listeners.remove(listener); - } - - /** - * Fires a perspective changing notification to all registered listeners. - * - * @param currentPerspective the current perspective that will become the old perspective - * @param newPerspective the perspectve that will be the newly selected perspective - */ - public void firePerpectiveChanging(Perspective currentPerspective, Perspective newPerspective) { - PerspectiveSelectionEvent evt = new PerspectiveSelectionEvent(manager, currentPerspective, newPerspective); - for (PerspectiveSelectionListener listener : listeners) { - listener.perspectiveChanging(evt); - } - } - - /** - * Fires a perspective changed notification to all registered listeners. - * - * @param priorPerspective the previously selected perspective - * @param newPerspective the newly selected perspective - */ - public void firePerpectiveChanged(Perspective priorPerspective, Perspective newPerspective) { - PerspectiveSelectionEvent evt = new PerspectiveSelectionEvent(manager, priorPerspective, newPerspective); - for (PerspectiveSelectionListener listener : listeners) { - listener.perspectiveChanged(evt); - } - } -} +package saf.core.ui.event; + +import saf.core.ui.dock.Perspective; +import saf.core.ui.dock.DockingManager; + +import java.util.List; +import java.util.ArrayList; + +/** + * Utility support class for firing perspective related events + * to perspective selection listeners. + * + * @author Nick Collier + */ +public class PerspectiveSelectionSupport { + + private List listeners = new ArrayList(); + private DockingManager manager; + + /** + * Creates a PerspectiveSelectionSupport that will support the + * selection of perspectives manager by the specified manager. + * + * @param manager the manager whose perspectives this class works with + */ + public PerspectiveSelectionSupport(DockingManager manager) { + this.manager = manager; + } + + /** + * Adds a PerspectiveSelectionListener to the list of listeners to notify + * when the perspective changes. + * + * @param listener the listener to add + */ + public void addPerspectiveListener(PerspectiveSelectionListener listener) { + listeners.add(listener); + } + + /** + * Removes a PerspectiveSelectionListener from the list of listeners to notify + * when the perspective changes. + * + * @param listener the listener to remove + */ + public void removePerspectiveListener(PerspectiveSelectionListener listener) { + listeners.remove(listener); + } + + /** + * Fires a perspective changing notification to all registered listeners. + * + * @param currentPerspective the current perspective that will become the old perspective + * @param newPerspective the perspectve that will be the newly selected perspective + */ + public void firePerpectiveChanging(Perspective currentPerspective, Perspective newPerspective) { + PerspectiveSelectionEvent evt = new PerspectiveSelectionEvent(manager, currentPerspective, newPerspective); + for (PerspectiveSelectionListener listener : listeners) { + listener.perspectiveChanging(evt); + } + } + + /** + * Fires a perspective changed notification to all registered listeners. + * + * @param priorPerspective the previously selected perspective + * @param newPerspective the newly selected perspective + */ + public void firePerpectiveChanged(Perspective priorPerspective, Perspective newPerspective) { + PerspectiveSelectionEvent evt = new PerspectiveSelectionEvent(manager, priorPerspective, newPerspective); + for (PerspectiveSelectionListener listener : listeners) { + listener.perspectiveChanged(evt); + } + } +} diff --git a/festc_saf_ui/src/saf/core/ui/msg/package-info.java b/festc_saf_ui/src/saf/core/ui/msg/package-info.java index 91d0d18..43d1f8a 100644 --- a/festc_saf_ui/src/saf/core/ui/msg/package-info.java +++ b/festc_saf_ui/src/saf/core/ui/msg/package-info.java @@ -1,8 +1,8 @@ -/** - * - */ -/** - * @author Dongmei Yang - * - */ +/** + * + */ +/** + * @author Dongmei Yang + * + */ package saf.core.ui.msg; \ No newline at end of file diff --git a/festc_saf_ui/src/saf/core/ui/util/package-info.java b/festc_saf_ui/src/saf/core/ui/util/package-info.java index ecdec24..181c810 100644 --- a/festc_saf_ui/src/saf/core/ui/util/package-info.java +++ b/festc_saf_ui/src/saf/core/ui/util/package-info.java @@ -1,8 +1,8 @@ -/** - * - */ -/** - * @author Dongmei Yang - * - */ +/** + * + */ +/** + * @author Dongmei Yang + * + */ package saf.core.ui.util; \ No newline at end of file