# HG changeset patch # User Daniele Nicolodi # Date 1323098406 -3600 # Node ID d58813ab1b92e077b860d3a4ca93c87d8878ce8c # Parent 69e3d49b4b0c766ae98d209c122356f87dd846c1 Update ltpda_uo.submit diff -r 69e3d49b4b0c -r d58813ab1b92 m-toolbox/classes/@ltpda_uo/submit.m --- a/m-toolbox/classes/@ltpda_uo/submit.m Mon Dec 05 16:20:06 2011 +0100 +++ b/m-toolbox/classes/@ltpda_uo/submit.m Mon Dec 05 16:20:06 2011 +0100 @@ -42,25 +42,25 @@ % then we call validate on the object before submitting. If validate is % true, then we set the validated flag in the database after submission if % it passes. -% -% +% +% function varargout = submit(varargin) - + % check if this is a call for parameters if utils.helper.isinfocall(varargin{:}) varargout{1} = getInfo(varargin{3}); return end - + import utils.const.* utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename); - + % collect all AOs [pls, invars, rest] = utils.helper.collect_objects(varargin(:), 'plist'); [sinfo, invars, objs] = utils.helper.collect_objects(rest(:), 'struct'); - + % identify plists which are only used for the submission process mask = false(numel(pls), 1); for ii = 1:numel(pls) @@ -77,22 +77,22 @@ if sum(~mask) pls = combine(pls(~mask)); end - + % rearrange nested objects lists into a single cell array objs = flatten(objs); - + if isempty(objs) error('### input at least one object to submit to the repository'); end - + % combine user plist with default pls = fixPlist(pls); dpl = getDefaultPlist(); pls = combine(pls, dpl.pset('HOSTNAME', '')); - + % for backwards compatibility convert any user supplied sinfo-structure into a plist pls = ltpda_uo.convertSinfo2Plist(pls, sinfo); - + % read XML submission informations file filename = pls.find('sinfo filename'); if ~isempty(filename) @@ -103,106 +103,48 @@ error('### unable to read specified file: %s', filename); end end - + % collect additional informations sinfo = ltpda_uo.submitDialog(pls); if isempty(sinfo) [varargout{1}, varargout{2}] = userCanceled(); return end - + % check completeness of user supplied informations sinfo = checkSinfo(sinfo); - - % user supplied connection - conn = find(pls, 'conn'); - - % obtain a connection from the connection manager - rm = LTPDARepositoryManager(); - - if isempty(conn) - connections = rm.findConnections(pls); - if isempty(connections) - % no connection found. create a new one - conn = rm.newConnection(pls); - if isempty(conn) - [varargout{1}, varargout{2}] = userCanceled(); - return - end - elseif numel(connections) == 1 && ~utils.prog.yes2true(pls.find('use selector')) - % found only one connection and we are not forcing the use of the selector - conn = connections(1); - else - % make the user select the desired database connection - conn = rm.manager.selectConnection([]); - if isempty(conn) - [varargout{1}, varargout{2}] = userCanceled(); - return - end - end - end - - % avoid to ask for a password if one was specified in the plist - if isjava(conn) && ~conn.isConnected() - passwd = pls.find('password'); - if ~isempty(passwd) - conn.setPassword(passwd); - end - end - - % connect to the database - if isempty(conn.openConnection()) - error('### unable to connect to the database') - end - + + % database connection + c = LTPDADatabaseConnectionManager().connect(pls); + utils.helper.msg(msg.PROC1, 'submitting %d objects to repository', numel(objs)); - + try - % lock connection to avoid expire during processing - conn.setLocked(true); - - % reload connection table if we have a GUI - if ~isempty(rm.gui) - rm.gui.reloadConnectionTable(); - end - - % look-up user id - userid = utils.jmysql.getUserID(conn); - username = conn.getUsername(); - - utils.helper.msg(msg.PROC1, 'got user id %d for user: %s', userid, char(username)); - if userid < 1 || isnan(userid) || strcmp(userid, 'No Data') || ischar(userid) - error('### Unknown username.'); - end + % get username and userid + [username, userid] = utils.repository.getUser(c); % author of the data: let's take the username author = username; - + % date for the transaction.transdata and objmeta.submitted columns as UTC time string t = time(); tdate = format(t, 'yyyy-mm-dd HH:MM:SS', 'UTC'); - + % machine details prov = provenance(); - - utils.helper.msg(msg.IMPORTANT, 'submitting to %s@%s:%s', ... - char(conn.getUsername), char(conn.getHostname), char(conn.getDatabase)); - - % obtain the underlying connection - c = conn.getConn(); - + % start a transaction. either we submitt all objects or we roll back all changes c.setAutoCommit(false); - + % process each object and collect id numbers ids = zeros(numel(objs), 1); cid = []; for kk = 1:numel(objs) - + % this object obj = objs{kk}; - + utils.helper.msg(msg.PROC1, 'submitting object: %s / %s', class(obj), obj.name); - + % format object creation time as UTC time string if isa(obj, 'plist') % plist-objects stores creatins time as milli secs since the epoch @@ -210,13 +152,13 @@ else created = obj.created.format('yyyy-mm-dd HH:MM:SS', 'UTC'); end - + % Set the UUID if it is empty. This should only happen for PLIST % objects. if isempty(obj.UUID) obj.UUID = char(java.util.UUID.randomUUID); end - + % create an XML representaion of the object if utils.prog.yes2true(pls.find('binary')); utils.helper.msg(msg.PROC2, 'binary submit'); @@ -225,16 +167,16 @@ utils.helper.msg(msg.PROC2, 'xml submit'); otxt = utils.prog.obj2xml(obj); end - + % create an MD5 hash of the xml representation md5hash = utils.prog.hash(otxt, 'MD5'); - + % create a binary representaion of the object bobj = utils.prog.obj2binary(obj); if isempty(bobj) error('### failed to obtain a binary representation'); end - + % submit object to objs table stmt = c.prepareStatement(... 'INSERT INTO objs (xml, hash, uuid) VALUES (?, ?, ?)'); @@ -242,7 +184,7 @@ stmt.setObject(2, char(md5hash)); stmt.setObject(3, obj.UUID); stmt.executeUpdate(); - + % obtain object id rs = stmt.getGeneratedKeys(); if rs.next() @@ -252,7 +194,7 @@ end rs.close(); stmt.close(); - + % insert binary representation stmt = c.prepareStatement(... 'INSERT INTO bobjs (obj_id, mat) VALUES (?,?)'); @@ -260,14 +202,14 @@ stmt.setObject(2, bobj); stmt.execute(); stmt.close(); - + % reference IDs are stored in a CSV string if ischar(sinfo.reference_ids) refids = sinfo.reference_ids; else refids = utils.prog.csv(sinfo.reference_ids); end - + % insert object meta data stmt = c.prepareStatement(... [ 'INSERT INTO objmeta (obj_id, obj_type, name, created, version, ' ... @@ -294,18 +236,18 @@ stmt.setObject(18, java.lang.String(author)); stmt.execute(); stmt.close(); - + % update other meta-data tables - cols = utils.jmysql.execute(c, 'SHOW COLUMNS FROM tsdata'); + cols = utils.mysql.execute(c, 'SHOW COLUMNS FROM tsdata'); if utils.helper.ismember('obj_id', cols(:,1)) % the tsdata table contains an obj id column. use the new database schema - utils.jmysql.insertObjMetadata(c, obj, objid); + utils.repository.insertObjMetadata(c, obj, objid); else % otherwise use the old one utils.helper.msg(msg.PROC2, 'using back-compatibility code'); - utils.jmysql.insertObjMetadataV1(c, obj, objid); + utils.repository.insertObjMetadataV1(c, obj, objid); end - + % update transactions table stmt = c.prepareStatement(... 'INSERT INTO transactions (obj_id, user_id, transdate, direction) VALUES (?, ?, ?, ?)'); @@ -315,21 +257,21 @@ stmt.setObject(4, java.lang.String('in')); stmt.execute(); stmt.close(); - + % collect the id of the submitted object ids(kk) = objid; end - + % make collection entry if numel(objs) > 1 - + % insert record into collections table stmt = c.prepareStatement(... 'INSERT INTO collections (nobjs, obj_ids) VALUES (?, ?)'); stmt.setObject(1, length(ids)); stmt.setObject(2, java.lang.String(utils.prog.csv(ids))); stmt.executeUpdate(); - + % obtain collection id rs = stmt.getGeneratedKeys(); if rs.next() @@ -339,35 +281,32 @@ end rs.close(); stmt.close(); - + end - + catch ex utils.helper.msg(msg.IMPORTANT, 'submission error. no object submitted') c.close() - conn.setLocked(false); rethrow(ex) end - + % commit the transaction c.commit(); - + + % close the connection if we own it + if isempty(find(pls, 'conn')) + c.close(); + end + % report IDs of the inserted objects for kk = 1:numel(objs) - utils.helper.msg(msg.IMPORTANT, 'submitted %s object with ID: %d, UUID: %s, name: %s', ... + utils.helper.msg(msg.IMPORTANT, 'submitted %s object with ID: %d UUID: %s name: %s', ... class(objs{kk}), ids(kk), objs{kk}.UUID, objs{kk}.name); end if ~isempty(cid) utils.helper.msg(msg.IMPORTANT, 'made collection entry with ID: %d', cid); end - - % unlock connection expire - conn.setLocked(false); - - % reset timer - LTPDARepositoryManager.resetTimer(rm.timerClearPass, conn); - LTPDARepositoryManager.resetTimer(rm.timerDisconnect, conn); - + % pass back outputs if nargout > 0 varargout{1} = ids; @@ -389,23 +328,23 @@ function sinfo = checkSinfo(sinfo) % check sinfo structure - + import utils.const.* - + % fieldnames mainfields = {'experiment_title', 'experiment_description', 'analysis_description'}; extrafields = {'quantity', 'keywords', 'reference_ids', 'additional_comments', 'author', 'additional_authors'}; - + % fieldnames of the input structure fnames = fieldnames(sinfo); - + % check mandatory fields for jj = 1:length(mainfields) if ~ismember(fnames, mainfields{jj}) error('### the sinfo structure should contain a ''%s'' field', mainfields{jj}); end end - + % check extra fields for jj = 1:length(extrafields) if ~ismember(fnames, extrafields{jj}) @@ -413,7 +352,7 @@ sinfo.(extrafields{jj}) = ''; end end - + % additional checks if length(sinfo.experiment_title) < 5 error('### ''experiment title'' should be at least 5 characters long'); @@ -424,7 +363,7 @@ if length(sinfo.analysis_description) < 10 error('### ''analysis description'' should be at least 10 characters long'); end - + end @@ -451,12 +390,12 @@ end function plo = buildplist() - + plo = plist.TO_REPOSITORY_PLIST; - + p = param({'sinfo filename', 'Path to an XML file containing submission metadata'}, paramValue.EMPTY_STRING); plo.append(p); - + p = param({'binary', 'Submit only binary version of the objects'}, paramValue.FALSE_TRUE); plo.append(p); end @@ -474,23 +413,23 @@ function flat = flatten(objs) % flatten nested lists into a single cell array - + flat = {}; - + while iscell(objs) && numel(objs) == 1 objs = objs{1}; end - + if numel(objs) == 1 flat = {objs}; return; end - + for jj = 1:numel(objs) obj = flatten(objs(jj)); for kk = 1:numel(obj) flat = [ flat obj(kk) ]; end end - + end