001/**
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: tao $'
006 * '$Date: 2010-06-03 16:45:10 -0700 (Thu, 03 Jun 2010) $' 
007 * '$Revision: 24730 $'
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 */
029package org.kepler.workflowscheduler.gui;
030
031
032import java.text.ParseException;
033import java.text.SimpleDateFormat;
034import java.util.Calendar;
035import java.util.Date;
036import java.util.Stack;
037import java.util.TimeZone;
038import java.util.Vector;
039
040import org.apache.commons.logging.Log;
041import org.apache.commons.logging.LogFactory;
042import org.kepler.objectmanager.repository.EcogridRepository;
043import org.kepler.objectmanager.repository.Repository;
044import org.kepler.objectmanager.repository.RepositoryManager;
045import org.xml.sax.Attributes;
046import org.xml.sax.SAXException;
047import org.xml.sax.helpers.DefaultHandler;
048
049
050
051
052/**
053 * A parser which parses the result xml from remote scheduler server to
054 * get existing schedules information
055 * @author tao
056 *
057 */
058public class QueryingSchedulerServerResultParser extends DefaultHandler 
059{
060  private static final Log log = LogFactory.getLog(QueryingSchedulerServerResultParser.class.getName());
061  
062  private static final String SCHEDULEDWORKFLOWRESULTSET = "scheduledWorkflowResultset";
063  private static final String SCHEDULEDJOB = "scheduledJob";
064  private static final String STATUS = "status";
065  private static final String NAME = "name";
066  private static final String SCHEDULED = "scheduled";
067  private static final String UNSCHEDULED = "unscheduled";
068  private static final String DELETED = "deleted";
069  private static final String STARTTIME = "startTimeInSpecifiedZone";
070  private static final String ENDTIME = "endTimeInSpecifiedZone";
071  private static final String INTERVALVALUE = "intervalValue";
072  private static final String INTERVALUNIT = "intervalUnit";
073  private static final String JOBPARAM = "jobParam";
074  private static final String DESTINATIONREPOSITORYNAME = "destinationRepositoryName";
075  private static final String WORKFLOWRUNENGINENAME = "workflowRunEngineName";
076  private static final String WORKFLOWNAME = "workflowname";
077  private static final String WORKFLOWID = "workflowid";
078  private static final String KARID = "karid";
079  private static final String KEY = "key";
080  private static final String VALUE = "value";
081  private static final String STARTTIMEFORMAT = "startTimeFormat";
082  private static final String STARTTIMEZONE = "startTimeZoneID";
083  private static final String ENDTIMEFORMAT = "endTimeFormat";
084  private static final String ENDTIMEZONE = "endTimeZoneID";
085 
086  private boolean processDestinationName = false;
087  private boolean findDestinationName = false;
088  private boolean processWorkflowRunEngineName = false;
089  private boolean findWorkflowRunEngineName = false;
090  private boolean processWorkflowName = false;
091  private boolean findWorkflowName = false;
092  private boolean processKarid = false;
093  private boolean findKarid = false;
094  private boolean processWorkflowId = false;
095  private boolean findWorkflowId = false;
096  
097  private StringBuffer textBuffer = null;
098  private String startTime = null;
099  private String startTimeFormat = null;
100  private String startTimeZoneID = null;
101  private String endTime = null;
102  private String endTimeFormat = null;
103  private String endTimeZoneID = null;
104  private String nodeValue = null;
105  //private String currentElementName = null;
106  private String parentElementName = null;
107  //private String status = null;
108  //private String startTime = null;
109  //private String endTime = null;
110  //private String interval = null;
111  //private String intervalUnit = null;
112  //private String workflowRunEngineName = null;
113  //private String workflowRunKarDestinationRepoName = null;
114  //private String workflowJobName = null;
115  //private String workflowId = null;
116  //private String workflowName = null;
117  //private String karId = null;
118  private Schedule currentSchedule = null;
119  private Vector<Schedule> schedulesVector = new Vector<Schedule>();
120  private Stack<String>elementNameStack = new Stack<String>();
121  
122  /**
123   * Constructor
124   */
125  public QueryingSchedulerServerResultParser()
126  {
127    
128  }
129  
130  /** SAX Handler that is called at the start of each XML element */
131  public void startElement(String uri, String localName, String qName,
132          Attributes atts) throws SAXException
133  {
134    if(!elementNameStack.isEmpty())
135    {
136      parentElementName = elementNameStack.peek();
137    }    
138    elementNameStack.addElement(localName);
139    if(localName != null && localName.equals(SCHEDULEDJOB))
140    {
141      currentSchedule = new Schedule();
142    }
143    else if(localName != null && localName.equals(JOBPARAM) && atts != null)
144    {
145      String name = atts.getValue(uri, NAME);
146      if(name != null && name.equals(DESTINATIONREPOSITORYNAME))
147      {
148        processDestinationName = true;
149      }
150      else if (name != null && name.equals(WORKFLOWRUNENGINENAME))
151      {
152        processWorkflowRunEngineName = true;
153      }
154      else if (name != null && name.equals(KARID))
155      {
156        processKarid = true;
157      }
158      else if (name != null && name.equals(WORKFLOWNAME))
159      {
160        processWorkflowName = true;
161      }
162      else if( name != null && name.equals(WORKFLOWID))
163      {
164        processWorkflowId = true;
165      }
166     
167        
168    }
169    else if(localName != null && processDestinationName && localName.equals(VALUE))
170    {
171      findDestinationName = true;
172    }
173    else if(localName != null && processWorkflowRunEngineName && localName.equals(VALUE))
174    {
175      findWorkflowRunEngineName = true;
176    }
177    else if(localName != null && processKarid && localName.equals(VALUE))
178    {
179      findKarid = true;
180    }
181    else if(localName != null && processWorkflowName && localName.equals(VALUE))
182    {
183      findWorkflowName = true;
184    }
185    else if (localName != null && processWorkflowId && localName.equals(VALUE))
186    {
187      findWorkflowId = true;
188    }
189
190    textBuffer = null;
191    textBuffer = new StringBuffer();
192  }
193  
194  /** SAX Handler that is called for each XML text node */
195  public void characters(char[] cbuf, int start, int len) throws SAXException
196  {
197    textBuffer.append(new String(cbuf, start, len));
198  }
199  
200  /** SAX Handler that is called at the end of each XML element */
201  public void endElement(String uri, String localName, String qName)
202          throws SAXException
203  {
204    elementNameStack.pop();
205    nodeValue = textBuffer.toString().trim();
206    //status
207    if(localName != null && localName.equals(STATUS) && 
208        currentSchedule != null && parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
209    {
210      if(nodeValue != null && nodeValue.equals(SCHEDULED))
211      {
212        currentSchedule.setEnabled(true);
213      }
214      else if(nodeValue != null && nodeValue.equals(UNSCHEDULED))
215      {
216        currentSchedule.setEnabled(false);
217      }
218      else
219      {
220        //set current schedule to null (not count this schedule)
221        currentSchedule = null;
222      }
223    }
224    else if(localName != null && localName.equals(NAME) && currentSchedule != null && 
225        parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
226    {
227      //scheduledJobName
228      currentSchedule.setWorkflowJobName(nodeValue);
229    }
230    else if(localName != null && localName.equals(STARTTIME) && currentSchedule != null && 
231        parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
232    {
233      //start time
234      startTime = nodeValue;
235      log.debug("The start time  is "+startTime);
236      //currentSchedule.setStartTime(nodeValue);
237    }
238    else if(localName != null && localName.equals(STARTTIMEFORMAT) && currentSchedule != null && 
239        parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
240    {
241      //start time zone
242      startTimeFormat = nodeValue;
243      log.debug("The start time format is "+startTimeFormat);
244      //currentSchedule.setStartTime(nodeValue);
245    }
246    else if(localName != null && localName.equals(STARTTIMEZONE) && currentSchedule != null && 
247        parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
248    {
249      //start time zone
250      startTimeZoneID = nodeValue;
251      log.debug("The start time zone is "+startTimeZoneID);
252      //currentSchedule.setStartTime(nodeValue);
253    }
254    else if(localName != null && localName.equals(ENDTIME) && currentSchedule != null && 
255        parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
256    {
257     //end time
258      endTime = nodeValue;
259      log.debug("End time is " +endTime);
260      //currentSchedule.setEndTime(nodeValue);
261    }
262    else if(localName != null && localName.equals(ENDTIMEFORMAT) && currentSchedule != null && 
263        parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
264    {
265      //start time zone
266      endTimeFormat = nodeValue;
267      log.debug("The end time format is "+endTimeFormat);
268      //currentSchedule.setStartTime(nodeValue);
269    }
270    else if(localName != null && localName.equals(ENDTIMEZONE) && currentSchedule != null && 
271        parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
272    {
273      //start time zone
274      endTimeZoneID = nodeValue;
275      log.debug("The end time zone is "+endTimeZoneID);
276      //currentSchedule.setStartTime(nodeValue);
277    }
278    else if(localName != null && localName.equals(INTERVALVALUE) && currentSchedule != null 
279        && parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
280    {
281      //interval value
282      try
283      {
284        currentSchedule.setInterval(nodeValue);
285      }
286      catch(NumberFormatException e)
287      {
288        log.error(e.getMessage());
289        //if it is not integer, set the current schedule to null (remove it)
290        currentSchedule = null;
291      }
292          
293    }
294    else if(localName != null && localName.equals(INTERVALUNIT) && currentSchedule != null 
295        && parentElementName != null && parentElementName.equals(SCHEDULEDJOB))
296    {
297      //interval unit
298      try
299      {
300        currentSchedule.setIntervalUnit(nodeValue);
301      }
302      catch(Exception e)
303      {
304        log.error(e.getMessage());
305        //if it is not integer, set the current schedule to null (remove it)
306        currentSchedule = null;
307      }
308          
309    }
310    else if(localName != null && localName.equals(SCHEDULEDJOB) && currentSchedule != null)
311    {
312      //currentSchedule.setKarLSID(karId);
313      //currentSchedule.setWorkflowId(workflowId);
314      //currentSchedule.setWorkflowName(workflowName);
315      /*if(startTime != null)
316      {
317        if(startTimeZoneID == null || startTimeZoneID.trim().equals(""))
318        {
319          currentSchedule.setStartTime(startTime);
320        }
321        else
322        {
323          currentSchedule.setStartTime(startTime+" "+startTimeZoneID);
324        }
325      }*/
326      if(startTime != null && !startTime.trim().equals(""))
327      {
328        currentSchedule.setStartTimeLabel(transformToLabel(startTime, startTimeFormat, startTimeZoneID));
329      }
330    
331      /*if(endTime != null)
332      {
333        if(endTimeZoneID == null || endTimeZoneID.trim().equals(""))
334        {
335          currentSchedule.setEndTime(endTime);
336        }
337        else
338        {
339          currentSchedule.setEndTime(endTime+" "+endTimeZone);
340        }
341      }*/
342      if(endTime != null && ! endTime.trim().equals(""))
343      {
344        currentSchedule.setEndTimeLabel(transformToLabel(endTime,endTimeFormat, endTimeZoneID));
345      }
346      
347      schedulesVector.add(currentSchedule);
348      currentSchedule = null;
349    }
350    
351    if(findDestinationName)
352    {
353      Repository repository = null;
354      try
355      {
356        repository = RepositoryManager.getInstance().getRepository(nodeValue);
357      }
358      catch(Exception e)
359      {
360        log.warn("Couldn't get repository from the name "+nodeValue+" - "+e.getMessage());
361      }
362      if(repository == null)
363      {
364        repository = new EcogridRepository(nodeValue, null, null,null, null, null, null, null,null, null, null, null);
365      }
366      currentSchedule.setWorkflowRunDestination(repository);
367      findDestinationName = false;
368      processDestinationName = false;
369    }
370    else if(findWorkflowRunEngineName)
371    {     
372      WorkflowRunEngine engine = new WorkflowRunEngine(nodeValue);
373      currentSchedule.setWorkflowRunEngine(engine);
374      findWorkflowRunEngineName = false;
375      processWorkflowRunEngineName = false;  
376    }
377    else if(findKarid)
378    {
379      currentSchedule.setKarLSID(nodeValue);
380      findKarid = false;
381      processKarid =false;
382    }
383    else if(findWorkflowName)
384    {
385      currentSchedule.setWorkflowName(nodeValue);
386      findWorkflowName = false;
387      processWorkflowName = false;
388    }
389    else if(findWorkflowId)
390    {
391      currentSchedule.setWorkflowId(nodeValue);
392      findWorkflowId = false;
393      processWorkflowId = false;
394    }
395    
396       
397    
398    textBuffer = null;
399    textBuffer = new StringBuffer();
400  }
401  
402  /**
403   * Get the schedules list in vector format
404   * @return a vector contains the schedules 
405   */
406  public Vector<Schedule> getSchedules()
407  {
408    return schedulesVector;
409  }
410
411 /*
412  * Transform the time from given time zone id to local time. First transform time string
413  * and given time id into a calendar object. Then transform the calendar object to a time string
414  * with the default time zone.
415  */
416  
417  private String transformToLabel(String timeString, String timeFormat, String timeZoneID)
418  {
419    String label = null;
420    if(timeZoneID == null || timeZoneID.trim().equals(""))
421    {
422      label = timeString;
423    }
424    else
425    {
426      if(timeFormat == null || timeFormat.trim().equals(""))
427      {
428        timeFormat = WorkflowSchedulerPanel.TIMESTAMPFORMAT;
429      }
430      SimpleDateFormat readDateFormatter = null;
431      try 
432      {
433        if(WorkflowSchedulerPanel.localContainsTimeZoneID(timeZoneID))
434        {
435          readDateFormatter = new SimpleDateFormat(timeFormat);
436          readDateFormatter.setLenient(false);
437          TimeZone zone = TimeZone.getTimeZone(timeZoneID);
438          //System.out.println("the time zone name from id is "+zone.getDisplayName());
439          readDateFormatter.setTimeZone(zone);
440          Date date = readDateFormatter.parse(timeString);
441          Calendar cal = Calendar.getInstance();
442          cal.setTime(date);
443          try 
444          {
445            //TimeZone currentZone = TimeZone.getDefault();
446            //boolean isDaylightTime = currentZone.inDaylightTime(date);
447            //format the date to the format we need
448            SimpleDateFormat displayFormat = new SimpleDateFormat(WorkflowSchedulerPanel.TIMESTAMPFORMATWITHTIMEZONE);
449            displayFormat.setLenient(false);
450            displayFormat.setTimeZone(zone);
451            label = displayFormat.format(cal.getTime());
452          } 
453          catch (IllegalArgumentException e) 
454          {
455            log.warn("QueryingSchedulerServerResultParser.transformToLabel - the time format - " +WorkflowSchedulerPanel.TIMESTAMPFORMATWITHTIMEZONE+ "  is not a legitimate format: " + e.getMessage());
456            label = timeString +" "+timeZoneID;
457            
458          }
459        }
460        else
461        {
462          label = timeString +" "+timeZoneID;
463        }
464       
465      } 
466      catch (IllegalArgumentException e) 
467      {
468        log.warn("QueryingSchedulerServerResultParser.transformToLabel - the time format - " +timeFormat+ " from the scheduler server is not a legitimate format: " + e.getMessage());
469        label = timeString +" "+timeZoneID;
470        return label;
471      }
472      catch(ParseException e)
473      {
474        log.warn("QueryingSchedulerServerResultParser.transformToLabel - couldn't parse the string - "+timeString+" with the format " +timeFormat+" : " + e.getMessage());
475        label = timeString +" "+timeZoneID;
476      }
477      
478     
479    }
480    //System.out.println("The new time string is "+newTime);
481    return label;
482  }
483}