001    /**
002     $Revision: 1.5 $"
003     $Id: DBSApiFileLogic.java,v 1.5 2007/01/08 17:45:39 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.Hashtable;
013    import java.util.Vector;
014    import dbs.sql.DBSSql;
015    import dbs.util.DBSUtil;
016    import dbs.DBSException;
017    
018    /**
019    * A class that has the core business logic of all the File APIs.  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>. This class inherits from DBSApiLogic class.
020    * @author sekhri
021    */
022    public class DBSApiFileLogic extends DBSApiLogic {
023                    
024            /**
025            * Constructs a DBSApiLogic object that can be used to invoke several APIs.
026            */
027            DBSApiPersonLogic personApi = null;
028            public DBSApiFileLogic() {
029                    personApi = new DBSApiPersonLogic();
030            }
031    
032    
033            /**
034             * 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>
035             * <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>
036             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
037             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
038             * @param path a dataset path in the format of /primary/tier/processed. This path is used to find the existing processed dataset id.
039             * @param blockName a block name in the format of /primary/processed#GUID. This block name is used to find the existing block id.
040             * @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.
041             * @param detail a parameter to determine whether the details of the files needs to be listed or not.
042             * @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.
043             */
044            public void listFiles(Connection conn, Writer out, String path, String blockName, String patternLFN, String detail) throws Exception {
045    
046                    //By default a file detail is not needed
047    
048                    String procDSID = null;
049                    String blockID = null;
050                    if(!isNull(path)) {
051                            procDSID = (new DBSApiProcDSLogic()).getProcessedDSID(conn, path);
052                    }
053                    if(!isNull(blockName)) {
054                            blockID = (new DBSApiBlockLogic()).getBlockID(conn, blockName, false, true);
055                            //FIXME: We need to make sure that we MUST have ONLY an OPEN Block for adding a file to !
056                           
057                    }
058                    if(blockID == null && procDSID == null) {
059                            throw new DBSException("Missing data", "1005", "Null Fields. Expected either a Processed Dataset or a Block");
060                    }
061                    PreparedStatement ps = null;
062                    ResultSet rs =  null;
063                    try {
064                            ps = DBSSql.listFiles(conn, procDSID, blockID, getPattern(patternLFN, "pattern_lfn"));
065                            rs =  ps.executeQuery();
066                            while(rs.next()) {
067                                    String fileID = get(rs, "ID");
068                                    String lfn = get(rs, "LFN");
069                                    out.write(((String) "<file id='" + fileID +
070                                            "' lfn='" + lfn +
071                                            "' checksum='" + get(rs, "CHECKSUM") +
072                                            "' size='" + get(rs, "FILESIZE") +
073                                            "' queryable_meta_data='" + get(rs, "QUERYABLE_META_DATA") +
074                                            "' number_of_events='" + get(rs, "NUMBER_OF_EVENTS") +
075                                            "' validation_status='" + get(rs, "VALIDATION_STATUS") +
076                                            "' type='" + get(rs, "TYPE") +
077                                            "' status='" + get(rs, "STATUS") +
078                                            "' block_name='" + get(rs, "BLOCK_NAME") +
079                                            "' creation_date='" + getTime(rs, "CREATION_DATE") +
080                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
081                                            "' created_by='" + get(rs, "CREATED_BY") +
082                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
083                                            "'>\n"));
084                                    if (!isNull(detail)) {
085                                            globalFile = new Hashtable();
086                                            globalFile.put(lfn, fileID);
087                                            listFileParents(conn, out, lfn);
088                                            listFileAlgorithms(conn, out, lfn);
089                                            listFileTiers(conn, out, lfn);
090                                            listFileLumis(conn, out, lfn);
091                                    }
092                                    out.write(((String) "</file>\n"));
093          
094                            }
095                    } finally { 
096                            if (rs != null) rs.close();
097                            if (ps != null) ps.close();
098                    }
099    
100            }
101    
102            /**
103             * Lists all the parents of the given file.  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.listFileParents</code> method. It writes a list of logical file names on the output stream.  A sample XML that is written to the output stream is like <br>
104             * <code> <""/></code>
105             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
106             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
107             * @param lfn the logical file name of the file whose parents needs to be listed.
108             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied lfn is invalid, the database connection is unavailable or the file is not found.
109             */
110             public void listFileParents(Connection conn, Writer out, String lfn) throws Exception {
111                    PreparedStatement ps = null;
112                    ResultSet rs =  null;
113                    try {
114                            ps = DBSSql.listFileParents(conn, getFileID(conn, lfn, true));
115                            rs =  ps.executeQuery();
116                            while(rs.next()) {
117                                    out.write(((String) "<file-parent id='" +  get(rs, "ID") +
118                                            "' lfn='" + get(rs, "LFN") +
119                                            "' checksum='" + get(rs, "CHECKSUM") +
120                                            "' size='" + get(rs, "FILESIZE") +
121                                            "' queryable_meta_data='" + get(rs, "QUERYABLE_META_DATA") +
122                                            "' number_of_events='" + get(rs, "NUMBER_OF_EVENTS") +
123                                            "' validation_status='" + get(rs, "VALIDATION_STATUS") +
124                                            "' type='" + get(rs, "TYPE") +
125                                            "' status='" + get(rs, "STATUS") +
126                                            "' block_name='" + get(rs, "BLOCK_NAME") +
127                                            "' creation_date='" + getTime(rs, "CREATION_DATE") +
128                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
129                                            "' created_by='" + get(rs, "CREATED_BY") +
130                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
131                                            "'/>\n"));
132                            }
133                    } finally { 
134                            if (rs != null) rs.close();
135                            if (ps != null) ps.close();
136                    }
137             }
138    
139             /**
140             * Lists all the algorithm configs of the given file.  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.listFileAlgorithms</code> method. It writes a list of algorithms on the output stream.  A sample XML that is written to the output stream is like <br>
141             * <code> <""/></code>
142             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
143             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
144             * @param lfn the logical file name of the file whose algorithms needs to be listed.
145             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied lfn is invalid, the database connection is unavailable or the file is not found.
146             */
147             public void listFileAlgorithms(Connection conn, Writer out, String lfn) throws Exception {
148                    PreparedStatement ps = null;
149                    ResultSet rs =  null;
150                    try {
151                            ps = DBSSql.listFileAlgorithms(conn, getFileID(conn, lfn, true));
152                            rs =  ps.executeQuery();
153                            while(rs.next()) {
154                                    out.write(((String) "<file-algorithm id='" + get(rs, "ID") + 
155                                            "' app_version='" + get(rs, "APP_VERSION") +
156                                            "' app_family_name='" + get(rs, "APP_FAMILY_NAME") +
157                                            "' app_executable_name='" + get(rs, "APP_EXECUTABLE_NAME") +
158                                            "' ps_name='" + get(rs, "PS_NAME") +
159                                            "' ps_hash='" + get(rs, "PS_HASH") +
160                                            "' creation_date='" + getTime(rs, "CREATION_DATE") +
161                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
162                                            "' created_by='" + get(rs, "CREATED_BY") +
163                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
164                                            "'/>\n"));
165                            }
166                    } finally { 
167                            if (rs != null) rs.close();
168                            if (ps != null) ps.close();
169                    }
170             }
171    
172             /**
173             * Lists all the data tiers of the given file.  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.listFileTiers</code> method. It writes a list of date tiers on the output stream.  A sample XML that is written to the output stream is like <br>
174             * <code> <""/></code>
175             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
176             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
177             * @param lfn the logical file name of the file whose data tiers needs to be listed.
178             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied lfn is invalid, the database connection is unavailable or the file is not found.
179             */
180             public void listFileTiers(Connection conn, Writer out, String lfn) throws Exception {
181                    PreparedStatement ps = null;
182                    ResultSet rs =  null;
183                    try {
184                            ps = DBSSql.listFileTiers(conn, getFileID(conn, lfn, true));
185                            rs =  ps.executeQuery();
186                            while(rs.next()) {
187                                    out.write(((String) "<file-data_tier id='" + get(rs, "ID") +
188                                            "' name='" + get(rs, "NAME") +
189                                            "' creation_date='" + getTime(rs, "CREATION_DATE") +
190                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
191                                            "' created_by='" + get(rs, "CREATED_BY") +
192                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
193                                            "'/>\n"));
194    
195                            }
196                    } finally { 
197                            if (rs != null) rs.close();
198                            if (ps != null) ps.close();
199                    }
200             }
201    
202             /**
203             * Lists all the lumi sections of the given file.  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.listFileLumis</code> method. It writes a list of lumi sections on the output stream.  A sample XML that is written to the output stream is like <br>
204             * <code> <""/></code>
205             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
206             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
207             * @param lfn the logical file name of the file whose lumi sections needs to be listed.
208             * @throws Exception Various types of exceptions can be thrown. Commonly they are thrown if the supplied lfn is invalid, the database connection is unavailable or the file is not found.
209             */
210             public void listFileLumis(Connection conn, Writer out, String lfn) throws Exception {
211                    PreparedStatement ps = null;
212                    ResultSet rs =  null;
213                    try {
214                            ps = DBSSql.listFileLumis(conn, getFileID(conn, lfn, true));
215                            rs =  ps.executeQuery();
216                            while(rs.next()) {
217                                    out.write(((String) "<file-lumi-section id='" +  get(rs, "ID") +
218                                            "' lumi_section_number='" + get(rs, "LUMI_SECTION_NUMBER") +
219                                            "' run_number='" + get(rs, "RUN_NUMBER") +
220                                            "' start_event_number='" + get(rs, "START_EVENT_NUMBER") +
221                                            "' end_event_number='" + get(rs, "END_EVENT_NUMBER") +
222                                            "' lumi_start_time='" + get(rs, "LUMI_START_TIME") +
223                                            "' lumi_end_time='" + get(rs, "LUMI_END_TIME") +
224                                            "' creation_date='" + getTime(rs, "CREATION_DATE") +
225                                            "' last_modification_date='" + get(rs, "LAST_MODIFICATION_DATE") +
226                                            "' created_by='" + get(rs, "CREATED_BY") +
227                                            "' last_modified_by='" + get(rs, "LAST_MODIFIED_BY") +
228                                            "'/>\n"));
229    
230                                    }
231                    } finally { 
232                            if (rs != null) rs.close();
233                            if (ps != null) ps.close();
234                    }
235             }
236    
237    
238           /**
239             * 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> 
240             * 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>
241             * 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>
242             * Then it iterates through all the files Hashtable provided in the files vector and inserts one file at a time. <br>
243             * 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>
244             * 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>
245             * 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>
246             * 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>
247             * Finally it updates the block information with correct number of files and size in bytes by calling the updateBlock method.
248             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
249             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
250             * @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>
251             * <code>lfn, checksum, number_of_events, size, queryable_meta_data, file_status, type, validation_status, lumi_section, data_tier, parent, algorithm, created_by, creation_date </code> <br>
252             * Further the keys <code>lumi_section, data_tier, parent, algorithm </code> are itself vector of Hashtable. <br>
253             * The key that <code>parent </code> hashtable may or may not contain is <code>lfn</code> <br>
254             * The key that <code>data_tier </code> hashtable may or may not contain is <code>name</code> <br>
255             * The keys that <code>lumi_section </code> hashtable may or may not contain are <br>
256             * <code>lumi_section_number, run_number, start_event_number, end_event_number, lumi_start_time, lumi_end_time</code> <br>
257             * The keys that <code>algorithm </code> hashtable may or may not contain are <br> 
258             * <code>app_version, app_family_name, app_executable_name, ps_name</code> <br>
259              * @param path a dataset path in the format of /primary/tier/processed. This path is used to find the existing processed dataset id.
260             * @param blockName a block name in the format of /primary/processed#GUID. This block name is used to find the existing block id.
261             * @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.
262             * @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.
263             */
264            public void insertFiles(Connection conn, Writer out, String path, String blockName, Vector files, Hashtable dbsUser) throws Exception {
265                    
266                    //Get the User ID from USERDN
267                    String lmbUserID = personApi.getUserID(conn, dbsUser);
268    
269                    /*//Check if all the path is in the files are same.
270                    if(files.size() > 0) {
271                            String path = get((Hashtable)files.get(0), "path");
272                            for (int i = 1; i < files.size() ; ++i) {
273                                    String tmpPath = get((Hashtable)files.get(i), "path");
274                                    if(!tmpPath.equals(path)) {
275                                            throw new DBSException("Bad Data", "300", "Different Processed Datatsets. All files in the list should belong to same processed datatset. Dataset1 " + path + " Datatset2 " + tmpPath);
276                                    }
277                            
278                            }
279                    }*/
280                    String procDSID = (new DBSApiProcDSLogic()).getProcessedDSID(conn, path);
281                    String blockID;
282    
283                    //If user INSIST to provide a BlockName
284                    if ( ! isNull(blockName) && !(blockName.equals("")) ) {
285                        blockID = (new DBSApiBlockLogic()).getBlockID(conn, blockName, true, true);
286                        //FIXME: We must need to verify that Block is OpenForWriting
287                        
288                    }
289                    //Let DBS choose the Block
290                    else {
291                        blockID = (new DBSApiBlockLogic()).dbsManagedBlockID(conn, procDSID, path, dbsUser);
292                    }
293                    //These tables are used to store the types and staus fileds along with thier id
294                    //If the id can be fetched from here then we do not have to fietch it from database again and again
295                    boolean newFileInserted = false;
296                    Hashtable statusTable = new Hashtable();
297                    Hashtable typeTable = new Hashtable();
298                    Hashtable valStatusTable = new Hashtable();
299                    String statusID = "";
300                    String typeID = "";
301                    String valStatusID = "";
302                    for (int i = 0; i < files.size() ; ++i) {
303                            Hashtable file = (Hashtable)files.get(i);
304                    
305                            String fileID = "";
306                            //String path = get(file, "path");
307                            //String blockName = get(file, "block_name");
308                            String lfn = get(file, "lfn", true);
309                            String fileStatus = get(file, "file_status", false);
310                            String type = get(file, "type", false);
311                            String valStatus = get(file, "validation_status", false);
312                            String cbUserID = personApi.getUserID(conn, get(file, "created_by", false), dbsUser );
313                            String creationDate = getTime(file, "creation_date", false);
314    
315                            Vector lumiVector = DBSUtil.getVector(file,"lumi_section");
316                            Vector tierVector = DBSUtil.getVector(file,"data_tier");
317                            Vector parentVector = DBSUtil.getVector(file,"parent");
318                            Vector algoVector = DBSUtil.getVector(file,"algorithm");
319                    
320                            //Set defaults Values
321                            if (isNull(fileStatus)) fileStatus = "VALID";
322                            if (isNull(type)) type = "EVD";
323                            if (isNull(valStatus)) valStatus = "VALID";
324                            
325                            //Insert a File status if it does not exists
326                            //insertName(conn, out, "Status", "Status", fileStatus , lmbUserID);
327    
328                            //Insert a File Validation status if it does not exists
329                            //insertName(conn, out, "Status", "Status", valStatus , lmbUserID);
330    
331                            //Insert a File Type if it does not exists
332                            //insertName(conn, out, "Type", "Type", type , lmbUserID);
333                            
334                            //Insert a File by fetching the fileStatus, type and validationStatus
335                            if( (fileID = getFileID(conn, lfn, false)) == null ) {
336                                    newFileInserted = true;
337                                    //TODO Exception of null status or type should be catched and parsed and 
338                                    //a proper message should be returned back to the user. Different Database can have different error message YUK
339                                    //Status should be defaulted to something in the database itself. A wrong status may insert a dafult value.
340                                    //User will never know about this YUK
341                                    if( isNull(statusID = get(statusTable, fileStatus)) ) {
342                                            statusID = getID(conn, "FileStatus", "Status", fileStatus, true);
343                                            statusTable.put(fileStatus, statusID);
344                                    }
345                                    if( isNull(typeID = get(typeTable, type)) ) {
346                                            typeID = getID(conn, "FileType", "Type", type, true);
347                                            typeTable.put(type, typeID);
348                                    }
349                                    if( isNull(valStatusID = get(valStatusTable, valStatus)) ) {
350                                            valStatusID = getID(conn, "FileStatus", "Status", valStatus, true);
351                                            valStatusTable.put(valStatus, valStatusID);
352                                    }
353            
354                                    PreparedStatement ps = null;
355                                    try {
356                                            ps = DBSSql.insertFile(conn, 
357                                                            procDSID, 
358                                                            blockID, 
359                                                            lfn, 
360                                                            get(file, "checksum", false), 
361                                                            get(file, "number_of_events", false), 
362                                                            get(file, "size", false), 
363                                                            statusID,
364                                                            typeID,
365                                                            valStatusID,
366                                                            get(file, "queryable_meta_data", false), 
367                                                            cbUserID, lmbUserID, creationDate);
368                                            ps.execute();
369                                    } finally { 
370                                            if (ps != null) ps.close();
371                                    }
372    
373                            } else {
374                                    //Write waring message that file exists already
375                                    writeWarning(out, "Already Exists", "1020", "File " + lfn + " Already Exists");
376                            }
377    
378                            //if(isNull(fileID)) fileID = getFileID(conn, lfn);
379                            //Fetch the File ID that was just inseted to be used for subsequent insert of other tables only if it is needed.
380                            //FileID is needed if any of the other table information is provided i.e the vector size is > 0
381                            if(algoVector.size() > 0 || tierVector.size() > 0 || parentVector.size() > 0 || lumiVector.size() > 0) 
382                                    if(isNull(fileID)) fileID = getFileID(conn, lfn, true);
383                                    //fileID = getFileID(conn, lfn, true);
384    
385                            //Insert FileAlgo table by fetching application ID. 
386                            //Use get with 2 params so that it does not do type checking, since it will be done in getID call.
387                            for (int j = 0; j < algoVector.size(); ++j) {
388                                    Hashtable hashTable = (Hashtable)algoVector.get(j);
389                                    insertMap(conn, out, "FileAlgo", "Fileid", "Algorithm", 
390                                                    fileID, 
391                                                    (new DBSApiAlgoLogic()).getAlgorithmID(conn, get(hashTable, "app_version"), 
392                                                                    get(hashTable, "app_family_name"), 
393                                                                    get(hashTable, "app_executable_name"),
394                                                                    get(hashTable, "ps_name"),
395                                                                    true), 
396                                                    cbUserID, lmbUserID, creationDate);
397                            }
398    
399                            //Insert FileTier table by fetching data tier ID
400                            for (int j = 0; j < tierVector.size(); ++j) {
401                                    insertMap(conn, out,    "FileTier", "Fileid", "DataTier", 
402                                            fileID, 
403                                            getID(conn, "DataTier", "Name", 
404                                                    get((Hashtable)tierVector.get(j), "name") , 
405                                                    true), 
406                                            cbUserID, lmbUserID, creationDate);
407                            }
408                            
409                            //Insert FileParentage table by fetching parent File ID
410                            for (int j = 0; j < parentVector.size(); ++j) {
411                                    insertMap(conn, out, "FileParentage", "ThisFile", "itsParent", 
412                                                    fileID, 
413                                                    getFileID(conn, get((Hashtable)parentVector.get(j), "lfn"), true),
414                                                    cbUserID, lmbUserID, creationDate);
415                            }
416                            //TODO Discussion about Lumi section is needed
417                            //Insert FileLumi table by first inserting and then fetching Lumi Section ID
418                            for (int j = 0; j < lumiVector.size(); ++j) {
419                                    Hashtable hashTable = (Hashtable)lumiVector.get(j);
420                                    //Insert A lumi Section if it does not exists
421                                    insertLumiSection(conn, out, hashTable, cbUserID, lmbUserID, creationDate);
422                                    insertMap(conn, out, "FileLumi", "Fileid", "Lumi", 
423                                                    fileID, 
424                                                    getID(conn, "LumiSection", "LumiSectionNumber", get(hashTable, "lumi_section_number") , true), 
425                                                    cbUserID, lmbUserID, creationDate);
426                            }
427                    
428                            if ( i%100 == 0) conn.commit(); //For Every 100 files commit the changes
429                    }//For loop
430                    //Update Block numberOfFiles and Size
431                    if (newFileInserted) {
432                            PreparedStatement ps = null;
433                            try {
434                                    ps = DBSSql.updateBlock(conn, blockID);
435                                    ps.executeUpdate();
436                            } finally { 
437                                    if (ps != null) ps.close();
438                            }
439                    }
440    
441            }
442    
443            /**
444             * Insert a data tier in file. 
445             * 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>
446             * 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.
447             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
448             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
449             * @param table a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single file. The keys along with its values that it may or may not contain are <br>
450             * <code>lfn, created_by, creation_date </code> <br>
451             * If this lfn is not provided or the file id could not be found then an exception is thrown.
452             * @param tierName a data tier name which is assumed to be already present in the database.
453             * @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.
454             * @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.
455             */
456            public void insertTierInFile(Connection conn, Writer out, Hashtable table, String tierName, Hashtable dbsUser) throws Exception {
457                    insertMap(conn, out, "FileTier", "Fileid", "DataTier", 
458                                    getFileID(conn, get(table, "lfn", true), true), 
459                                    getID(conn, "DataTier", "Name", tierName , true), 
460                                    personApi.getUserID(conn, get(table, "created_by", false), dbsUser ),
461                                    personApi.getUserID(conn, dbsUser),
462                                    getTime(table, "creation_date", false));
463    
464            }
465            
466            /**
467             * Insert a parent in a file. 
468             * 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>
469             * 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.
470             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
471             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
472             * @param table a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single file. The keys along with its values that it may or may not contain are <br>
473             * <code>lfn, created_by, creation_date </code> <br>
474             * If this lfn is not provided or the file id could not be found then an exception is thrown.
475             * @param parentLFN a logical file name of the parent file.
476             * @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.
477             * @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.
478             */
479            public void insertParentInFile(Connection conn, Writer out, Hashtable table, String parentLFN, Hashtable dbsUser) throws Exception {
480                    insertMap(conn, out, "FileParentage", "ThisFile", "itsParent", 
481                                    getFileID(conn, get(table, "lfn", true), true),
482                                    getFileID(conn, parentLFN, true),
483                                    personApi.getUserID(conn, get(table, "created_by", false), dbsUser ),
484                                    personApi.getUserID(conn, dbsUser),
485                                    getTime(table, "creation_date", false));
486            }
487    
488    
489            /**
490             * Insert a algorithm in a file. 
491             * 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>
492             * 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.
493             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
494             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
495             * @param table a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single file. The keys along with its values that it may or may not contain are <br>
496             * <code>lfn, created_by, creation_date </code> <br>
497             * If this lfn is not provided or the file id could not be found then an exception is thrown.
498             * @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> 
499             * <code>app_version, app_family_name, app_executable_name, ps_name</code> <br>
500             * @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.
501             * @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.
502             */
503            public void insertAlgoInFile(Connection conn, Writer out, Hashtable table, Hashtable algo, Hashtable dbsUser) throws Exception {
504                    insertMap(conn, out, "FileAlgo", "Fileid", "Algorithm", 
505                                    getFileID(conn, get(table, "lfn", true), true), 
506                                    (new DBSApiAlgoLogic()).getAlgorithmID(conn, get(algo, "app_version"), 
507                                                    get(algo, "app_family_name"), 
508                                                    get(algo, "app_executable_name"),
509                                                    get(algo, "ps_name"), 
510                                                    true), 
511                                    personApi.getUserID(conn, get(table, "created_by", false), dbsUser ),
512                                    personApi.getUserID(conn, dbsUser),
513                                    getTime(table, "creation_date", false));
514            }
515    
516            /**
517             * Insert a lumi section in a file. 
518             * 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>
519             * 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.
520             * @param conn a database connection <code>java.sql.Connection</code> object created externally.
521             * @param out an output stream <code>java.io.Writer</code> object where this method writes the results into.
522             * @param table a <code>java.util.Hashtable</code> that contains all the necessary key value pairs for a single file. The keys along with its values that it may or may not contain are <br>
523             * <code>lfn, created_by, creation_date </code> <br>
524             * If this lfn is not provided or the file id could not be found then an exception is thrown.
525             * @param lsNumber a lumi section number that uniquely identifies a lumi section.
526             * @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.
527             * @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.
528             */
529            public void insertLumiInFile(Connection conn, Writer out, Hashtable table, String lsNumber, Hashtable dbsUser) throws Exception {
530                    insertMap(conn, out, "FileLumi", "Fileid", "Lumi", 
531                                    getFileID(conn, get(table, "lfn", true), true), 
532                                    getID(conn, "LumiSection", "LumiSectionNumber", lsNumber, true), 
533                                    personApi.getUserID(conn, get(table, "created_by", false), dbsUser ),
534                                    personApi.getUserID(conn, dbsUser),
535                                    getTime(table, "creation_date", false));
536            }
537    
538    
539    
540            private String getFileID(Connection conn, String lfn, boolean excep) throws Exception {
541                    String id = "";
542                    if(!isNull( id = get(globalFile, lfn) )) {
543                            return id;
544                    }
545                    if( !isNull(id = getID(conn, "Files", "LogicalFileName", lfn, excep)) ) {
546                            globalFile = new Hashtable();//Just store one file id only
547                            globalFile.put(lfn, id);
548                    }
549                    return id;
550            }
551            
552            
553    }