001    /**
002     $Revision: 1.44 $"
003     $Id: DBSApiLogic.java,v 1.44 2006/12/08 20:59:24 sekhri Exp $"
004     *
005     */
006    
007    package dbs.api;
008    import java.sql.Connection;
009    import java.sql.ResultSet;
010    import java.sql.PreparedStatement;
011    import java.io.Writer;
012    import java.util.regex.Pattern;
013    import java.util.Hashtable;
014    import java.util.Vector;
015    import java.util.Enumeration;
016    import java.util.UUID;
017    import db.DBManagement;
018    import dbs.sql.DBSSql;
019    import dbs.util.DBSUtil;
020    import dbs.DBSException;
021    
022    import dbs.DBSConstants;
023    
024    /**
025    * A class that has the core business logic of the DBS API. Here all the API is defined and implemented. The signature for the API is internal to DBS and is not exposed to the clients. There is another class <code>dbs.api.DBSApi</code> that has an interface for the clients. All these low level APIs are invoked from <code>dbs.api.DBSApi</code>. 
026    * @author sekhri
027    */
028    public class DBSApiLogic {
029            //private static String SAFE_PATH = "[-A-Za-z0-9_./\\p{%}]";
030            //private static String SAFE_NAME = "[-A-Za-z0-9_.]";
031    
032            //A regular expression used to validate a path that will not contain any special characters or blank space but can contain slashes.
033            private static String SAFE_PATH = "[-\\w_\\.%/]+";
034            //A regular expression used to validate a word. This word will not contain any blank space or special characters.
035            private static String SAFE_WORD = "[-\\w_\\.%]+";
036            //A regular expression used to validate a sentence. This word will not contain any special characters but can contain blank spaces.
037            private static String SAFE_STR = "[-\\w_\\.% ]+";
038            //A regular expression used to validate a block name. This word will not contain any special characters or blank spaces but can contain slashes.
039            private static String SAFE_BLOCK = "[-\\w_\\.%#/]+";
040            //A regular expression used to validate a path that will contain exactly three slashes.
041            private static String VALID_PATH = "^/([^/]+)/([^/]+)/([^/]+)";
042            //A regular expression used to validate a block name that will contain exactly thw slashes and a hash.
043            private static String VALID_BLOCK = "^/([^/]+)/([^/]+)#([^/]+)";
044    
045            /**
046            * Constructs a DBSApiLogic object that can be used to invoke several APIs. The constructor does notthing.
047            */
048            public DBSApiLogic() {}
049    
050            
051            /**
052             * Lists all the primary datasets from the database in a xml format. This method makes one sql query, execute it, fetch the results and packs and write it in xml format to the output stream. The query that it executes get generated by <code>dbs.DBSSql.listPrimaryDatasets</code> method. A sample XML that is written to the output stream is like <br>
053             * <code><"primary-dataset id='278' annotation='aaaaf9' primary_name='This_is_a_test_primary' start_date='NOV' end_date='DEC' creation_date='2006-12-06 10:35:22.0' last_modification_date='2006-12-06 10:35:22.0' trigger_path_description='' mc_channel_description='' mc_production='' mc_decay_chain='' other_description='' type='VALID' created_by='ANZARDN' last_modified_by='ANZARDN'"/></code>
054             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
055             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
056             * @param pattern a parameter passed in from the client that can contain wild card characters. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
057             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied pattern is invalid or the database connection is unavailable.
058             */
059            public void listPrimaryDatasets(Connection conn, Writer out, String pattern) throws Exception {
060                     
061                    PreparedStatement ps = null;
062                    ResultSet rs =  null;
063                    try {
064                            ps = DBSSql.listPrimaryDatasets(conn, getPattern(pattern, "primary_dataset_name_pattern"));
065                            rs =  ps.executeQuery();
066                            while(rs.next()) {
067                                    out.write(((String) "<primary-dataset id='" + get(rs, "ID") +
068                                                    "' annotation='" + get(rs, "ANNOTATION") +
069                                                    "' primary_name='" + get(rs, "PRIMARY_NAME") +
070                                                    "' start_date='" + get(rs, "START_DATE") +
071                                                    "' end_date='" + get(rs, "END_DATE") +
072                                                    "' creation_date='" + get(rs, "CREATION_DATE") +
073                                                    "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
074                                                    "' trigger_path_description='" + get(rs, "TRIGGER_PATH_DESCRIPTION") +
075                                                    "' mc_channel_description='" + get(rs, "MC_CHANNEL_DESCRIPTION") +
076                                                    "' mc_production='" + get(rs, "MC_PRODUCTION") +
077                                                    "' mc_decay_chain='" + get(rs, "MC_DECAY_CHAIN") +
078                                                    "' other_description='" + get(rs, "OTHER_DESCRIPTION") +
079                                                    "' type='" + get(rs, "TYPE") +
080                                                    "' created_by='" + get(rs, "CREATED_BY") +
081                                                    "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
082                                                    "'/>\n"));
083                            }
084                    } finally { 
085                            if (rs != null) rs.close();
086                            if (ps != null) ps.close(); 
087                    }
088            }
089    
090            /**
091             * Lists all the processed datasets from the database in a xml format. This method makes one sql query, execute it, fetch the results and packs and write it in xml format to the output stream. The query that it executes get generated by <code>dbs.DBSSql.listProcessedDatasets</code> method. A sample XML that is written to the output stream is like <br>
092             * <code><"processed-dataset id='1' primary_datatset_name='TestPrimary' processed_datatset_name='TestProcessed' creation_date='2006-11-29 16:39:48.0' last_modification_date='2006-11-29 16:39:48.0' physics_group_name='BPositive' physics_group_convener='ANZARDN' created_by='ANZARDN' last_modified_by='ANZARDN'"> <br> 
093             * <"data_tier name='SIM'"/> <"data_tier name='HIT'"/> <"algorithm app_version='TestVersio' app_family_name='AppFamily011' app_executable_name='TestExe011' ps_name='MyFirstParam01'"/> <"algorithm app_version='TestVersion0111' app_family_name='AppFamily01' app_executable_name='TestExe01' ps_name='MyFirstParam01'"/> <"/processed-dataset"> </code>
094             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
095             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
096             * @param patternPrim a parameter passed in from the client that can contain wild card characters for primary dataset name. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
097             * @param patternDT a parameter passed in from the client that can contain wild card characters for data tier name. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
098             * @param patternProc a parameter passed in from the client that can contain wild card characters for processed dataset name. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
099             * @param patternVer a parameter passed in from the client that can contain wild card characters for application version. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
100             * @param patternFam a parameter passed in from the client that can contain wild card characters for application family. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
101             * @param patternExe a parameter passed in from the client that can contain wild card characters for application executable name. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
102             * @param patternPS a parameter passed in from the client that can contain wild card characters for parameter set name. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
103             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied patterns are invalid or the database connection is unavailable.
104             */
105            public void listProcessedDatasets(Connection conn, Writer out, String patternPrim, String patternDT, String patternProc, String patternVer, String patternFam, String patternExe, String patternPS) throws Exception {
106                    String prevDS = "";
107                    String prevTier = "";
108                    String prevExe = "";
109                    String prevFam = "";
110                    String prevVer = "";
111                    String prevPS = "";
112                    // When data is returned from the database, a bunch of tiers and application are returned in random order, so we need
113                    // to store all of them in a vector so that while writing xml, previously written data tier does not get written again.
114                    Vector dtVec = null; 
115                    
116                    //The xml genrated is nested and this flag is needed to know if first time a tag needs to be written
117                    boolean first = true; 
118    
119                    PreparedStatement ps = null;
120                    ResultSet rs =  null;
121                    try {
122                            ps = DBSSql.listProcessedDatasets(conn, 
123                                            getPattern(patternPrim, "primary_datatset_name_pattern"), 
124                                            getPattern(patternDT, "data_tier_name_pattern"), 
125                                            getPattern(patternProc, "processed_datatset_name_pattern"), 
126                                            getPattern(patternVer, "app_version"), 
127                                            getPattern(patternFam, "app_family_name"), 
128                                            getPattern(patternExe, "app_executable_name"), 
129                                            getPattern(patternPS, "parameterset_name"));
130                            rs =  ps.executeQuery();
131                            while(rs.next()) {
132                                    //String path = "/" + get(rs, "primary_name") + "/" + get(rs, "data_tier") + "/" + get(rs, "processed_name");
133                                    String procDSID = get(rs, "ID");
134                                    String tier = get(rs, "DATA_TIER");
135                                    String fam = get(rs, "APP_FAMILY_NAME");
136                                    String exe = get(rs, "APP_EXECUTABLE_NAME");
137                                    String ver = get(rs, "APP_VERSION");
138                                    String pset = get(rs, "PS_NAME");
139            
140                                    if( !prevDS.equals(procDSID) && ! first) {
141                                            out.write(((String) "</processed-dataset>\n")); 
142                                    }
143                                    if( !prevDS.equals(procDSID) || first) {
144                                            out.write(((String) "<processed-dataset id='" + get(rs, "ID") + 
145                                                            //"' path='" +  get(rs, "PATH") +
146                                                            "' primary_datatset_name='" +  get(rs, "PRIMARY_DATATSET_NAME") +
147                                                            "' processed_datatset_name='" +  get(rs, "PROCESSED_DATATSET_NAME") +
148                                                            "' creation_date='" + get(rs, "CREATION_DATE") +
149                                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
150                                                            "' physics_group_name='" + get(rs, "PHYSICS_GROUP_NAME") +
151                                                            "' physics_group_convener='" + get(rs, "PHYSICS_GROUP_CONVENER") +
152                                                            "' created_by='" + get(rs, "CREATED_BY") +
153                                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
154                                                            "'>\n"));
155                                            first = false;
156                                            prevDS = procDSID;
157                                            dtVec = new Vector();// Or dtVec.removeAllElements();
158                                    }
159                                    if( (!prevTier.equals(tier) || first) && !dtVec.contains(tier) ) {
160                                            out.write(((String) "\t<data_tier name='" + tier + "'/>\n"));
161                                            dtVec.add(tier);
162                                            prevTier = tier;
163                                    }
164                                    if( !prevExe.equals(exe) || !prevFam.equals(fam) || !prevVer.equals(ver) || !prevPS.equals(pset) || first) {
165                                            out.write(((String) "\t<algorithm app_version='" + ver + 
166                                                                "' app_family_name='" + fam + "' app_executable_name='" + 
167                                                                exe + "' ps_name='" + pset + "'/>\n"));
168                                            prevExe = exe;
169                                            prevFam = fam;
170                                            prevVer = ver;
171                                            prevPS = pset;
172                                    }
173                            }
174                    } finally { 
175                            if (rs != null) rs.close();
176                            if (ps != null) ps.close();
177                    }
178    
179                    if (!first) out.write(((String) "</processed-dataset>\n")); 
180            }
181    
182            /**
183             * Lists all the algorithms/applications from the database in a xml format. This method makes one sql query, execute it, fetch the results and packs and write it in xml format to the output stream. The query that it executes get generated by <code>dbs.DBSSql.listAlgorithms</code> method. A sample XML that is written to the output stream is like <br>
184             * <code> <"algorithm id='3' app_version='MyVersion12' app_family_name='MyFamily' app_executable_name='MyExe' ps_name='DUMMY_ps_nam' ps_hash='DUMMY_HASH' creation_date='2006-12-06 16:12:10.0' last_modification_date='2006-12-06 16:12:10.0' created_by='ANZARDN' last_modified_by='ANZARDN'"/> </code>
185             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
186             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
187             * @param patternVer a parameter passed in from the client that can contain wild card characters for application version. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
188             * @param patternFam a parameter passed in from the client that can contain wild card characters for application family. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
189             * @param patternExe a parameter passed in from the client that can contain wild card characters for application executable name. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
190             * @param patternPS a parameter passed in from the client that can contain wild card characters for parameter set name. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
191             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied pattern parameters are invalid or the database connection is unavailable.
192             */
193            public void listAlgorithms(Connection conn, Writer out, String patternVer, String patternFam, String patternExe, String patternPS) throws Exception {
194                    //FIXME name should be changed to hash
195                    patternVer      = getPattern(patternVer, "app_version");
196                    patternFam      = getPattern(patternFam, "app_family_name");
197                    patternExe      = getPattern(patternExe, "app_executable_name");
198                    patternPS       = getPattern(patternPS, "parameterset_name");
199    
200                    PreparedStatement ps = null;
201                    ResultSet rs = null;
202                    try {
203                            ps = DBSSql.listAlgorithms(conn, patternVer, patternFam, patternExe, patternPS);
204                            rs =  ps.executeQuery();
205                            while(rs.next()) {
206                                    out.write(((String) "<algorithm id='" + get(rs, "ID") + 
207                                                    "' app_version='" + get(rs, "APP_VERSION") +
208                                                    "' app_family_name='" + get(rs, "APP_FAMILY_NAME") +
209                                                    "' app_executable_name='" + get(rs, "APP_EXECUTABLE_NAME") +
210                                                    "' ps_name='" + get(rs, "PS_NAME") +
211                                                    "' ps_hash='" + get(rs, "PS_HASH") +
212                                                    "' creation_date='" + get(rs, "CREATION_DATE") +
213                                                    "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
214                                                    "' created_by='" + get(rs, "CREATED_BY") +
215                                                    "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
216                                                    "'/>\n"));
217                            }
218                    } finally {
219                            if (rs != null) rs.close();
220                            if (ps != null) ps.close();
221                    }
222    
223            }
224    
225            /**
226             * Lists all the runs within a processed dataset from the database in a xml format. This method makes one sql query, execute it, fetch the results and packs and write it in xml format to the output stream. The query that it executes get generated by <code>dbs.DBSSql.listRuns</code> method. First it fetches the processed dataset ID from the database by calling a private <code>getProcessedDSID<code> method using the path provided in the parameter. If the processed dataset id does not esists then it throws an exception. A sample XML that is written to the output stream is like <br>
227             * <code> <"run id='1' run_number='9999' number_of_events='54' number_of_lumi_sections='12' total_luminosity='2' store_number='32' start_of_run='nov' end_of_run='dec' creation_date='2006-12-06 16:12:12.0' last_modification_date='2006-12-06 16:12:12.0' created_by='ANZARDN' last_modified_by='ANZARDN'"/></code>
228             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
229             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
230             * @param path a dataset path in the format of /primary/tier/processed. If this path is not provided or the dataset id could not be found then an exception is thrown.
231             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied path is invalid, the database connection is unavailable or processed dataset is not found.
232             */
233            public void listRuns(Connection conn, Writer out, String path) throws Exception {
234                    PreparedStatement ps = null;
235                    ResultSet rs = null;
236                    try {
237                            ps = DBSSql.listRuns(conn, getProcessedDSID(conn, path));
238                            rs =  ps.executeQuery();
239                            while(rs.next()) {
240                                    out.write(((String) "<run id='" + get(rs, "ID") +
241                                            "' run_number='" + get(rs, "RUN_NUMBER") +
242                                            "' number_of_events='" + get(rs, "NUMBER_OF_EVENTS") +
243                                            "' number_of_lumi_sections='" + get(rs, "NUMBER_OF_LUMI_SECTIONS") +
244                                            "' total_luminosity='" + get(rs, "TOTAL_LUMINOSITY") +
245                                            "' store_number='" + get(rs, "STRORE_NUMBER") +
246                                            "' start_of_run='" + get(rs, "START_OF_RUN") +
247                                            "' end_of_run='" + get(rs, "END_OF_RUN") +
248                                            "' creation_date='" + get(rs, "CREATION_DATE") +
249                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
250                                            "' created_by='" + get(rs, "CREATED_BY") +
251                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
252                                            "'/>\n"));
253                            }
254                    } finally { 
255                            if (rs != null) rs.close();
256                            if (ps != null) ps.close();
257                    }
258    
259            }
260    
261            /**
262             * Lists all the data tiers within a processed dataset from the database in a xml format. This method makes one sql query, execute it, fetch the results and packs and write it in xml format to the output stream. The query that it executes get generated by <code>dbs.DBSSql.listTiers</code> method. First it fetches the processed dataset ID from the database by calling a private <code>getProcessedDSID<code> method using the path provided in the parameter. If the processed dataset id does not esists then it throws an exception. A sample XML that is written to the output stream is like <br>
263             * <code> <"data_tier id='12' name='HIT' creation_date='2006-12-06 16:21:46.0' last_modification_date='2006-12-06 16:21:46.0' created_by='ANZARDN' last_modified_by='ANZARDN'"/></code>
264             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
265             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
266             * @param path a dataset path in the format of /primary/tier/processed. If this path is not provided or the dataset id could not be found then an exception is thrown.
267             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied path is invalid, the database connection is unavailable or processed dataset is not found.
268             */
269            public void listTiers(Connection conn, Writer out, String path) throws Exception {
270                    PreparedStatement ps = null;
271                    ResultSet rs = null;
272                    try {
273                            ps =  DBSSql.listTiers(conn, getProcessedDSID(conn, path));
274                            rs =  ps.executeQuery();
275                            while(rs.next()) {
276                                    out.write(((String) "<data_tier id='" + get(rs, "ID") +
277                                            "' name='" + get(rs, "NAME") +
278                                            "' creation_date='" + get(rs, "CREATION_DATE") +
279                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
280                                            "' created_by='" + get(rs, "CREATED_BY") +
281                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
282                                            "'/>\n"));
283                            }
284                    } finally { 
285                            if (rs != null) rs.close();
286                            if (ps != null) ps.close();
287                    }
288            }
289    
290            /**
291             * Lists all the blocks within a processed dataset from the database in a xml format. This method makes one sql query, execute it, fetch the results and packs and write it in xml format to the output stream. The query that it executes get generated by <code>dbs.DBSSql.listBlocks</code> method. First it fetches the processed dataset ID from the database by calling a private <code>getProcessedDSID<code> method using the path provided in the parameter. If the processed dataset id does not esists then it throws an exception. A sample XML that is written to the output stream is like <br>
292             * <code> <"block id='2' name='/test/test#9ac2b28b-781f-4907-a87a-40e233ab139a' size='0' number_of_files='0' creation_date='2006-12-06 16:29:34.0' last_modification_date='2006-12-06 16:29:34.0' created_by='ANZARDN' last_modified_by='ANZARDN'"/></code>
293             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
294             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
295             * @param path a dataset path in the format of /primary/tier/processed. If this path is not provided or the dataset id could not be found then an exception is thrown.
296             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied path is invalid, the database connection is unavailable  or processed dataset is not found.
297             */
298            public void listBlocks(Connection conn, Writer out, String path) throws Exception {
299                    PreparedStatement ps = null;
300                    ResultSet rs =  null;
301                    try {
302                            ps =  DBSSql.listBlocks(conn, getProcessedDSID(conn, path));
303                            rs =  ps.executeQuery();
304                            while(rs.next()) {
305                                    out.write(((String) "<block id='" + get(rs, "ID") +
306                                            "' name='" + get(rs, "NAME") +
307                                            "' size='" + get(rs, "BLOCKSIZE") +
308                                            "' number_of_files='" + get(rs, "NUMBER_OF_FILES") +
309                                            //"' open_for_writing='" + get(rs, "OPEN_FOR_WRITING") +
310                                            "' creation_date='" + get(rs, "CREATION_DATE") +
311                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
312                                            "' created_by='" + get(rs, "CREATED_BY") +
313                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
314                                            "'/>\n"));
315                            }
316                    } finally {
317                            if (rs != null) rs.close();
318                            if (ps != null) ps.close();
319                    }
320            }
321    
322    
323    
324            /**
325             * Lists all the files within a processed dataset or within a block from the database in a xml format. This method makes one sql query, execute it, fetch the results and packs and write it in xml format to the output stream. The query that it executes get generated by <code>dbs.DBSSql.listFiles</code> method. First it fetches the processed dataset ID from the database by calling a private <code>getProcessedDSID<code> method using the path provided in the parameter. It also fetches the block id from the database by calling a private method <code>getBlockID</code> If niether the processed dataset id nor the block id exists then it throws an exception. A sample XML that is written to the output stream is like <br>
326             * <code> <"file id='9' lfn='TEST_LFN' checksum='CHKSUM' size='200' queryable_meta_data='any' number_of_events='200' validation_status='1' type='EVD' status='VALID' block_name='/test/test#8a99a0' creation_date='2006-12-07 09:52:55.0' last_modification_date='2006-12-07 09:52:55.0' created_by='ANZARDN' last_modified_by='ANZARDN'"><"data_tier name='HIT'"/><"data_tier name='SIM'"/><"/file"></code>
327             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
328             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
329             * @param path a dataset path in the format of /primary/tier/processed. This path is used to find the existing processed dataset id.
330             * @param blockName a block name in the format of /primary/processed#GUID. This block name is used to find the existing block id.
331             * @param patternLFN a parameter passed in from the client that can contain wild card characters for logical file name. This pattern is used to restrict the SQL query results by sustitution it in the WHERE clause.
332             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied patternLFN is invalid, the database connection is unavailable or processed dataset or block is not found.
333             */
334            public void listFiles(Connection conn, Writer out, String path, String blockName, String patternLFN) throws Exception {
335    
336                    patternLFN = getPattern(patternLFN, "pattern_lfn");
337                    String prevTier = "";
338                    //The xml genrated is nested and this flag is needed to know if first time a tag needs to be written
339                    boolean first = true;
340                    String prevFileID = "";
341                    
342                    String procDSID = null;
343                    String blockID = null;
344                    if(!isNull(path)) {
345                            procDSID = getProcessedDSID(conn, path);
346                    }
347                    if(!isNull(blockName)) {
348                            blockID = getBlockID(conn, blockName, true);
349                    }
350                    if(blockID == null && procDSID == null) {
351                            throw new DBSException("Missing data", "1005", "Null Fields. Expected either a Processed Dataset or a Block");
352                    }
353                    PreparedStatement ps = null;
354                    ResultSet rs =  null;
355                    try {
356                            ps = DBSSql.listFiles(conn, procDSID, blockID, patternLFN);
357                            rs =  ps.executeQuery();
358                            while(rs.next()) {
359                                    String fileID = get(rs, "ID");
360                                    String tier = get(rs, "DATA_TIER");
361    
362                                    if( !prevFileID.equals(fileID) && ! first) {
363                                            out.write( (String) "</file> \n");
364                                    }
365                             
366                                    if( !prevFileID.equals(fileID) || first) {  
367                                            out.write(((String) "<file id='" + fileID +
368                                            "' lfn='" + get(rs, "LFN") +
369                                            "' checksum='" + get(rs, "CHECKSUM") +
370                                            "' size='" + get(rs, "FILESIZE") +
371                                            "' queryable_meta_data='" + get(rs, "QUERYABLE_META_DATA") +
372                                            "' number_of_events='" + get(rs, "NUMBER_OF_EVENTS") +
373                                            "' validation_status='" + get(rs, "VALIDATION_STATUS") +
374                                            "' type='" + get(rs, "TYPE") +
375                                            "' status='" + get(rs, "STATUS") +
376                                            "' block_name='" + get(rs, "BLOCK_NAME") +
377                                            "' creation_date='" + get(rs, "CREATION_DATE") +
378                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
379                                            "' created_by='" + get(rs, "CREATED_BY") +
380                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
381                                            "'>\n"));
382                                            first = false;
383                                            prevFileID = fileID;
384                                    }
385          
386                                    if( !prevTier.equals(tier) || first ) {
387                                            out.write(((String) "\t<data_tier name='" + tier + "'/>\n"));
388                                            prevTier = tier;
389                                    }
390                            }
391                    } finally { 
392                            if (rs != null) rs.close();
393                            if (ps != null) ps.close();
394                    }
395    
396                    if (!first) out.write(((String) "</file>\n"));
397            }
398    
399            /**
400             * Insert a primary dataset whose parameters are provided in the passed dataset <code>java.util.Hashtable</code>. This hashtable dataset is generated externally and filled in with the primary dataset parameters by parsing the xml input provided by the client. This method inserts entriy into more than one table associated with PrimaryDataset table. The the main query that it executes to insert in PrimaryDataset table, get generated by <code>dbs.DBSSql.insertPrimaryDataset</code> method.<br> 
401             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. Then it inserts the primary dataset type in PrimaryDSType table if does not exist already. It works on Description tables (needed to be done in the code) and finally inserts a new primary dataset in PrimaryDataset table.
402             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
403             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
404             * @param dataset a <code>java.util.Hashtable</code> that contains all the necessary key value pairs required for inserting a new primary dataset. The keys along with its values that it may or may not contain are <br>
405             * <code>type, annotation, primary_name, start_date, end_date</code>
406             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
407             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a duplicate entry is being added.
408             */
409            public void insertPrimaryDataset(Connection conn, Writer out, Hashtable dataset, Hashtable dbsUser) throws Exception {
410                    String warMsg ;
411                    //Get the User ID from USERDN
412                    String userID = getUserID(conn, dbsUser); 
413                    
414                    String type = get(dataset, "type", false);
415                                    
416                    //Insert a Dataset Type if it does not exists
417                    insertName(conn, "PrimaryDSType", "Type", type , userID);
418                    
419                    //Insert a Dataset Trigger Desc if it does not exists
420                    //FIXME some problem with this table while insertng rows
421                    //insertName(conn, "TriggerPathDescription", "TriggerPathDescription", tpDesc , userID);
422                    
423                    //Insert a Dataset Other Desc if it does not exists
424                    //insertName(conn, "OtherDescription", "Description", oDesc , userID);
425    
426                    //TODO Insert MCDesc . Change in the schema is required.
427                    //FIXME The schemna should be changed so that PrimaryDatasetDescription should have PrimarYdataset ID as forign key. 
428                    //Not the other way around
429                    //String mcDesc = get(dataset, "mc_channel_description", false);
430                    //String mcPro = get(dataset, "mc_production", false);
431                    //String mcDecay = get(dataset, "mc_decay_chain", false);
432                    //String oDesc = get(dataset, "other_description", false);
433                    //String tpDesc = get(dataset, "trigger_path_description", false);
434    
435                    //TODO Insert PrimaryDatasetDescription table also
436                    //String primDSID;
437                    //if( (primDSID = getID(conn, "PrimaryDataset", "Name", name, false)) == null ) {
438                    PreparedStatement ps = null;
439                    try {
440                            ps = DBSSql.insertPrimaryDataset(conn, 
441                                            get(dataset, "annotation", false),
442                                            get(dataset, "primary_name", true),
443                                            "0",//FIXME Should not be in the schema
444                                            get(dataset, "start_date", true),
445                                            get(dataset, "end_date", false),
446                                            getID(conn, "PrimaryDSType", "Type", type, true), 
447                                            userID);
448                            ps.execute();
449                    } finally { 
450                            if (ps != null) ps.close();
451                    }
452    
453                    //} else {
454                            //Append Warnning message that run eixts
455                    //}
456    
457            }
458    
459            /**
460             * Insert a run  whose parameters are provided in the passed run <code>java.util.Hashtable</code>. This hashtable run is generated externally and filled in with the run parameters by parsing the xml input provided by the client. This method inserts entry into just one table called Run table. The the main query that it executes to insert in Run table, get generated by <code>dbs.DBSSql.insertRun</code> method.<br> 
461             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. Then it finally inserts a new run in Run table.
462             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
463             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
464             * @param run a <code>java.util.Hashtable</code> that contains all the necessary key value pairs required for inserting a new run. The keys along with its values that it may or may not contain are <br>
465             * <code>run_number, number_of_events, number_of_lumi_sections, total_luminosity, store_number, start_of_run, end_of_run</code>
466             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
467             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a duplicate entry is being added.
468             */
469            public void insertRun(Connection conn, Writer out, Hashtable run, Hashtable dbsUser) throws Exception {
470                    PreparedStatement ps = null;
471                    try {
472                            ps = DBSSql.insertRun(conn, 
473                                    get(run, "run_number", true),
474                                    get(run, "number_of_events", true),
475                                    get(run, "number_of_lumi_sections", true),
476                                    get(run, "total_luminosity", true),
477                                    get(run, "store_number", true),
478                                    get(run, "start_of_run", false),
479                                    get(run, "end_of_run", false),
480                                    getUserID(conn, dbsUser));
481                            ps.execute();
482                    } finally { 
483                            if (ps != null) ps.close();
484                    }
485    
486            }
487    
488            /**
489             * Insert a tier whose name is provided in the parameter tierName. This method inserts entry into just one table table called DataTier table. The the main query that it executes to insert in DataTier table, get generated by a generic <code>dbs.DBSSql.insertName</code> method.<br> 
490             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. Then it finally inserts a new tier in DataTier table.
491             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
492             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
493             * @param tierName a <code>java.lang.String</code> that contains the name of the data tier to be inserted.
494             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
495             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameter tierName is invalid, the database connection is unavailable or a duplicate entry is being added.
496             */
497            public void insertTier(Connection conn, Writer out, String tierName, Hashtable dbsUser) throws Exception {
498                    insertName(conn, "DataTier", "Name", tierName , getUserID(conn, dbsUser));
499            }
500    
501    
502            /**
503             * Insert a block whose parameters are provided in the passed block <code>java.util.Hashtable</code>. This hashtable block is generated externally and filled in with the block parameters by parsing the xml input provided by the client. This method inserts entry into just one table called Block table. The the main query that it executes to insert in Block table, get generated by <code>dbs.DBSSql.insertBlock</code> method.<br> 
504             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
505             * Then it fetches the inserts the processed dataset id using the path suppiled in the block hashtable by calling a private <code>getProcessedDSID</code> method. If the processed dataset id is not found then an exception is thrown. <br>
506             * Then it either takes the block name suppiled in the block hashtable or generates one first generating a new GUID and then by concating /Primary/Process#GUID. Finally it inserts a new block in the Block table and writes the block name on the output stream in xml format so that the cleint can get the name of the newly created block.
507             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
508             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
509             * @param block a <code>java.util.Hashtable</code> that contains all the necessary key value pairs required for inserting a new block. The keys along with its values that it may or may not contain are <br>
510             * <code>path, name, open_for_writing</code>
511             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
512             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a duplicate entry is being added.
513             */
514            public void insertBlock(Connection conn, Writer out, Hashtable block, Hashtable dbsUser) throws Exception {
515                    String path = get(block, "path");
516                    String name = get(block, "name");
517                    String openForWriting = get(block, "open_for_writing", false);
518            
519                    String procDSID = getProcessedDSID(conn, path);//Getting ID before spliting the path will type chech the path also.
520                    //Set defaults Values
521                    String[] data = path.split("/");
522                    if (isNull(name)) name = "/" + data[1] + "/" + data[3] +"#" + UUID.randomUUID(); 
523                    if (isNull(openForWriting)) openForWriting = "1";
524                    checkBlock(name);
525                    PreparedStatement ps = null;
526                    try {
527                            ps = DBSSql.insertBlock(conn,
528                                    "0",// A new block should always have 0 size
529                                    name,
530                                    procDSID,
531                                    "0",// A new block should always have 0 files
532                                    openForWriting,
533                                    getUserID(conn, dbsUser));
534    
535                            ps.execute();
536                    } finally { 
537                            if (ps != null) ps.close();
538                    }
539                    out.write("<block block_name='" + name + "'/>");
540    
541            }
542    
543            /**
544             * Insert a algorithm/application whose parameters are provided in the passed algo <code>java.util.Hashtable</code>. This hashtable block is generated externally and filled in with the algorithm parameters by parsing the xml input provided by the client. This method inserts entry into more than one table associated with AlgorithmConfig table. The the main query that it executes to insert in AlgorithmConfig table, get generated by <code>dbs.DBSSql.insertApplication</code> method.<br> 
545             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
546             * Then it inserts a new version in the AppVersion table by calling a generic private insertName method. <br>
547             * Then it inserts a new family in the AppFamily table by calling a generic private insertName method. <br>
548             * Then it inserts a new executable in the AppExecutable table by calling a generic private insertName method. <br>
549             * Then it inserts a new parameter set in the QueryableParameterSet table by calling a insertParameterSet method. <br>
550             * Finally it inserts a new algorithm in the AlgorithmConfig table.
551             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
552             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
553             * @param algo a <code>java.util.Hashtable</code> that contains all the necessary key value pairs required for inserting a new algorithm. The keys along with its values that it may or may not contain are <br>
554             * <code>app_version, app_family_name, app_executable_name, ps_name, ps_hash, ps_version, ps_type, ps_annotation, ps_content</code>
555             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
556             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a duplicate entry is being added.
557             */
558            public void insertAlgorithm(Connection conn, Writer out, Hashtable algo, Hashtable dbsUser) throws Exception {
559                    String version = get(algo, "app_version", true);
560                    String family = get(algo, "app_family_name", true);
561                    String exe = get(algo, "app_executable_name", true);
562                    String psName = get(algo, "ps_name", true);
563                    
564                    //Get the User ID from USERDN
565                    String userID = getUserID(conn, dbsUser);
566                    //Insert the application version if it does not exists
567                    insertName(conn, "AppVersion", "Version", version, userID);
568                    
569                    //Insert the Application Family if it does not exists
570                    insertName(conn, "AppFamily", "FamilyName", family, userID);
571                    
572                    //Insert the Application Executable if it does not exists
573                    insertName(conn, "AppExecutable", "ExecutableName", exe, userID);
574    
575                    //Insert the ParameterSet if it does not exists
576                    //insertParameterSet(conn, psHash, psName, psVersion, psType, psAnnotation, psContent, userID);
577                    insertParameterSet(conn, algo, userID);
578                    
579                    //Insert the Algorithm by fetching the ID of exe, version, family and parameterset
580                    PreparedStatement ps = null;
581                    try {
582                            ps = DBSSql.insertApplication(conn, 
583                                    getID(conn, "AppExecutable", "ExecutableName", exe, true), 
584                                    getID(conn, "AppVersion", "Version", version, true), 
585                                    getID(conn, "AppFamily", "FamilyName", family, true), 
586                                    getID(conn, "QueryableParameterSet", "Name", psName, true), 
587                                    userID);
588                            ps.execute();
589                    } finally { 
590                      if (ps != null) ps.close();
591                    }
592           }
593    
594           /**
595             * Insert a list of Files whose parameters are provided in the passed files <code>java.util.Vector</code>. This vector contains a list of hashtable and is generated externally and filled in with the file parameters by parsing the xml input provided by the client. This method inserts entries into more than one table associated with File table. The the main query that it executes to insert in File table, get generated by <code>dbs.DBSSql.insertFile</code> method.<br> 
596             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
597             * Then it fetches the processed dataset id and the block id by calling a private getProcessedDSID method and private getBlockID method with parameters path and blockName. The log of insert file bahaves in a way such that all the files to be inserted per this method call, should belong to the same processed dataset and same block <br>
598             * Then it iterates through all the files Hashtable provided in the files vector and inserts one file at a time. <br>
599             * Then in the same loop it fetches all the algorithm list of the file that just got inserted and inserts a new row in FileAlgoMap table by calling a generic private insertMap method. <br>
600             * Then in the same loop it fetches all the tier list of the file that just got inserted and inserts a new row in FileTier table by calling a generic private insertMap method. <br>
601             * Then in the same loop it fetches all the parent list of the file that just got inserted and inserts a new row in FileParentage table by calling a generic private insertMap method. <br>
602             * Then in the same loop it fetches all the lumi section list of the file that just got inserted and inserts a new row in FileLumi table by calling a generic private insertMap method. Before it insert in to this FileLumi table , it first insert the LumiSection by calling insertLumiSection method<br>
603             * Finally it updates the block information with correct number of files and size in bytes by calling the updateBlock method.
604             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
605             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
606             * @param files a <code>java.util.Vector</code> that contains a list of <code>java.util.Hastable</code>  that contain all the necessary key value pairs required for inserting a new file. The keys along with its values that it may or may not contain are <br>
607             * <code>lfn, checksum, number_of_events, size, queryable_meta_data, file_status, type, validation_status, lumi_section, data_tier, parent, algorithm </code> <br>
608             * Further the keys <code>lumi_section, data_tier, parent, algorithm </code> are itself vector of Hashtable. <br>
609             * The key that <code>parent </code> hashtable may or may not contain is <code>lfn</code> <br>
610             * The key that <code>data_tier </code> hashtable may or may not contain is <code>name</code> <br>
611             * The keys that <code>lumi_section </code> hashtable may or may not contain are <br>
612             * <code>lumi_section_number, run_number, start_event_number, end_event_number, lumi_start_time, lumi_end_time</code> <br>
613             * The keys that <code>algorithm </code> hashtable may or may not contain are <br> 
614             * <code>app_version, app_family_name, app_executable_name, ps_name</code> <br>
615              * @param path a dataset path in the format of /primary/tier/processed. This path is used to find the existing processed dataset id.
616             * @param blockName a block name in the format of /primary/processed#GUID. This block name is used to find the existing block id.
617             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
618             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a duplicate entry is being added.
619             */
620            public void insertFiles(Connection conn, Writer out, String path, String blockName, Vector files, Hashtable dbsUser) throws Exception {
621                    
622                    //Get the User ID from USERDN
623                    String userID = getUserID(conn, dbsUser);
624                    /*//Check if all the path is in the files are same.
625                    if(files.size() > 0) {
626                            String path = get((Hashtable)files.get(0), "path");
627                            for (int i = 1; i < files.size() ; ++i) {
628                                    String tmpPath = get((Hashtable)files.get(i), "path");
629                                    if(!tmpPath.equals(path)) {
630                                            throw new DBSException("Bad Data", "300", "Different Processed Datatsets. All files in the list should belong to same processed datatset. Dataset1 " + path + " Datatset2 " + tmpPath);
631                                    }
632                            
633                            }
634                    }*/
635                    String procDSID = getProcessedDSID(conn, path);
636                    String blockID = getBlockID(conn, blockName, true);
637    
638                    
639                    for (int i = 0; i < files.size() ; ++i) {
640                            Hashtable file = (Hashtable)files.get(i);
641                    
642                            //String path = get(file, "path");
643                            //String blockName = get(file, "block_name");
644                            String lfn = get(file, "lfn", true);
645                            String fileStatus = get(file, "file_status", false);
646                            String type = get(file, "type", false);
647                            String valStatus = get(file, "validation_status", false);
648                            Vector lumiVector = DBSUtil.getVector(file,"lumi_section");
649                            Vector tierVector = DBSUtil.getVector(file,"data_tier");
650                            Vector parentVector = DBSUtil.getVector(file,"parent");
651                            Vector algoVector = DBSUtil.getVector(file,"algorithm");
652                    
653                            //Set defaults Values
654                            if (isNull(fileStatus)) fileStatus = "NEW";
655                            if (isNull(type)) type = "EVD";
656                            if (isNull(valStatus)) valStatus = "NOTVALIDATED";
657                            
658                            //Insert a File status if it does not exists
659                            //insertName(conn, "Status", "Status", fileStatus , userID);
660    
661                            //Insert a File Validation status if it does not exists
662                            //insertName(conn, "Status", "Status", valStatus , userID);
663    
664                            //Insert a File Type if it does not exists
665                            //insertName(conn, "Type", "Type", type , userID);
666                            //checkWord(fileStatus, "FileStatus");
667                            //checkWord(type, "FileType");
668                            //checkWord(valStatus, "ValidationStatus");
669                            //Insert a File by fetching the fileStatus, type and validationStatus
670                            //if( (fileID = getID(conn, "Files", "LogicalFileName", lfn, false)) == null ) {
671                            //TODO Exception of null status or type should be catched and parsed and 
672                            //a proper message should be returned back to the user. Different Database can have different error message YUK
673                            //Status should be defaulted to something in the database itself. A wrong status may insert a dafult value.
674                            //User will never know about this YUK
675                            PreparedStatement ps = null;
676                            try {
677                                    ps = DBSSql.insertFile(conn, 
678                                                    procDSID, 
679                                                    blockID, 
680                                                    lfn, 
681                                                    get(file, "checksum", false), 
682                                                    get(file, "number_of_events", false), 
683                                                    get(file, "size", false), 
684                                                    fileStatus, 
685                                                    type, 
686                                                    valStatus, 
687                                                    get(file, "queryable_meta_data", false), 
688                                                    userID);
689                                    ps.execute();
690                            } finally { 
691                                    if (ps != null) ps.close();
692                            }
693    
694                            //}
695    
696                            //if(isNull(fileID)) fileID = getID(conn, "Files", "LogicalFileName", lfn, true);
697                            //Fetch the File ID that was just inseted to be used for subsequent insert of other tables only if it is needed.
698                            //FileID is needed if any of the other table information is provided i.e the vector size is > 0
699                            String fileID = "";
700                            if(algoVector.size() > 0 || tierVector.size() > 0 || parentVector.size() > 0 || lumiVector.size() > 0) 
701                                    fileID = getID(conn, "Files", "LogicalFileName", lfn, true);
702    
703                            //Insert FileAlgo table by fetching application ID. 
704                            //Use get with 2 params so that it does not do type checking, since it will be done in getID call.
705                            for (int j = 0; j < algoVector.size(); ++j) {
706                                    Hashtable hashTable = (Hashtable)algoVector.get(j);
707                                    insertMap(conn, "FileAlgo", "Fileid", "Algorithm", 
708                                                    fileID, 
709                                                    getAlgorithmID(conn, get(hashTable, "app_version"), 
710                                                                    get(hashTable, "app_family_name"), 
711                                                                    get(hashTable, "app_executable_name"),
712                                                                    get(hashTable, "ps_name")), 
713                                                    userID);
714                            }
715    
716                            //Insert FileTier table by fetching data tier ID
717                            for (int j = 0; j < tierVector.size(); ++j) {
718                                    insertMap(conn, "FileTier", "Fileid", "DataTier", 
719                                            fileID, 
720                                            getID(conn, "DataTier", "Name", 
721                                                    get((Hashtable)tierVector.get(j), "name") , 
722                                                    true), 
723                                            userID);
724                            }
725                            
726                            //Insert FileParentage table by fetching parent File ID
727                            for (int j = 0; j < parentVector.size(); ++j) {
728                                    insertMap(conn, "FileParentage", "ThisFile", "itsParent", 
729                                                    fileID, 
730                                                    getID(conn, "Files", "LogicalFileName", 
731                                                            get((Hashtable)parentVector.get(j), "lfn") , 
732                                                            true), 
733                                                    userID);
734                            }
735                            //TODO Discussion about Lumi section is needed
736                            //Insert FileLumi table by first inserting and then fetching Lumi Section ID
737                            for (int j = 0; j < lumiVector.size(); ++j) {
738                                    Hashtable hashTable = (Hashtable)lumiVector.get(j);
739                                    //Insert A lumi Section if it does not exists
740                                    insertLumiSection(conn, out, hashTable, userID);
741                                    insertMap(conn, "FileLumi", "Fileid", "Lumi", 
742                                                    fileID, 
743                                                    getID(conn, "LumiSection", "LumiSectionNumber", get(hashTable, "lumi_section_number") , true), 
744                                                    userID);
745                            }
746                    
747                    }//For loop
748                    //Update Block numberOfFiles and Size
749                    PreparedStatement ps = null;
750                    try {
751                            ps = DBSSql.updateBlock(conn, blockID);
752                            ps.executeUpdate();
753                    } finally { 
754                            if (ps != null) ps.close();
755                    }
756    
757            }
758    
759           /**
760             * Insert a processed dataset whose parameters are provided in the passed dataset <code>java.util.Hashtable</code>. This hashtable is generated externally and filled in with the processed dataset parameters by parsing the xml input provided by the client. This method inserts entr into more than one table associated with ProcessedDataset table. The the main query that it executes to insert in ProcessedDataset table, get generated by <code>dbs.DBSSql.insertProcessedDataset</code> method.<br> 
761             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
762             * Then it insert a new processed dataset whose sql query is generated by calling <code>dbs.sql.insertProcessedDatatset<code>
763             * Then it fetches all the algorithm list of the processed dataset that just got inserted and inserts a new row in ProcAlgoMap table by calling a generic private insertMap method. <br>
764             * Then it fetches all the tier list of the  processed dataset that just got inserted and inserts a new row in ProcDSTier table by calling a generic private insertMap method. Before that it first inserts the data tier if it does not exists by calling a generic insertName method.<br>
765             * Then it fetches all the parent list of the  processed dataset that just got inserted and inserts a new row in DatasetParentage table by calling a generic private insertMap method. <br>
766             * Then it fetches all the run list of the  processed dataset that just got inserted and inserts a new row in ProcDSRun table by calling a generic private insertMap method. <br>
767             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
768             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
769             * @param dataset a  <code>java.util.Hastable</code>  that contain all the necessary key value pairs required for inserting a new processed dataset. The keys along with its values that it may or may not contain are <br>
770             * <code>primary_datatset_name, processed_datatset_name, physics_group_name, physics_group_convener,status, data_tier, parent, algorithm, run </code> <br>
771             * Further the keys <code>data_tier, parent, algorithm, run </code> are itself vector of Hashtable. <br>
772             * The key that <code>parent </code> hashtable may or may not contain is <code>path</code> <br>
773             * The key that <code>data_tier </code> hashtable may or may not contain is <code>name</code> <br>
774             * The keys that <code>run </code> hashtable may or may not contain is  <code>run_number</code> <br>
775             * The keys that <code>algorithm </code> hashtable may or may not contain are <br> 
776             * <code>app_version, app_family_name, app_executable_name, ps_name</code> <br>
777             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
778             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a duplicate entry is being added.
779             */
780            public void insertProcessedDataset(Connection conn, Writer out, Hashtable dataset, Hashtable dbsUser) throws Exception {
781                    String warMsg ;
782                    //Get the User ID from USERDN
783                    String userID = getUserID(conn, dbsUser);
784    
785                    String procDSName = get(dataset, "processed_datatset_name", true);
786                    String phyGroupName = get(dataset, "physics_group_name", false);
787                    String phyGroupCon = get(dataset, "physics_group_convener", false);
788                    String status = get(dataset, "status", false);
789                    Vector tierVector = DBSUtil.getVector(dataset,"data_tier");
790                    Vector parentVector = DBSUtil.getVector(dataset,"parent");
791                    Vector algoVector = DBSUtil.getVector(dataset,"algorithm");
792                    Vector runVector = DBSUtil.getVector(dataset,"run");
793            
794    
795                    //Set defaults Values
796                    if (isNull(status)) status = "VALID";
797                    if (isNull(phyGroupName)) phyGroupName = "ALLGROUP";
798                    if (isNull(phyGroupCon)) phyGroupCon = "ANZARDN";//FIXME Some default convenor name should be used
799                    
800                    //Insert a Processed Dataset status if it does not exists
801                    //insertName(conn, "Status", "Status", status , userID);
802                    
803                    //Insert a Physics Group if it does not exists
804                    insertPhysicsGroup(conn, out,  phyGroupName, phyGroupCon, userID);
805                    
806                    //Insert a Processed Datatset before by fetching the primDSID, status
807                    //if( (procDSID = getID(conn, "ProcessedDataset", "Name", procDSName, false)) == null ) {
808                    PreparedStatement ps = null;
809                    try {
810                            ps = DBSSql.insertProcessedDatatset(conn, 
811                                            procDSName,
812                                            getID(conn, "PrimaryDataset", "Name", 
813                                                    get(dataset, "primary_datatset_name", true), 
814                                                    true),
815                                            get(dataset, "open_for_writing", false),
816                                            getID(conn, "PhysicsGroup", "PhysicsGroupName", phyGroupName, true), 
817                                            getID(conn, "ProcDSStatus", "Status", status, true), 
818                                            userID);
819                            ps.execute();
820                    } finally {
821                            if (ps != null) ps.close();
822                    }
823    
824                    //} else {
825                            //warMsg =+ (String)"ProcessedDataset Name " + procDSName + " already exists but ignored.\n";
826                    //}
827    
828    
829                    //Fetch the Processed Datatset ID that was just inseted or fetched , to be used for subsequent insert of other tables.
830                    //FIXME this might use processed datatset with primary datatset combination instead of just proDSName
831                    //if(isNull(procDSID)) procDSID = getID(conn, "ProcessedDataset", "Name", procDSName, true);
832                    String procDSID = "";
833                    if(algoVector.size() > 0 || tierVector.size() > 0 || parentVector.size() > 0) 
834                            procDSID = getID(conn, "ProcessedDataset", "Name", procDSName, true);
835                    
836                    //Insert ProcAlgoMap table by fetching application ID. 
837                    for (int j = 0; j < algoVector.size(); ++j) {
838                            Hashtable hashTable = (Hashtable)algoVector.get(j);
839                            insertMap(conn, "ProcAlgo", "Dataset", "Algorithm", 
840                                            procDSID, 
841                                            getAlgorithmID(conn, get(hashTable, "app_version"), 
842                                                            get(hashTable, "app_family_name"), 
843                                                            get(hashTable, "app_executable_name"),
844                                                            get(hashTable, "ps_name")), 
845                                            userID);
846                    }
847    
848                    //Insert ProcDSTier table by fetching data tier ID
849                    for (int j = 0; j < tierVector.size(); ++j) {
850                            Hashtable hashTable = (Hashtable)tierVector.get(j);
851                            String tierName = get(hashTable, "name", true);
852                            //Insert DataTier if it does not exists
853                            insertName(conn, "DataTier", "Name", tierName , userID);
854                            insertMap(conn, "ProcDSTier", "Dataset", "DataTier", 
855                                            procDSID, 
856                                            getID(conn, "DataTier", "Name", tierName , true), 
857                                            userID);
858                    }
859    
860                    //Insert DatasetParentage table by fetching parent File ID
861                    for (int j = 0; j < parentVector.size(); ++j) {
862                            insertMap(conn, "DatasetParentage", "ThisDataset", "ItsParent", 
863                                            procDSID, 
864                                            getProcessedDSID(conn,  get((Hashtable)parentVector.get(j), "path")), 
865                                            userID);
866                    }
867    
868                    //Insert ProcDSRun table by fetching Run ID
869                    for (int j = 0; j < runVector.size(); ++j) {
870                            insertMap(conn, "ProcDSRuns", "Dataset", "Run", 
871                                            procDSID, 
872                                            getID(conn, "Runs", "RunNumber", get((Hashtable)runVector.get(j), "run_number") , true), 
873                                            userID);
874                    }
875    
876            }
877    
878            /**
879             * Insert a analysis dataset whose parameters are provided in the passed dataset <code>java.util.Hashtable</code>. This hashtable is generated externally and filled in with the analysis dataset parameters by parsing the xml input provided by the client. This method inserts entry into more than one table associated with AnalysisDataset table. The the main query that it executes to insert in AnalysisDataset table, get generated by <code>dbs.DBSSql.insertAnalysisDataset</code> method.<br> 
880             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
881             * Then it insert a new type field in AnalysisDSType table by calling a generic private  insertName method. <br>
882             * Then it insert a new status field in AnalysisDSStatus table by calling a generic private  insertName method. <br>
883             * Then it insert a new analysis dataset in AnalysisDataset table. <br>
884             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
885             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
886             * @param dataset a  <code>java.util.Hastable</code>  that contain all the necessary key value pairs required for inserting a new analysis dataset. The keys along with its values that it may or may not contain are <br>
887             * <code>name, type, status, annotation, physics_group_name </code> <br>
888             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
889             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a duplicate entry is being added.
890             */
891             public void createAnalysisDatasetFromPD(Connection conn, Writer out, Hashtable dataset, Hashtable dbsUser) throws Exception { 
892                    String name = get(dataset, "name", true);
893                    String type = get(dataset, "type", true);
894                    String status = get(dataset, "status", true);
895                    String userID = getUserID(conn, dbsUser);
896                    String procDSID = getProcessedDSID(conn, get(dataset, "path"));
897    
898                    //FIXME Parentage of Analysis Datasets (not well understood yet)
899                    //Vector parentVector = DBSUtil.getVector(dataset,"parent");
900    
901                    //FIXME   Make sure that Type and Status fileds are well understood
902                    //        will they pre-exist, or user can define as they create AnalysisDS ??     
903    
904                    insertName(conn, "AnalysisDSType", "Type", type , userID);
905                    insertName(conn, "AnalysisDSStatus", "Status", status, userID);
906    
907                    ResultSet rsLumi = null;
908                    PreparedStatement psLumi = null; 
909                    try { 
910                            psLumi = DBSSql.listLumiSections(conn, procDSID); 
911                            PreparedStatement ps = null;
912                            try {
913                                    ps = DBSSql.insertAnalysisDataset(conn,
914                                                    getStr(dataset, "annotation", true),
915                                                    name,
916                                                    psLumi.toString(),
917                                                    procDSID,
918                                                    getID(conn, "AnalysisDSType", "Type", type, true),
919                                                    getID(conn, "AnalysisDSStatus", "Status", status, true),
920                                                    getID(conn, "PhysicsGroup", "PhysicsGroupName", 
921                                                            get(dataset, "physics_group_name", true), 
922                                                            true), 
923                                                    userID); 
924                                                    
925                                    ps.execute();
926                             } finally {
927                                    if (ps != null) ps.close();   
928                             }
929    
930                             System.out.println("ANZAR: procDSID="+procDSID);
931                             //ID of just added AnalysisDS 
932                             String analysisDSID = getID(conn, "AnalysisDataset", "Name", name , true);
933                     
934                              //For eacxh run belonging to this ProcDS, get LumiSections and
935                              //make an entry into AnalysisDatasetLumi
936    
937                              rsLumi =  psLumi.executeQuery(); 
938                              while(rsLumi.next())    
939                                    insertMap(conn, "AnalysisDatasetLumi", "AnalysisDataset", "Lumi",  
940                                                    analysisDSID, 
941                                                    get(rsLumi, "ID"), 
942                                                    userID);
943                              
944                    } finally {
945                              if (psLumi != null) psLumi.close();
946                              if (rsLumi != null) rsLumi.close();
947                    }
948             }
949    
950            /**
951             * Insert a data tier in processed dataset. 
952             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
953             * Then it inserts entry into just one table ProcDSTier by calling a generic private <code>insertMap</code> method. It first fetches the processed dataset id by calling getProcessedDSID.
954             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
955             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
956             * @param path a dataset path in the format of /primary/tier/processed. If this path is not provided or the dataset id could not be found then an exception is thrown.
957             * @param tierName a data tier name which is assumed to be already present in the database.
958             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
959             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a procsssed dataset is not found.
960             */
961            public void insertTierInPD(Connection conn, Writer out, String path, String tierName, Hashtable dbsUser) throws Exception {
962                    insertMap(conn, "ProcDSTier", "Dataset", "DataTier", 
963                                    getProcessedDSID(conn, path), 
964                                    getID(conn, "DataTier", "Name", tierName , true), 
965                                    getUserID(conn, dbsUser));
966            }
967    
968    
969            /**
970             * Insert a dataset parent in processed dataset. 
971             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
972             * Then it inserts entry into just one table DatasetParentage by calling a generic private <code>insertMap</code> method. It first fetches the processed dataset id by calling a private getProcessedDSID method.
973             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
974             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
975             * @param path a dataset path in the format of /primary/tier/processed. If this path is not provided or the dataset id could not be found then an exception is thrown.
976             * @param parentPath a dataset path in the format of /primary/tier/processed that represent the parent of this dataset represented by path.
977             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
978             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a procsssed dataset is not found.
979             */
980            public void insertParentInPD(Connection conn, Writer out, String path, String parentPath, Hashtable dbsUser) throws Exception {
981                    insertMap(conn, "DatasetParentage", "ThisDataset", "ItsParent", 
982                                            getProcessedDSID(conn, path), 
983                                            getProcessedDSID(conn, parentPath), 
984                                            getUserID(conn, dbsUser));
985            }
986    
987            /**
988             * Insert a algorithm in processed dataset. 
989             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
990             * Then it inserts entry into just one table ProcAlgoMap by calling a generic private <code>insertMap</code> method. It first fetches the processed dataset id by calling a private getProcessedDSID method.
991             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
992             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
993             * @param path a dataset path in the format of /primary/tier/processed. If this path is not provided or the dataset id could not be found then an exception is thrown.
994             * @param algo a <code>java.util.Hashtable</code> that conatin the parameter that defines an algorithm. The keys that <code>algo </code> hashtable may or may not contain are <br> 
995             * <code>app_version, app_family_name, app_executable_name, ps_name</code> <br>
996             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
997             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a procsssed dataset is not found.
998             */
999            public void insertAlgoInPD(Connection conn, Writer out, String path, Hashtable algo, Hashtable dbsUser) throws Exception {
1000                    insertMap(conn, "ProcAlgo", "Dataset", "Algorithm", 
1001                                            getProcessedDSID(conn, path), 
1002                                            getAlgorithmID(conn, get(algo, "app_version"), 
1003                                                            get(algo, "app_family_name"), 
1004                                                            get(algo, "app_executable_name"),
1005                                                            get(algo, "ps_name")), 
1006                                            getUserID(conn, dbsUser));
1007            }
1008    
1009    
1010            /**
1011             * Insert a run parent in processed dataset. 
1012             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
1013             * Then it inserts entry into just one table ProcDSRun by calling a generic private <code>insertMap</code> method. It first fetches the processed dataset id by calling a private getProcessedDSID method.
1014             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1015             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
1016             * @param path a dataset path in the format of /primary/tier/processed. If this path is not provided or the dataset id could not be found then an exception is thrown.
1017             * @param runNumber a run number that uniquely identifies a run.
1018             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1019             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or a procsssed dataset is not found.
1020             */
1021            public void insertRunInPD(Connection conn, Writer out, String path, String runNumber, Hashtable dbsUser) throws Exception {
1022                    insertMap(conn, "ProcDSRuns", "Dataset", "Run", 
1023                                    getProcessedDSID(conn, path), 
1024                                    getID(conn, "Runs", "RunNumber", runNumber , true), 
1025                                    getUserID(conn, dbsUser));
1026            }
1027    
1028            /**
1029             * Insert a data tier in file. 
1030             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
1031             * Then it inserts entry into just one table FileTier by calling a generic private <code>insertMap</code> method. It first fetches the file id by calling a generic private getID method.
1032             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1033             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
1034             * @param lfn a logical file name that unquely identifies a file. If this lfn is not provided or the file id could not be found then an exception is thrown.
1035             * @param tierName a data tier name which is assumed to be already present in the database.
1036             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1037             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or the file is not found.
1038             */
1039            public void insertTierInFile(Connection conn, Writer out, String lfn, String tierName, Hashtable dbsUser) throws Exception {
1040                    insertMap(conn, "FileTier", "Fileid", "DataTier", 
1041                                    getID(conn, "Files", "LogicalFileName", lfn, true), 
1042                                    getID(conn, "DataTier", "Name", tierName , true), 
1043                                    getUserID(conn, dbsUser));
1044    
1045            }
1046            
1047            /**
1048             * Insert a parent in a file. 
1049             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
1050             * Then it inserts entry into just one table FileParentage by calling a generic private <code>insertMap</code> method. It first fetches the file id by calling a generic private getID method.
1051             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1052             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
1053             * @param lfn a logical file name that unquely identifies a file. If this lfn is not provided or the file id could not be found then an exception is thrown.
1054             * @param parentLFN a logical file name of the parent file.
1055             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1056             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or the file is not found.
1057             */
1058            public void insertParentInFile(Connection conn, Writer out, String lfn, String parentLFN, Hashtable dbsUser) throws Exception {
1059                    insertMap(conn, "FileParentage", "ThisFile", "itsParent", 
1060                                    getID(conn, "Files", "LogicalFileName", lfn, true),
1061                                    getID(conn, "Files", "LogicalFileName", parentLFN, true),
1062                                    getUserID(conn, dbsUser));
1063            }
1064    
1065    
1066            /**
1067             * Insert a algorithm in a file. 
1068             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
1069             * Then it inserts entry into just one table FileAlgoMap by calling a generic private <code>insertMap</code> method. It first fetches the file id by calling a generic private getID method.
1070             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1071             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
1072             * @param lfn a logical file name that unquely identifies a file. If this lfn is not provided or the file id could not be found then an exception is thrown.
1073             * @param algo a <code>java.util.Hashtable</code> that conatin the parameter that defines an algorithm. The keys that <code>algo </code> hashtable may or may not contain are <br> 
1074             * <code>app_version, app_family_name, app_executable_name, ps_name</code> <br>
1075             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1076             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or the file is not found.
1077             */
1078            public void insertAlgoInFile(Connection conn, Writer out, String lfn, Hashtable algo, Hashtable dbsUser) throws Exception {
1079                    insertMap(conn, "FileAlgo", "Fileid", "Algorithm", 
1080                                    getID(conn, "Files", "LogicalFileName", lfn, true), 
1081                                    getAlgorithmID(conn, get(algo, "app_version"), 
1082                                                    get(algo, "app_family_name"), 
1083                                                    get(algo, "app_executable_name"),
1084                                                    get(algo, "ps_name")), 
1085                                    getUserID(conn, dbsUser));
1086            }
1087    
1088            /**
1089             * Insert a lumi section in a file. 
1090             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
1091             * Then it inserts entry into just one table FileLumi by calling a generic private <code>insertMap</code> method. It first fetches the file id by calling a generic private getID method.
1092             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1093             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
1094             * @param lfn a logical file name that unquely identifies a file. If this lfn is not provided or the file id could not be found then an exception is thrown.
1095             * @param lsNumber a lumi section number that uniquely identifies a lumi section.
1096             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1097             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable or the file is not found.
1098             */
1099            public void insertLumiInFile(Connection conn, Writer out, String lfn, String lsNumber, Hashtable dbsUser) throws Exception {
1100                    insertMap(conn, "FileLumi", "Fileid", "Lumi", 
1101                                    getID(conn, "Files", "LogicalFileName", lfn, true), 
1102                                    getID(conn, "LumiSection", "LumiSectionNumber", lsNumber, true), 
1103                                    getUserID(conn, dbsUser));
1104            }
1105    
1106    
1107    
1108    
1109            /**
1110             * Insert a lumi section whose parameters are provided in the passed lumi <code>java.util.Hashtable</code>. This hashtable is generated externally and filled in with the lumi section parameters by parsing the xml input provided by the client. This method inserts entry into just one  LumiSection table. The the main query that it executes to insert in LumiSection table, get generated by <code>dbs.DBSSql.insertLumiSection</code> method.<br> 
1111             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
1112             * Then it insert a new lumi section whose sql query is generated by calling <code>dbs.sql.insertLumiSection<code>
1113             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1114             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
1115             * @param table a <code>java.util.Hastable</code>  that contain all the necessary key value pairs required for inserting a new lumi section. The keys along with its values that it may or may not contain are <br>
1116             * <code>lumi_section_number, run_number, start_event_number, end_event_number, lumi_start_time, lumi_end_time </code> <br>
1117             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1118             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable.
1119             */
1120            public void insertLumiSection(Connection conn, Writer out, Hashtable table, Hashtable dbsUser) throws Exception {
1121                    insertLumiSection(conn, out, table, getUserID(conn, dbsUser));
1122            }
1123            private void insertLumiSection(Connection conn, Writer out, Hashtable lumi, String userID) throws Exception {
1124                    String lsNumber = get(lumi, "lumi_section_number", true);
1125                    //Insert a new Lumi Section by feting the run ID 
1126                    if( getID(conn, "LumiSection", "LumiSectionNumber", lsNumber, false) == null ) {
1127                            PreparedStatement ps = null;
1128                            try {
1129                                    ps = DBSSql.insertLumiSection(conn,
1130                                                    lsNumber,
1131                                                    getID(conn, "Runs", "RunNumber",
1132                                                            get(lumi, "run_number", true),
1133                                                            true),
1134                                                    get(lumi, "start_event_number", true),
1135                                                    get(lumi, "end_event_number", true),
1136                                                    get(lumi, "lumi_start_time", false),
1137                                                    get(lumi, "lumi_end_time", false),
1138                                                    userID);
1139                                    ps.execute();
1140                            } finally {
1141                                    if (ps != null) ps.close();
1142                            }
1143    
1144                    } else {
1145                            writeWarning(out, "Already Exists", "401", "LumiSection " + lsNumber + " Already Exists");
1146                    }
1147            }
1148    
1149            private static void writeWarning(Writer out, String message, String code, String detail) throws Exception {
1150                    //out.write(DBSConstants.XML_EXCEPTION_HEADER);
1151                    message = message.replace('\'',' ');
1152                    detail= detail.replace('\'',' ');
1153                    code =code.replace('\'',' ');
1154                    out.write("<warning message='" + message + "' ");
1155                    out.write(" code ='" + code + "' ");
1156                    out.write(" detail ='" + detail + "' />\n");
1157                    out.flush();
1158                    //out.write(DBSConstants.XML_EXCEPTION_FOOTER);
1159            }
1160    
1161    
1162    
1163    
1164            /*TODO more information needed and change in the schema required,
1165             * private void insertMCDesc(Connection conn, Hashtable table, String userID) throws Exception {
1166                    String mcDesc = get(table, "mc_channel_description", true);
1167                    String mcProd = get(table, "mc_production", false);
1168                    String mcChain = get(table, "mc_decay_chain", false);
1169    
1170                    //Insert a new Lumi Section by feting the run ID 
1171                    if( getMCDescID(conn, mcDesc, mcProd, mcChain) == null ) {
1172                            DBManagement.execute(conn, DBSSql.insertMCDesc(mcDesc, mcProd, mcChain, userID));
1173                    }
1174            }*/
1175    
1176            /**
1177             * This is a private generic method that can insert entry into any table that has just one coloum in it which is unique. Since there are many such tables in the schema that has such kind of tables, therefore this method is resued several times to insert rows in them. It first checks of the row already exist in the database or not. Only if it does not exist, it goes ahead and performs a new insert.
1178             * @param table the table name of the table in the database schema.
1179             * @param key the coloumn name of the table in the database schema that is unique.
1180             * @param value the value to be inserted in the coloumn name of the table.
1181             * @param userID a user id of the person who is insertin this new row into this given database table. The user id correspond to the Person table id in database. This is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1182             */
1183            private void insertName(Connection conn, String table, String key, String value, String userID) throws Exception {
1184                    if(isNull(value)) throw new DBSException("Missing data", "1006", "Null field. Expected a valid " + key );
1185                    if(isNull(userID)) throw new DBSException("Missing data", "1006", "Null field. Expected a valid UserDN");
1186                    if( getID(conn, table, key, value, false) == null ) {
1187                            PreparedStatement ps = null;
1188                            try {
1189                                    ps = DBSSql.insertName(conn, table, key, value, userID);
1190                                    ps.execute();
1191                            } finally {
1192                                    if (ps != null) ps.close();
1193                            }
1194                    }
1195            }
1196            
1197            /**
1198             * This is a private generic method that can insert entry into any table that has just two coloum in it which are unique. Since there are many such tables in the schema that has such kind of tables, therefore this method is resued several times to insert rows in them. It first checks of the row already exist in the database or not. Only if it does not exist, it goes ahead and performs a new insert.
1199             * @param table the table name of the table in the database schema.
1200             * @param key1 the first coloumn name of the table in the database schema.
1201             * @param key2 the second coloumn name of the table in the database schema.
1202             * @param value1 the first value to be inserted in the first coloumn name of the table.
1203             * @param value2 the second value to be inserted in the second coloumn name of the table.
1204             * @param userID a user id of the person who is insertin this new row into this given database table. The user id correspond to the Person table id in database. This is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1205             */
1206            private void insertMap(Connection conn, String tableName, String key1, String key2, String value1, String value2, String userID) throws Exception {
1207                    if( getMapID(conn, tableName, key1, key2, value1, value2, false) == null ) {
1208                            PreparedStatement ps = null;
1209                            try {
1210                                    ps = DBSSql.insertMap(conn, tableName, key1, key2, value1, value2, userID);
1211                                    ps.execute();
1212                            } finally {
1213                                    if (ps != null) ps.close();
1214                            }
1215                    }       
1216    
1217            }
1218    
1219    
1220            /**
1221             * Insert a parameter set whose parameters are provided in the passed algo <code>java.util.Hashtable</code>. This hashtable is generated externally and filled in with the lumi section parameters by parsing the xml input provided by the client. This method inserts entry into just one  QueryableParameterSet table. The the main query that it executes to insert in QueryableParameterSet table, get generated by <code>dbs.DBSSql.insertParameterSet</code> method.<br> 
1222             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
1223             * Then it insert a new parameter set whose sql query is generated by calling <code>dbs.sql.insertParameterSet<code>
1224             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1225             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
1226             * @param algo a <code>java.util.Hastable</code>  that contain all the necessary key value pairs required for inserting a new parameter set. The keys along with its values that it may or may not contain are <br>
1227             * <code>ps_name, ps_hash, ps_version, ps_type, ps_annotation, ps_content</code> <br>
1228             * @param userID a user id of the person who is insertin this new row into this given database table. The user id correspond to the Person table id in database. This is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1229             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters in the hashtable are invalid, the database connection is unavailable.
1230             */
1231            private void insertParameterSet(Connection conn, Hashtable algo, String userID) throws Exception {
1232                    String psName = get(algo, "ps_name", true);
1233                    if( getID(conn, "QueryableParameterSet", "Name", psName, false) == null ) {
1234                            PreparedStatement ps = null;
1235                            try {
1236                                    ps = DBSSql.insertParameterSet(conn,
1237                                                    get(algo, "ps_hash", true), 
1238                                                    psName, 
1239                                                    getStr(algo, "ps_version", true), 
1240                                                    getStr(algo, "ps_type", true), 
1241                                                    getStr(algo, "ps_annotation", true), 
1242                                                    //FIXME We are allowing every thing in content, need to fix it
1243                                                    get(algo, "ps_content"), 
1244                                                    userID);
1245                                    ps.execute();
1246                            } finally {
1247                                    if (ps != null) ps.close();
1248                            }
1249                    }
1250            }
1251    
1252            /**
1253             * Insert a physics group whose parameters. This method inserts entry into just one PhysicsGroup table. The the main query that it executes to insert in PhysicsGroup table, get generated by <code>dbs.DBSSql.insertPhysicsGroup</code> method.<br> 
1254             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
1255             * Then it insert a new physics group if it does not already exist.
1256             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1257             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
1258             * @param name the name of the phsysics group to be inserted.
1259             * @param phyGroupCon the name of the physics group convenor to be inserted.
1260             * @param userID a user id of the person who is insertin this new row into this given database table. The user id correspond to the Person table id in database. This is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1261             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid or the database connection is unavailable.
1262             */
1263            public void insertPhysicsGroup(Connection conn, Writer out, String name, String phyGroupCon, String userID) throws Exception {
1264                    //Insert a new Person if it does not exists
1265                    insertPerson(conn, out,  "", phyGroupCon, "", userID); //FIXME Get userName and contactInfo also
1266                    if( getID(conn, "PhysicsGroup", "PhysicsGroupName", name, false) == null ) {
1267                            PreparedStatement ps = null;
1268                            try {
1269                                    ps = DBSSql.insertPhysicsGroup(conn,
1270                                            name, 
1271                                            getID(conn, "Person", "DistinguishedName", phyGroupCon, true), 
1272                                            userID);
1273                                    ps.execute();
1274                            } finally {
1275                                    if (ps != null) ps.close();
1276                            }
1277                    }
1278            }
1279    
1280            /**
1281             * Insert a new person in the Person table. This method inserts entry into just one Person table and its query is generated by <code>dbs.DBSSql.insertPerson</code> method.<br> 
1282             * First it fetches the userID by using the parameters specified in the dbsUser <code>java.util.Hashtable</code> and if the user does not exists then it insert the new user in the Person table. All this user operation is done by a private method getUserID. <br>
1283             * Then it insert a new user if it does not already exist.
1284             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1285             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
1286             * @param userName the name of the user to be inserted in the database.
1287             * @param userDN the distinguish name of the user to be inserted in the database.
1288             * @param contactInfo the contact infromation  of the user to be inserted in the database.
1289             * @param userID a user id of the person who is insertin this new row into this given database table. The user id correspond to the Person table id in database. This is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.
1290             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid or  the database connection is unavailable.
1291             */
1292            public void insertPerson(Connection conn, Writer out, String userName, String userDN, String contactInfo, String userID) throws Exception {
1293                    if (isNull(userID)) userID = "0";//0 is user not created by anyone
1294                    if( getID(conn, "Person", "DistinguishedName", userDN , false) == null ) {
1295                            PreparedStatement ps = null;
1296                            try {
1297                                    ps = DBSSql.insertPerson(conn, userName, userDN, contactInfo,  userID);
1298                                    ps.execute();
1299                            } finally {
1300                                    if (ps != null) ps.close();
1301                            }
1302                    }
1303            }
1304    
1305    
1306            /**
1307             * Gets a processed data set ID from the datbase by using the dataset path. This method calls another private method getProcessedDSID after spliting the dataset path.
1308             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1309             * @param path a dataset path in the format of /primary/tier/processed. If this path is not provided or the dataset id could not be found then an exception is thrown.
1310             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid or  the database connection is unavailable, or the processed dataset is not found.
1311             */
1312            private String getProcessedDSID(Connection conn, String path) throws Exception {
1313                    //checkPath(path);
1314                    String[] data = path.split("/");
1315                    if(data.length != 4) {
1316                            throw new DBSException("Invalid format", "1007", " Expected a path in format /PRIMARY/TIER/PROCESSED given " + path);
1317                    }
1318                    return  getProcessedDSID(conn, data[1], data[2], data[3]);
1319            }
1320    
1321            /**
1322             * Gets a processed dataset id from the datbase by using the primary dataset name , data tier name and processed dataset name. This actually generates the sql by calling the <code>dbs.sql.DBSSql.getProcessedDSID</code> method. 
1323             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1324             * @param prim the name of the primary dataset whose processed dataset id needs to be fetched..
1325             * @param dt the name of the data tier whose processed dataset id needs to be fetched..
1326             * @param proc the name of the processed dataset whose id needs to be fetched..
1327             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid or  the database connection is unavailable, or the processed dataset is not found.
1328             */
1329            private String getProcessedDSID(Connection conn, String prim, String dt, String proc) throws Exception {
1330                    checkWord(prim, "primary_dataset_name");
1331                    checkWord(dt, "data_tier");
1332                    checkWord(proc, "processed_dataset_name");
1333                    //ResultSet rs =  DBManagement.executeQuery(conn, DBSSql.getProcessedDSID(prim, dt, proc));
1334                    String id = "";
1335                    PreparedStatement ps = null;
1336                    ResultSet rs = null;
1337                    try {
1338                            ps = DBSSql.getProcessedDSID(conn, prim, dt, proc);
1339                            rs =  ps.executeQuery();
1340                            if(!rs.next()) {
1341                                    throw new DBSException("Unavailable data", "1008", "No such processed dataset /" + prim + "/" + dt + "/" +proc );
1342                            }
1343                            id = get(rs, "ID");
1344                    } finally {
1345                            if (rs != null) rs.close();
1346                            if (ps != null) ps.close();
1347                    }
1348    
1349                    return  id;
1350            }
1351    
1352            /**
1353             * Gets a algorithm id from the database by using the application version, application family, application executable and parameter set name. This actually generates the sql by calling the <code>dbs.sql.DBSSql.getAlgorithmID</code> method. 
1354             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1355             * @param ver the name of the application version whose algorithm configuration id needs to be fetched.
1356             * @param fam the name of the application family whose algorithm configuration id needs to be fetched.
1357             * @param exe the name of the application executable whose algorithm configuration id needs to be fetched.
1358             * @param psName the name of the parameter set whose algorithm configuration id needs to be fetched.
1359             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid or  the database connection is unavailable, or the algorithm is not found.
1360             */
1361            private String getAlgorithmID(Connection conn, String ver, String fam, String exe, String psName) throws Exception {
1362                    checkWord(ver, "app_version");
1363                    checkWord(fam, "app_family_name");
1364                    checkWord(exe, "app_executable_name");
1365                    checkWord(psName, "ps_name");
1366                    //ResultSet rs =  DBManagement.executeQuery(conn, DBSSql.getAlgorithmID(ver, fam, exe, ps));
1367                    String id = "";
1368                    PreparedStatement ps = null;
1369                    ResultSet rs = null;
1370                    try {
1371                            ps =  DBSSql.getAlgorithmID(conn, ver, fam, exe, psName);
1372                            rs =  ps.executeQuery();
1373                            if(!rs.next()) {
1374                                    throw new DBSException("Unavailable data", "1009", "No such algorithm version: " + ver + " family: " + fam + " executable: " + exe + " parameter set: " + psName);
1375                            }
1376                            id = get(rs, "ID");
1377                    } finally {
1378                            if (rs != null) rs.close();
1379                            if (ps != null) ps.close();
1380                    }
1381    
1382                    return  id;
1383            }
1384    
1385            /*private String getMCDescID(Connection conn, String des, String prod, String chain, boolean excep) throws Exception {
1386                    if(excep) checkWord(des, "mc_channel_description");
1387                    else if(!isNull(des) checkWord(des, "mc_channel_description");
1388                    if(!isNull(prod)) checkWord(prod, "mc_production");
1389                    if(!isNull(chain)) checkWord(chain, "mc_decay_chain");
1390                    PreparedStatement ps = null;
1391                    ResultSet rs =  DBManagement.executeQuery(conn, DBSSql.getMCDescID(des, prod, chain));
1392                    if(!rs.next()) {
1393                            if(excep) throw new DBSException("Bad Data", "300", "No such MCDescription " + des + " " + prod + " " + chain);
1394                            else return null;
1395                    }
1396                    return  get(rs, "id");
1397            }*/
1398    
1399    
1400    
1401            /**
1402             * Gets a block id from the database by using the block name as the unique key. This actually generates the sql by calling a generic private <code>dbs.sql.DBSSql.getID</code> method. 
1403             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1404             * @param name the name of the block whose id needs to be fetched.
1405             * @param excep a boolean flag that determines if the exception needs to be raised if the block is not found.
1406             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid or  the database connection is unavailable, or the block is not found.
1407             */
1408            private String getBlockID(Connection conn, String name, boolean excep) throws Exception {
1409                    checkBlock(name);
1410                    //ResultSet rs =  DBManagement.executeQuery(conn, DBSSql.getID( "Block", "Name", name));
1411                    String id = "";
1412                    PreparedStatement ps = null;
1413                    ResultSet rs = null;
1414                    try {
1415                            ps = DBSSql.getID(conn, "Block", "Name", name);
1416                            rs =  ps.executeQuery();
1417                            if(!rs.next()) {
1418                                    if(excep) throw new DBSException("Unavailable data", "1010", "No such block : name : "  + name );
1419                                    else return null;
1420                            }
1421                            id = get(rs, "ID");
1422                    } finally {
1423                            if (rs != null) rs.close();
1424                            if (ps != null) ps.close();
1425                    }
1426    
1427                    return  id;
1428            }
1429    
1430    
1431            /**
1432             * Gets a id of a table from the given database table using the key value pair specified in the parameters. This method can be called to fetch the id of any table that has just one unique key. The sql is generated by calling a generic private <code>dbs.sql.DBSSql.getID</code> method. 
1433             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1434             * @param tableName the name of the table in the database whose id needs to fetched.
1435             * @param key the name of the only unique coloumn in the given table whose id needs to fetched.
1436             * @param value the value of the only unique coloumn in the given table whose id needs to fetched.
1437             * @param excep a boolean flag that determines if the exception needs to be raised if the block is not found.
1438             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid or  the database connection is unavailable, or the table id is not found.
1439             */
1440            private String getID(Connection conn, String tableName, String key, String value, boolean excep) throws Exception {
1441                    if(isNull(tableName) || isNull(key) || isNull(value)) {
1442    
1443                         if(excep) throw new DBSException("Unavailable data", "1011", "No such " + 
1444                                                                                     tableName + " : " + key + " : " + value );
1445                         return null;
1446                    } 
1447                    if (excep) checkWord(value, key);
1448                    else if(!isNull(value)) checkWord(value, key);
1449    
1450                    //ResultSet rs =  DBManagement.executeQuery(conn, DBSSql.getID(tableName, key, value));
1451                    String id = "";
1452                    PreparedStatement ps = null;
1453                    ResultSet rs = null;
1454                    try {
1455                            ps =  DBSSql.getID(conn, tableName, key, value);
1456                            rs =  ps.executeQuery();
1457                            if(!rs.next()) {
1458                                    if(excep) throw new DBSException("Unavailable data", "1011", "No such " + tableName + " : " + key + " : " + value );
1459                                    else return null;
1460                            }
1461                            id = get(rs, "ID");
1462                    } finally {
1463                            if (rs != null) rs.close();
1464                            if (ps != null) ps.close();
1465                    }
1466    
1467                    return  id;
1468            }
1469    
1470    
1471            /**
1472             * Gets a id of a table from the given database table using the two key value pair specified in the parameters. This method can be called to fetch the id of any table that has excatly two unique keys. The sql is generated by calling a generic private <code>dbs.sql.DBSSql.getMapID</code> method. 
1473             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1474             * @param tableName the name of the table in the database whose id needs to fetched.
1475             * @param key1 the name of the first unique coloumn in the given table whose id needs to fetched.
1476             * @param key2 the name of the second unique coloumn in the given table whose id needs to fetched.
1477             * @param value1 the value of the first unique coloumn in the given table whose id needs to fetched.
1478             * @param value2 the value of the second unique coloumn in the given table whose id needs to fetched.
1479             * @param excep a boolean flag that determines if the exception needs to be raised if the block is not found.
1480             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid or  the database connection is unavailable, or the table id is not found.
1481             */
1482            private String getMapID(Connection conn, String tableName, String key1, String key2, String value1, String value2,  boolean excep) throws Exception {
1483                    if(isNull(tableName) || isNull(key1) || isNull(value1) || isNull(key2) || isNull(key2) ) return null;
1484                    if (excep) {
1485                            checkWord(value1, key1);
1486                            checkWord(value2, key2);
1487                    } else {
1488                            if(!isNull(value1)) checkWord(value1, key1);
1489                            if(!isNull(value2)) checkWord(value2, key2);
1490                    }
1491                    //ResultSet rs =  DBManagement.executeQuery(conn, DBSSql.getMapID(tableName, key1, key2, value1, value2));
1492                    String id = "";
1493                    PreparedStatement ps = null;
1494                    ResultSet rs = null;
1495                    try {
1496                            ps =  DBSSql.getMapID(conn, tableName, key1, key2, value1, value2);
1497                            rs =  ps.executeQuery();
1498                            if(!rs.next()) {
1499                                    if(excep) throw new DBSException("Unavailable data", "1012", "No such " + tableName + " : " + key1 + " : " + value1 + " : " + key2 + " : " + value2);
1500                                    else return null;
1501                            }
1502                            id = get(rs, "ID");
1503                    } finally {
1504                            if (rs != null) rs.close();
1505                            if (ps != null) ps.close();
1506                    }
1507    
1508                    return  id;
1509            }
1510    
1511            /**
1512             * Gets a id of a user from the Person table in the database. 
1513             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
1514             * @param dbsUser a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single user. The most import key in this table is the user_dn. This hashtable is used to insert the bookkeeping information with each row in the database. This is to know which user did the insert at the first place.  The keys along with its values that it may or may not contain are  <code>user_dn</code>
1515             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid or  the database connection is unavailable, or the table id is not found.
1516             */
1517            private String getUserID(Connection conn, Hashtable dbsUser) throws Exception {
1518                    String id = "";
1519                    String userDN = get(dbsUser, "user_dn", true);
1520                    if ( (id = getID(conn, "Person", "DistinguishedName", userDN , false)) == null) {
1521                            //FIXME instead of passing null for out stream writer , pass teh actual stream
1522                            insertPerson(conn, null,  "", userDN, "", ""); //FIXME Get userName and contactInfo also and the userID shoudl be decicde?
1523                            id = getID(conn, "Person", "DistinguishedName", userDN , true);
1524                    }
1525                    return id;
1526            }
1527    
1528            /**
1529             * Checks the dataset path against a regular expression that validates a valid dataset path.
1530             * @param path a dataset path in the format of /primary/tier/processed. If this path is not provided or the dataset id could not be found then an exception is thrown.
1531             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid.
1532             */
1533            private void checkPath(String path) throws Exception {
1534                    if(isNull(path)) 
1535                            throw new DBSException("Missing data", "1006", "Null Fields. Expected a valid path in format /PRIMARY/TIER/PROCESSED");
1536                    if (! Pattern.matches(VALID_PATH, path) ) 
1537                            throw new DBSException("Invalid format", "1007", "Expected a path in format /PRIMARY/TIER/PROCESSED which should satisfy the regular expression " + VALID_PATH + " The given path is " + path);
1538                    if( ! Pattern.matches(SAFE_PATH, path) ) 
1539                            throw new DBSException("Invalid format", "1013", "Invalid Characters in " + path + " for path. Expected a path in format /PRIMARY/TIER/PROCESSED  which should satisfy the regular expression  "+ SAFE_PATH);
1540            }
1541            
1542            /**
1543             * Checks the dataset block name against a regular expression that validates a valid block name.
1544             * @param blockName the name of the block in the format of /primary/processed#GUID. If this blockName is not provided or the block id could not be found then an exception is thrown.
1545             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid.
1546             */
1547            private void checkBlock(String blockName) throws Exception {
1548                    if(isNull(blockName)) 
1549                            throw new DBSException("Missing data", "1006", "Null Fields. Expected a valid block_name in format /PRIMARY/PROCESSED#GUID");
1550                    if (! Pattern.matches(VALID_BLOCK, blockName) ) 
1551                            throw new DBSException("Invalid format", "1014", "Expected a block_name in format /PRIMARY/PROCESSED#GUID which should satisfy the regular expression " + VALID_BLOCK + " The given block_name is " + blockName);
1552                    if( ! Pattern.matches(SAFE_BLOCK, blockName) ) 
1553                            throw new DBSException("Invalid format", "1015", "Invalid Characters in " + blockName + " for block_name. Expected a block_name in format /PRIMARY/PROCESSED#GUID which should satisfy the regular expression " + SAFE_BLOCK);
1554            }
1555            
1556    
1557            /**
1558             * Checks a word a s whole against a regular expression that validates a english word without any special characters.
1559             * @param pattern the value of the word that needs to be validated.
1560             * @param key the name of the key which is used to throw an exception in case the word fails to validate. This make the exception message more intutive as it states which key was being checked.
1561             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid.
1562             */
1563            private void checkWord(String pattern, String key) throws Exception {
1564                    if(isNull(pattern))
1565                            throw new DBSException("Missing data", "1006", "Null Fields. Expected a valid " + key);
1566                    if (! Pattern.matches(SAFE_WORD, pattern)) 
1567                            throw new DBSException("Invalid format", "1016", "Invalid Characters in " + pattern + " for " + key + " Expected a valid " + key + " which should satisfy the regular expression "+ SAFE_WORD);
1568            }
1569            
1570            /**
1571             * Checks a sentence  against a regular expression that validates a english sentence without any special characters.
1572             * @param pattern the value of the word that needs to be validated.
1573             * @param key the name of the key which is used to throw an exception in case the word fails to validate. This make the exception message more intutive as it states which key was being checked.
1574             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied parameters are invalid.
1575             */
1576            private void checkString(String pattern, String key) throws Exception {
1577                    if(isNull(pattern))
1578                            throw new DBSException("Missing data", "1006", "Null Fields. Expected a valid " + key);
1579                    if (! Pattern.matches(SAFE_STR, pattern))
1580                            throw new DBSException("Invalid format", "1017", "Invalid Characters in " + pattern + " for " + key + " Expected a valid " + key + " which should satisfy the regular expression " + SAFE_STR);
1581            }
1582    
1583    
1584            private boolean isNull(String pattern) {
1585                    return DBSUtil.isNull(pattern);
1586            }
1587            
1588            private String get(Hashtable table, String key, boolean excep) throws Exception{
1589                    String value = DBSUtil.get(table, key);
1590                    if(excep) checkWord(value, key);
1591                    else if(! isNull(value)) checkWord(value, key);
1592                    return value;
1593            }
1594    
1595            private String getStr(Hashtable table, String key, boolean excep) throws Exception{
1596                    String value = DBSUtil.get(table, key);
1597                    if(excep) checkString(value, key);
1598                    else if(! isNull(value)) checkString(value, key);
1599                    return value;
1600            }
1601    
1602    
1603            private String get(Hashtable table, String key) {
1604                    return DBSUtil.get(table, key);
1605            }
1606    
1607            private String get(ResultSet rs, String key) throws Exception {
1608    
1609                    String value = rs.getString(key);
1610                    if(isNull(value)) return "";
1611                    return value;
1612            }
1613            private String getPattern(String pattern, String key) throws Exception {
1614                    if(isNull(pattern))  return "%";
1615                    pattern = pattern.replace('*','%');
1616                    checkWord(pattern,key);
1617                    return pattern;
1618            }
1619    
1620            
1621    }