Coverage Report - org.apache.onami.scheduler.JobSchedulerBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
JobSchedulerBuilder
81%
36/44
83%
15/18
1.846
 
 1  
 package org.apache.onami.scheduler;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import static java.lang.String.format;
 23  
 import static java.util.TimeZone.getDefault;
 24  
 import static org.apache.onami.scheduler.Scheduled.DEFAULT;
 25  
 import static org.quartz.CronScheduleBuilder.cronSchedule;
 26  
 import static org.quartz.JobBuilder.newJob;
 27  
 import static org.quartz.JobKey.jobKey;
 28  
 import static org.quartz.TriggerBuilder.newTrigger;
 29  
 import static org.quartz.TriggerKey.triggerKey;
 30  
 import static org.quartz.utils.Key.DEFAULT_GROUP;
 31  
 
 32  
 import java.util.TimeZone;
 33  
 
 34  
 import javax.inject.Inject;
 35  
 
 36  
 import org.quartz.Job;
 37  
 import org.quartz.JobKey;
 38  
 import org.quartz.Scheduler;
 39  
 import org.quartz.Trigger;
 40  
 import org.quartz.TriggerKey;
 41  
 
 42  
 import com.google.inject.ProvisionException;
 43  
 
 44  
 /**
 45  
  * DSL to produce {@code Job} and add to a {@code Scheduler},
 46  
  * and associate the related {@code Trigger} with it.
 47  
  */
 48  
 public final class JobSchedulerBuilder {
 49  
 
 50  
     /**
 51  
      * The type of the {@code Job} to be executed.
 52  
      */
 53  
     private final Class<? extends Job> jobClass;
 54  
 
 55  
     /**
 56  
      * The {@code Job} name, must be unique within the group.
 57  
      */
 58  5
     private String jobName = DEFAULT;
 59  
 
 60  
     /**
 61  
      * The {@code Job} group name.
 62  
      */
 63  5
     private String jobGroup = DEFAULT_GROUP;
 64  
 
 65  
     /**
 66  
      * Instructs the {@code Scheduler} whether or not the {@code Job} should
 67  
      * be re-executed if a {@code recovery} or {@code fail-over} situation is
 68  
      * encountered.
 69  
      */
 70  5
     private boolean requestRecovery = false;
 71  
 
 72  
     /**
 73  
      * Whether or not the {@code Job} should remain stored after it is
 74  
      * orphaned (no {@code Trigger}s point to it).
 75  
      */
 76  5
     private boolean storeDurably = false;
 77  
 
 78  
     /**
 79  
      * The {@code Trigger} name, must be unique within the group.
 80  
      */
 81  5
     private String triggerName = DEFAULT;
 82  
 
 83  
     /**
 84  
      * The {@code Trigger} group.
 85  
      */
 86  5
     private String triggerGroup = DEFAULT_GROUP;
 87  
 
 88  
     /**
 89  
      * The cron expression to base the schedule on.
 90  
      */
 91  
     private String cronExpression;
 92  
 
 93  
     /**
 94  
      * The time zone for which the {@code cronExpression}
 95  
      * of this {@code CronTrigger} will be resolved.
 96  
      */
 97  5
     private TimeZone timeZone = getDefault();
 98  
 
 99  
     /**
 100  
      * The {@code Trigger}'s priority.  When more than one {@code Trigger} have the same
 101  
      * fire time, the scheduler will fire the one with the highest priority
 102  
      * first.
 103  
      */
 104  5
     private int priority = 0;
 105  
 
 106  
     /**
 107  
      * The {@code Trigger} to be used to schedule the {@code Job}
 108  
      *
 109  
      * @since 1.2
 110  
      */
 111  
     private Trigger trigger;
 112  
 
 113  
     /**
 114  
      * Indicates whether the job's trigger should be updated if it is already existing when being
 115  
      * scheduled (which is typically the case with a persistent {@link org.quartz.spi.JobStore}.
 116  
      *
 117  
      * @since 1.3
 118  
      */
 119  5
     private boolean updateExistingTrigger = false;
 120  
 
 121  
     /**
 122  
      * Creates a new {@code JobSchedulerBuilder} instance.
 123  
      *
 124  
      * This class can't be instantiated by users.
 125  
      *
 126  
      * @param jobClass The type of the {@code Job} to be executed
 127  
      */
 128  
     JobSchedulerBuilder( final Class<? extends Job> jobClass )
 129  5
     {
 130  5
         this.jobClass = jobClass;
 131  5
     }
 132  
 
 133  
     /**
 134  
      * Sets the {@code Job} name, must be unique within the group.
 135  
      *
 136  
      * @param jobName The {@code Job} name, must be unique within the group
 137  
      * @return This builder instance
 138  
      */
 139  
     public JobSchedulerBuilder withJobName( String jobName )
 140  
     {
 141  4
         this.jobName = jobName;
 142  4
         return this;
 143  
     }
 144  
 
 145  
     /**
 146  
      * Sets the {@code Job} group.
 147  
      *
 148  
      * @param jobGroup The {@code Job} group
 149  
      * @return This builder instance
 150  
      */
 151  
     public JobSchedulerBuilder withJobGroup( String jobGroup )
 152  
     {
 153  4
         this.jobGroup = jobGroup;
 154  4
         return this;
 155  
     }
 156  
 
 157  
     /**
 158  
      * Instructs the {@code Scheduler} whether or not the {@code Job} should
 159  
      * be re-executed if a {@code recovery} or {@code fail-over} situation is
 160  
      * encountered.
 161  
      *
 162  
      * @param requestRecovery The activation flag
 163  
      * @return This builder instance
 164  
      */
 165  
     public JobSchedulerBuilder withRequestRecovery( boolean requestRecovery )
 166  
     {
 167  4
         this.requestRecovery = requestRecovery;
 168  4
         return this;
 169  
     }
 170  
 
 171  
     /**
 172  
      * Whether or not the {@code Job} should remain stored after it is
 173  
      * orphaned (no {@code Trigger}s point to it).
 174  
      *
 175  
      * @param storeDurably The activation flag
 176  
      * @return This builder instance
 177  
      */
 178  
     public JobSchedulerBuilder withStoreDurably( boolean storeDurably )
 179  
     {
 180  4
         this.storeDurably = storeDurably;
 181  4
         return this;
 182  
     }
 183  
 
 184  
     /**
 185  
      * Sets the {@code Trigger} name, must be unique within the group.
 186  
      *
 187  
      * @param triggerName The {@code Trigger} name, must be unique within the group
 188  
      * @return This builder instance
 189  
      */
 190  
     public JobSchedulerBuilder withTriggerName( String triggerName )
 191  
     {
 192  4
         this.triggerName = triggerName;
 193  4
         return this;
 194  
     }
 195  
 
 196  
     /**
 197  
      * Sets the {@code Trigger} group.
 198  
      *
 199  
      * @param triggerGroup The {@code Trigger} group
 200  
      * @return This builder instance
 201  
      */
 202  
     public JobSchedulerBuilder withTriggerGroup( String triggerGroup )
 203  
     {
 204  0
         this.triggerGroup = triggerGroup;
 205  0
         return this;
 206  
     }
 207  
 
 208  
     /**
 209  
      * Sets the cron expression to base the schedule on.
 210  
      *
 211  
      * @param cronExpression The cron expression to base the schedule on
 212  
      * @return This builder instance
 213  
      */
 214  
     public JobSchedulerBuilder withCronExpression( String cronExpression )
 215  
     {
 216  4
         this.cronExpression = cronExpression;
 217  4
         return this;
 218  
     }
 219  
 
 220  
     /**
 221  
      * Sets the time zone for which the {@code cronExpression} of this
 222  
      * {@code CronTrigger} will be resolved.
 223  
      *
 224  
      * @param timeZone The time zone for which the {@code cronExpression}
 225  
      *        of this {@code CronTrigger} will be resolved.
 226  
      * @return This builder instance
 227  
      */
 228  
     public JobSchedulerBuilder withTimeZone( TimeZone timeZone )
 229  
     {
 230  0
         this.timeZone = timeZone;
 231  0
         return this;
 232  
     }
 233  
 
 234  
     /**
 235  
      * Sets the {@code Trigger}'s priority.  When more than one {@code Trigger} have the same
 236  
      * fire time, the scheduler will fire the one with the highest priority
 237  
      * first.
 238  
      *
 239  
      * @param priority The {@code Trigger}'s priority
 240  
      * @return This builder instance
 241  
      */
 242  
     public JobSchedulerBuilder withPriority( int priority )
 243  
     {
 244  0
         this.priority = priority;
 245  0
         return this;
 246  
     }
 247  
 
 248  
     /**
 249  
      * Sets the {@code Trigger} that will be used to schedule
 250  
      * the {@code Job}.
 251  
      *
 252  
      * <p>
 253  
      * Be aware that using using this method will override any other
 254  
      * {@code Trigger}-related operation, like {@link #withTriggerGroup(String)}
 255  
      * or {@link #withTimeZone(TimeZone)}
 256  
      *
 257  
      * @param trigger The {@code Trigger} to associate with the {@code Job}
 258  
      * @return This builder instance
 259  
      * @since 1.2
 260  
      */
 261  
     public JobSchedulerBuilder withTrigger(Trigger trigger)
 262  
     {
 263  1
         this.trigger = trigger;
 264  1
         return this;
 265  
     }
 266  
 
 267  
     /**
 268  
      * Requests an existing trigger (sharing the same key as the new trigger) for this job to
 269  
      * be replaced with the new trigger.
 270  
      *
 271  
      * @return This builder instance
 272  
      * @since 1.3
 273  
      */
 274  
     public JobSchedulerBuilder updateExistingTrigger()
 275  
     {
 276  2
         this.updateExistingTrigger = true;
 277  2
         return this;
 278  
     }
 279  
 
 280  
     /**
 281  
      * Add the produced {@code Job} to the given {@code Scheduler},
 282  
      * and associate the related {@code Trigger} with it.
 283  
      *
 284  
      * Users <b>MUST NOT</b> use this method!
 285  
      *
 286  
      * @param scheduler The given {@code Scheduler}
 287  
      * @throws Exception If any error occurs
 288  
      */
 289  
     @Inject
 290  
     public void schedule( Scheduler scheduler )
 291  
         throws Exception
 292  
     {
 293  5
         if ( cronExpression == null && trigger == null )
 294  
         {
 295  0
             throw new ProvisionException( format( "Impossible to schedule Job '%s' without cron expression",
 296  
                                                   jobClass.getName() ) );
 297  
         }
 298  5
         if ( cronExpression != null && trigger != null )
 299  
         {
 300  0
           throw new ProvisionException( format( "Impossible to schedule Job '%s' with cron expression " +
 301  
                                                 "and an associated Trigger at the same time", jobClass.getName() ) );
 302  
         }
 303  
 
 304  5
         JobKey jobKey = jobKey( DEFAULT.equals( jobName ) ? jobClass.getName() : jobName, jobGroup );
 305  5
         TriggerKey triggerKey = triggerKey( DEFAULT.equals( triggerName ) ? jobClass.getCanonicalName() : triggerName, triggerGroup );
 306  
 
 307  5
         if ( updateExistingTrigger && scheduler.checkExists( triggerKey ) ) {
 308  1
             scheduler.unscheduleJob( triggerKey );
 309  
         }
 310  
 
 311  5
         scheduler.scheduleJob( newJob( jobClass )
 312  
                                .withIdentity( jobKey )
 313  
                                .requestRecovery( requestRecovery )
 314  
                                .storeDurably( storeDurably ).build(),
 315  
                                ( trigger == null ) ?
 316  
                                newTrigger()
 317  
                                .withIdentity( triggerKey )
 318  
                                .withSchedule( cronSchedule( cronExpression )
 319  
                                               .inTimeZone( timeZone ) )
 320  
                                               .withPriority( priority )
 321  
                                               .build()
 322  
                                 : trigger);
 323  5
     }
 324  
 
 325  
 }