001/*
002 * Copyright (c) 2010-2011 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: barseghian $'
006 * '$Date: 2013-01-15 21:33:01 +0000 (Tue, 15 Jan 2013) $' 
007 * '$Revision: 31328 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.kepler.util;
031
032import java.util.ArrayList;
033import java.util.Iterator;
034import java.util.List;
035
036import org.kepler.build.modules.Module;
037import org.kepler.configuration.ConfigurationManager;
038import org.kepler.configuration.ConfigurationManagerException;
039import org.kepler.configuration.ConfigurationNamespace;
040import org.kepler.configuration.ConfigurationProperty;
041import org.kepler.configuration.NamespaceException;
042import org.kepler.objectmanager.lsid.KeplerLSID;
043import org.kepler.workflowrunmanager.WRMDefaults;
044
045public class RemoteStoreRunsTracker {
046
047        private final static String TRACKER_FILE_NAME ="remoteRunTracker";
048        private Module _provenanceModule = ConfigurationManager.getModule(WRMDefaults.moduleName);
049        private ConfigurationNamespace _configurationNamespace = 
050                new ConfigurationNamespace(TRACKER_FILE_NAME);
051        
052        private final static String REPOSITORIES = "repositories";
053        private final static String REPOSITORY = "repository";
054        private final static String NAME = "name";
055        private final static String RUN = "run";
056        
057        public enum TrackerRunAttribute {
058                /** originalRunLSID - LSID of run in KAR */
059                ORIGINAL_RUN_LSID("originalRunLSID"),
060                /** previewRunLSID - LSID of preview run in local reflection store*/
061                PREVIEW_RUN_LSID("previewRunLSID"),
062                /** karLSID - KAR attributes used to download the KAR */
063                KAR_LSID("karLSID"),
064                KAR_FILE_SIZE("karFileSize"),
065                KAR_FILE_NAME("karFileName"),
066                /** importedKARRunLSID - LSID of run after import from KAR into local reflection store. */
067                IMPORTED_KAR_RUN_LSID("importedKARRunLSID"), 
068                /** execId for the run in reflection store */
069                EXEC_ID("execId");
070                
071                /** Construct a new attribute. */
072                TrackerRunAttribute(String name) {
073                        _name = name;
074                }
075                
076                /** Get the name. */
077                public String toString() {
078                        return _name;
079                }
080                
081                /** check if attributeName is one specified in enum
082                 */
083                static public boolean isValid(String attributeName){
084                        for (TrackerRunAttribute ra: TrackerRunAttribute.values()){
085                                if (ra.toString().equals(attributeName)){
086                                        return true;
087                                }
088                        }
089                        return false;
090                }
091
092                /** The name of the attribute. */
093                private String _name;
094        }
095        
096        private String _remoteKarStoreName = null;
097        private ConfigurationProperty _repositoryCP = null;
098        
099        
100        /**
101         * Constructor.
102         * @param ecoGridRepoName
103         */
104        public RemoteStoreRunsTracker(String ecoGridRepoName){
105                //System.out.println("RemoteStoreRunsTracker("+ecoGridRepoName+")");
106                _remoteKarStoreName = ecoGridRepoName;
107                
108                ConfigurationManager configurationManager = ConfigurationManager.getInstance();
109                ConfigurationProperty repositoriesCP = configurationManager.
110                        getProperty(_provenanceModule, _configurationNamespace, REPOSITORIES);
111
112                List<ConfigurationProperty>repositoryCPs = repositoriesCP.getProperties(REPOSITORY);
113                for (ConfigurationProperty repositoryCP : repositoryCPs){
114                        ConfigurationProperty repositoryNameCP = repositoryCP.getProperty(NAME);
115                        if (repositoryNameCP.getValue().equals(_remoteKarStoreName)){
116                                _repositoryCP = repositoryCP;
117                        }
118                }
119                if (_repositoryCP == null){
120                        _repositoryCP = new ConfigurationProperty(_provenanceModule, "repository");
121                        _repositoryCP.setNamespace(_configurationNamespace);
122                        ConfigurationProperty repositoryCPNameChild = new ConfigurationProperty(_provenanceModule, "name",ecoGridRepoName);
123                        repositoryCPNameChild.setNamespace(_configurationNamespace);
124                        try {
125                                _repositoryCP.addProperty(repositoryCPNameChild);
126                                repositoriesCP.addProperty(_repositoryCP);
127                        } catch (NamespaceException e) {
128                                // TODO Auto-generated catch block
129                                System.out.println("******* ERROR trying to create missing repository config prop here for repo:"+_remoteKarStoreName);
130                                e.printStackTrace();
131                        } catch (ConfigurationManagerException e) {
132                                // TODO Auto-generated catch block
133                                System.out.println("******* ERROR trying to create missing repository config prop here for repo:"+_remoteKarStoreName);
134                                e.printStackTrace();
135                        }
136                }
137        }
138        
139        /** 
140         * @param lsidStr
141         * @return KeplerLSID or null
142         */
143        private KeplerLSID createLSID(String lsidStr){
144                if (lsidStr != null){
145                        try {
146                                KeplerLSID lsid = new KeplerLSID(lsidStr);
147                                return lsid;
148                        } catch (Exception e) {
149                                e.printStackTrace();
150                                return null;
151                        }
152                }
153                return null;
154        }
155        
156        /**
157         * Delete a run property from tracker file.
158         * @param run's original, preview, or imported lsid, or execId.
159         * @return true if run property was removed
160         */
161        public boolean deleteRunProperty(String lookup){
162                ConfigurationProperty cp = getRunChildProperty(lookup, TrackerRunAttribute.ORIGINAL_RUN_LSID);
163                ConfigurationProperty runProperty = cp.getParent();
164                ConfigurationProperty runParentProp = runProperty.getParent();
165                boolean removed = runParentProp.removeProperty(runProperty);
166                //runParentProp.prettyPrint();
167                return removed;
168        }
169        
170        /**
171         * @param run's original, preview, or imported lsid, or execId.
172         * @param trackerRunAttribute
173         * @return String property value, or null.
174         */
175        private String getRunChildPropertyValue(String lookup, 
176                        TrackerRunAttribute trackerRunAttribute){
177                ConfigurationProperty cp = getRunChildProperty(lookup, trackerRunAttribute);
178                if (cp != null){
179                        return cp.getValue();
180                }
181                return null;
182        }
183        
184        /**
185         * Return a child ConfigurationProperty of a specific run in tracker file, null if
186         * error or not found.
187         * Run is identified using run's original, preview, or imported LSID; or execId.
188         * An attempt to identify run by KAR LSID is NOT made, as this is currently unnecessary
189         * and in the future a KAR might hold more than one run.
190         * @param run's original, preview, or imported LSID, or execId.
191         * @param trackerRunAttribute
192         * @return ConfigurationProperty or null
193         */
194        private ConfigurationProperty getRunChildProperty(String lookup, 
195                        TrackerRunAttribute trackerRunAttribute){
196                
197                if (lookup == null){
198                        System.out.println("ERROR RemoteStoreRunsTracker getRunProperty lookup is null");
199                        return null;
200                }
201                
202                Iterator<ConfigurationProperty>itr = _repositoryCP.getProperties(RUN).iterator();
203                while (itr.hasNext()){
204                        ConfigurationProperty runCP = itr.next();
205                        
206                        ConfigurationProperty originalLSIDCP = 
207                                runCP.getProperty(TrackerRunAttribute.ORIGINAL_RUN_LSID.toString());
208                        if (originalLSIDCP != null && originalLSIDCP.getValue() != null){
209                                if (originalLSIDCP.getValue().equals(lookup)){
210                                        ConfigurationProperty cp = runCP.getProperty(trackerRunAttribute.toString());
211                                        return cp;
212                                }
213                        }
214                        
215                        ConfigurationProperty previewLSIDCP = 
216                                runCP.getProperty(TrackerRunAttribute.PREVIEW_RUN_LSID.toString());
217                        if (previewLSIDCP != null && previewLSIDCP.getValue() != null){
218                                if (previewLSIDCP.getValue().equals(lookup)){
219                                        ConfigurationProperty cp = runCP.getProperty(trackerRunAttribute.toString());
220                                        return cp;
221                                }
222                        }
223                        
224                        ConfigurationProperty importedKARRunLSIDCP = 
225                                runCP.getProperty(TrackerRunAttribute.IMPORTED_KAR_RUN_LSID.toString());
226                        if (importedKARRunLSIDCP != null && importedKARRunLSIDCP.getValue() != null){
227                                if (importedKARRunLSIDCP.getValue().equals(lookup)){
228                                        ConfigurationProperty cp = runCP.getProperty(trackerRunAttribute.toString());
229                                        return cp;
230                                }
231                        }
232                        
233                        ConfigurationProperty execIdCP = 
234                                runCP.getProperty(TrackerRunAttribute.EXEC_ID.toString());
235                        if (execIdCP != null && execIdCP.getValue() != null){
236                                if (execIdCP.getValue().equals(lookup)){
237                                        ConfigurationProperty cp = runCP.getProperty(trackerRunAttribute.toString());
238                                        return cp;
239                                }
240                        }
241                        
242                }
243                
244                return null;
245        }
246        
247        /**
248         * From the tracker file, get all original
249         * WorkflowRun LSIDs.
250         * @return
251         */
252        public List<KeplerLSID> getOriginalRunLSIDs(){
253                List<KeplerLSID> originalRunLSIDs = new ArrayList<KeplerLSID>();
254                
255                Iterator<ConfigurationProperty>itr = _repositoryCP.getProperties(RUN).iterator();
256                while (itr.hasNext()){
257                        ConfigurationProperty runCP = itr.next();
258                        ConfigurationProperty originalLSIDCP = 
259                                runCP.getProperty(TrackerRunAttribute.ORIGINAL_RUN_LSID.toString());
260                        if (originalLSIDCP != null && originalLSIDCP.getValue() != null){
261                                KeplerLSID lsid = createLSID(originalLSIDCP.getValue());
262                                if (lsid != null){
263                                        originalRunLSIDs.add(lsid);
264                                }
265                        }
266                }
267                return originalRunLSIDs;
268        }
269        
270        /**
271         * From the tracker file, get the original LSID of 
272         * the WorkflowRun in the KAR.
273         * @param run's original, preview, or imported run LSID, or execId.
274         * @return KeplerLSID or null
275         */
276        public KeplerLSID getOriginalRunLSID(String lookup){
277                                String lsidStr = getRunChildPropertyValue(lookup, 
278                                TrackerRunAttribute.ORIGINAL_RUN_LSID);
279                return createLSID(lsidStr);
280        }
281        
282        /**
283         * From the tracker file, get the LSID of the WorkflowRun 
284         * post KAR-import.
285         * @param run's original, preview, or imported LSID, or execId.
286         * @return KeplerLSID or null
287         */
288        public KeplerLSID getImportedKARRunLSID(String lookup){
289                String lsidStr = getRunChildPropertyValue(lookup, 
290                                TrackerRunAttribute.IMPORTED_KAR_RUN_LSID);
291                return createLSID(lsidStr);
292        }
293        
294        /**
295         * From the tracker file, get the KAR file name for a run.
296         * @param run's original, preview, or imported LSID, or execId.
297         * @return String filename or null
298         */
299        public String getKARFileName(String lookup){
300                String filename = getRunChildPropertyValue(lookup, 
301                                TrackerRunAttribute.KAR_FILE_NAME);
302                return filename;
303        }
304        
305        /**
306         * From the tracker file, get the KAR file size for a run.
307         * @param run's original, preview, or imported run lsid, or execId.
308         * @return Long fileSize
309         */
310        public Long getKARFileSize(String lookup){
311                String fileSizeStr = getRunChildPropertyValue(lookup, 
312                                TrackerRunAttribute.KAR_FILE_SIZE);
313                Long fileSize = new Long(fileSizeStr);
314                return fileSize;
315        }
316        
317        /**
318         * From the tracker file, get the KAR LSID for a run.
319         * @param run's original, preview, or imported LSID, or execId.
320         * @return KeplerLSID or null
321         */
322        public KeplerLSID getKARLSID(String lookup){
323                String karLSID = getRunChildPropertyValue(lookup, 
324                                TrackerRunAttribute.KAR_LSID);
325                return createLSID(karLSID);
326        }
327        
328        /**
329         * From the tracker file, get the LSID of the preview WorkflowRun 
330         * (the WorkflowRun that was downloaded, modified, and imported 
331         * into the local reflection store).
332         * @param run's original, preview, or imported LSID, or execId.
333         * @return KeplerLSID or null
334         */     
335        public KeplerLSID getPreviewRunLSID(String lookup){
336                String lsidStr = getRunChildPropertyValue(lookup, 
337                                TrackerRunAttribute.PREVIEW_RUN_LSID);
338                return createLSID(lsidStr);
339        }
340        
341        /**
342         * Check the tracker file to see if KAR was imported.
343         * @param run's original, preview, or imported LSID, or execId.
344         * @return boolean
345         */
346        public boolean isKARImported(String lookup){
347                if (getImportedKARRunLSID(lookup) != null){
348                        return true;
349                }
350                return false;
351        }
352        
353        public boolean setOriginalRunLSID(KeplerLSID lookupLSID, KeplerLSID originalRunLSID, boolean serialize){
354                return setRunProperty(lookupLSID.toString(), TrackerRunAttribute.ORIGINAL_RUN_LSID, 
355                                originalRunLSID.toString(), serialize);
356        }
357        
358        public boolean setPreviewRunLSID(KeplerLSID lookupLSID, KeplerLSID lsid, boolean serialize){
359                return setRunProperty(lookupLSID.toString(), TrackerRunAttribute.PREVIEW_RUN_LSID, 
360                                lsid.toString(), serialize);
361        }
362        
363        /**
364         * Set importedKARRunLSID. Only set this once KAR successfully imported into
365         * store.
366         * @see isKARImported
367         * @param lookup
368         * @param lsid
369         * @param serialize - immediately write change to file
370         * @return
371         */
372        public boolean setImportedKARRunLSID(String lookup, KeplerLSID lsid, boolean serialize){
373                return setRunProperty(lookup, TrackerRunAttribute.IMPORTED_KAR_RUN_LSID, 
374                                lsid.toString(), serialize);
375        }
376        
377        public boolean setKARFileName(String lookup, String karFileName, boolean serialize){
378                return setRunProperty(lookup, TrackerRunAttribute.KAR_FILE_NAME, 
379                                karFileName, serialize);
380        }
381        
382        public boolean setKARFileSize(String lookup, Long karFileSize, boolean serialize){
383                return setRunProperty(lookup, TrackerRunAttribute.KAR_FILE_SIZE, 
384                                karFileSize.toString(), serialize);
385        }
386        
387        public boolean setKARLSID(String lookup, KeplerLSID lsid, boolean serialize){
388                return setRunProperty(lookup, TrackerRunAttribute.KAR_LSID, 
389                                lsid.toString(), serialize);
390        }
391        
392        public boolean setExecId(KeplerLSID lookupLSID, Integer execId, boolean serialize) {
393                return setRunProperty(lookupLSID.toString(), TrackerRunAttribute.EXEC_ID, 
394                                execId.toString(), serialize);
395        }
396        
397        /**
398         * Attempt to set trackerRunAttribute for a specific run to propertyValue.
399         * If run is not found using lookup string, return false, unless trackerRunAttribute
400         * is ORIGINAL_RUN_LSID, in which case create a new run ConfigurationProperty.
401         * @param lsid
402         * @param trackerRunAttribute
403         * @param propertyValue
404         * @param serialize - immediately write change to file
405         * @return
406         */
407        private boolean setRunProperty(String lookup, 
408                        TrackerRunAttribute trackerRunAttribute, String propertyValue, boolean serialize){
409
410                ConfigurationProperty runChildProperty = getRunChildProperty(lookup, trackerRunAttribute);
411
412                try {
413                        if (runChildProperty != null){
414                                //System.out.println("WARN! - RemoteStoreRunsTracker resetting existing prop value. old:");
415                                //runChildProperty.prettyPrint();
416                                runChildProperty.setValue(propertyValue);
417                                //System.out.println("WARN! - RemoteStoreRunsTracker resetting existing prop value. new:");
418                                //runChildProperty.prettyPrint();
419                                return true;
420                        }
421                        else{
422                                ConfigurationProperty cp = new ConfigurationProperty(_provenanceModule, 
423                                                trackerRunAttribute.toString(), _configurationNamespace, propertyValue);
424
425                                ConfigurationProperty runCP = null;
426                                // create new run CP if trackerRunAttribute is ORIGINAL_RUN_LSID 
427                                if (trackerRunAttribute.toString().equals(TrackerRunAttribute.ORIGINAL_RUN_LSID.toString())){
428                                        List<ConfigurationProperty>cps = new ArrayList<ConfigurationProperty>();
429                                        cps.add(cp);
430                                        runCP = new ConfigurationProperty(_provenanceModule, RUN, 
431                                                        _configurationNamespace, cps, serialize);
432                                        _repositoryCP.addProperty(runCP, serialize);
433                                }
434                                else{
435                                        //find and add child to existing run CP, or fail.
436                                        ConfigurationProperty existingRunCPChild = getRunChildProperty(lookup, 
437                                                        TrackerRunAttribute.ORIGINAL_RUN_LSID);
438                                        if (existingRunCPChild == null){
439                                                existingRunCPChild = getRunChildProperty(lookup, TrackerRunAttribute.PREVIEW_RUN_LSID);
440                                        }
441                                        if (existingRunCPChild == null){
442                                                existingRunCPChild = getRunChildProperty(lookup, TrackerRunAttribute.IMPORTED_KAR_RUN_LSID);
443                                        }
444                                        if (existingRunCPChild == null){
445                                                existingRunCPChild = getRunChildProperty(lookup, TrackerRunAttribute.EXEC_ID);
446                                        }
447                                        if (existingRunCPChild == null){
448                                                System.out.println("ERROR cannot add "+trackerRunAttribute.toString() + 
449                                                                " with value:"+propertyValue + " because lookup failed for:"+lookup);
450                                                return false;
451                                        }
452                                        runCP = existingRunCPChild.getParent();
453                                        runCP.addProperty(cp, serialize);
454                                }
455
456                                return true;
457                        }
458                } catch (NamespaceException e) {
459                        // TODO Auto-generated catch block
460                        e.printStackTrace();
461                } catch (ConfigurationManagerException e) {
462                        // TODO Auto-generated catch block
463                        e.printStackTrace();
464                }
465                
466                return false;
467        }
468
469        
470}