View Javadoc

1   /* 
2    * Copyright (c) 2007, Fraunhofer-Gesellschaft
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are
7    * met:
8    * 
9    * (1) Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the disclaimer at the end.
11   *     Redistributions in binary form must reproduce the above copyright
12   *     notice, this list of conditions and the following disclaimer in
13   *     the documentation and/or other materials provided with the
14   *     distribution.
15   * 
16   * (2) Neither the name of Fraunhofer nor the names of its
17   *     contributors may be used to endorse or promote products derived
18   *     from this software without specific prior written permission.
19   * 
20   * DISCLAIMER
21   * 
22   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *  
34   */
35  package org.ogf.graap.wsag.it.samples.negotiation;
36  
37  import java.util.Calendar;
38  import java.util.GregorianCalendar;
39  
40  import org.apache.log4j.Logger;
41  import org.apache.xmlbeans.XmlDateTime;
42  import org.ggf.schemas.jsdl.x2005.x11.jsdl.JobDefinitionDocument;
43  import org.ggf.schemas.jsdl.x2005.x11.jsdl.RangeValueType;
44  import org.ggf.schemas.jsdl.x2005.x11.jsdl.ResourcesType;
45  import org.ogf.graap.wsag.api.AgreementOffer;
46  import org.ogf.graap.wsag.api.exceptions.NegotiationException;
47  import org.ogf.graap.wsag.api.exceptions.NegotiationFactoryException;
48  import org.ogf.graap.wsag.api.exceptions.ResourceUnavailableException;
49  import org.ogf.graap.wsag.api.exceptions.ResourceUnknownException;
50  import org.ogf.graap.wsag.api.types.AgreementOfferType;
51  import org.ogf.graap.wsag.client.api.AgreementClient;
52  import org.ogf.graap.wsag.client.api.AgreementFactoryClient;
53  import org.ogf.graap.wsag.client.api.NegotiationClient;
54  import org.ogf.graap.wsag.it.AbstractIntegrationTest;
55  import org.ogf.graap.wsag.samples.actions.SampleAgreementTemplate;
56  import org.ogf.graap.wsag.samples.actions.SampleNegotiationOffer;
57  import org.ogf.graap.wsag4j.types.scheduling.TimeConstraintDocument;
58  import org.ogf.graap.wsag4j.types.scheduling.TimeConstraintType;
59  import org.ogf.schemas.graap.wsAgreement.AgreementTemplateType;
60  import org.ogf.schemas.graap.wsAgreement.OfferItemType.ItemConstraint;
61  import org.ogf.schemas.graap.wsAgreement.ServiceDescriptionTermType;
62  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationConstraintSectionType;
63  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationContextDocument;
64  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationContextType;
65  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationOfferContextType;
66  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationOfferItemType;
67  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationOfferStateType;
68  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationOfferType;
69  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationRoleType;
70  import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationType;
71  
72  /**
73   * Sample Negotiator to demonstrate the Agreement Negotiation.
74   * 
75   * @author hrasheed
76   * 
77   */
78  public class AbstractSampleNegotiatorTest extends AbstractIntegrationTest
79  {
80  
81      /**
82       * 
83       */
84      private static final int DURATION = 15;
85  
86      /**
87       * 
88       */
89      private static final int STARTTIME_OFFSET = 10;
90  
91      /**
92       * 
93       */
94      private static final int ENDTIME_OFFSET = 20;
95  
96      private static final Logger LOG = Logger.getLogger( AbstractSampleNegotiatorTest.class );
97  
98      private static final String FACTORY_RESOURCE_ID = "SAMPLE-INSTANCE-1";
99  
100     private static final String TEMPLATE_NAME = "SAMPLE-TEMPLATE";
101 
102     private static final String RESOURCES_SDT_NAME = "RESOURCE_SDT";
103 
104     private static final String TIME_CONSTRAINT_SDT_NAME = "TIME_CONSTRAINT_SDT";
105 
106     private static final int END_TIME_OFFSET = 45;
107 
108     /**
109      * 
110      * @param name
111      *            the test case name
112      */
113     public AbstractSampleNegotiatorTest( String name )
114     {
115         super( name );
116     }
117 
118     /**
119      * Tests the negotiation of offers and counter offers.
120      * 
121      * @throws Exception
122      *             indicates an error in the test case
123      */
124     public void testSampleNegotiator() throws Exception
125     {
126 
127         //
128         // initiate the negotiation instance
129         //
130         NegotiationClient negotiation = initiateNegotiation();
131 
132         try
133         {
134             //
135             // retrieve the negotiable template
136             //
137             SampleAgreementTemplate negotiationTemplate = getNegotiableTemplate( negotiation );
138 
139             /******************************************************************
140              * First round of the Negotiation
141              ******************************************************************/
142             //
143             // This template includes the service description term 'RESOURCE_SDT' with a JSDL document
144             // describing the available compute resources.
145             //
146             // NegotiationOffer_1: 05 resources for 15 minutes duration with a time frame as
147             // startTime = current, endTime = startTime + 60
148             //
149             //
150             NegotiationOfferType counterOffer1 = negotiateRound1( negotiation, negotiationTemplate );
151 
152             /******************************************************************
153              * Second round of the Negotiation
154              ******************************************************************/
155             //
156             // we receive 2 counter offers with different resource availability as
157             //
158             // CounterOffer_1: 05 resources for 20 minutes duration with a time fame as
159             // startTime = current + 5, endTime = startTime + 20
160             //
161             // CounterOffer_2: 05 resources for 15 minutes duration with a time fame as
162             // startTime = current + 10, endTime = startTime + 30
163             //
164             // Say that both counter offers are not sufficient with respect to time,
165             // we create another negotiation offer with
166             //
167             // NegotiationOffer_2: 05 resources for 15 minutes duration with a time frame as
168             // startTime = current + 10, endTime = startTime + 20
169             //
170             NegotiationOfferType selectedCounterOffer = negotiateRound2( negotiation, counterOffer1 );
171 
172             //
173             // create agreement if negotiated offer satisfy the requirements
174             //
175             AgreementOffer offer = new AgreementOfferType( selectedCounterOffer );
176             AgreementClient agreement =
177                 getAgreementFactoryClient( FACTORY_RESOURCE_ID ).createAgreement( offer );
178             assertNotNull( agreement );
179             LOG.info( "negotiated agreement successfully created" );
180 
181             //
182             // finally terminate the negotiation process
183             //
184             LOG.info( "terminating negotiated agreement" );
185             negotiation.terminate();
186 
187         }
188         catch ( NegotiationException e )
189         {
190             fail( "NegotiationException: " + e.getMessage() );
191         }
192         catch ( ResourceUnavailableException e )
193         {
194             fail( "ResourceUnavailableException: " + e.getMessage() );
195         }
196         catch ( ResourceUnknownException e )
197         {
198             fail( "ResourceUnknownException: " + e.getMessage() );
199         }
200         catch ( Exception e )
201         {
202             e.printStackTrace();
203             fail( "sample-negotiator fails. Error: " + e.getMessage() );
204         }
205     }
206 
207     /**
208      * @param negotiation
209      * @param counterOffer1
210      * @return
211      * @throws Exception
212      * @throws NegotiationException
213      * @throws ResourceUnknownException
214      * @throws ResourceUnavailableException
215      */
216     private NegotiationOfferType negotiateRound2( NegotiationClient negotiation,
217                                                   NegotiationOfferType counterOffer1 ) throws Exception
218     {
219         /******************************************************************
220          * Second round of the Negotiation
221          ******************************************************************/
222         //
223         // we receive 2 counter offers with different resource availability as
224         //
225         // CounterOffer_1: 05 resources for 20 minutes duration with a time fame as
226         // startTime = current + 5, endTime = startTime + 20
227         //
228         // CounterOffer_2: 05 resources for 15 minutes duration with a time fame as
229         // startTime = current + 10, endTime = startTime + 30
230         //
231         // Say that both counter offers are not sufficient with respect to time,
232         // we create another negotiation offer with
233         //
234         // NegotiationOffer_2: 05 resources for 15 minutes duration with a time frame as
235         // startTime = current + 10, endTime = startTime + 20
236         //
237         SampleNegotiationOffer negotiationOffer2 = new SampleNegotiationOffer( counterOffer1 );
238 
239         ResourcesType jobResources2 = negotiationOffer2.getResourceDefinition();
240 
241         RangeValueType totalCountRange2 = RangeValueType.Factory.newInstance();
242         totalCountRange2.addNewExact().setDoubleValue( 5 );
243         jobResources2.setTotalResourceCount( totalCountRange2 );
244 
245         TimeConstraintType timeConstraint2 = negotiationOffer2.getTimeConstraint();
246 
247         Calendar startTime2 = (Calendar) timeConstraint2.getStartTime().clone();
248         startTime2.add( Calendar.MINUTE, STARTTIME_OFFSET );
249         Calendar endTime2 = (Calendar) startTime2.clone();
250         endTime2.add( Calendar.MINUTE, ENDTIME_OFFSET );
251         timeConstraint2.setStartTime( startTime2 );
252         timeConstraint2.setEndTime( endTime2 );
253         timeConstraint2.setDuration( DURATION );
254 
255         setResourcesSDT( negotiationOffer2, jobResources2 );
256         setTimeConstraintSDT( negotiationOffer2, timeConstraint2 );
257 
258         NegotiationOfferType[] negotiationOfferTypes2 = { negotiationOffer2.getXMLObject() };
259         if ( LOG.isTraceEnabled() )
260         {
261             for ( int i = 0; i < negotiationOfferTypes2.length; i++ )
262             {
263                 LOG.trace( "Iteration-2: negotiation offers: " + negotiationOfferTypes2[i].toString() );
264             }
265         }
266 
267         NegotiationOfferType[] counterOffers2 = negotiation.negotiate( negotiationOfferTypes2 );
268         assertNotNull( counterOffers2 );
269         assertEquals( 1, counterOffers2.length );
270 
271         LOG.info( "Iteration-2: Number of counter offers received: " + counterOffers2.length );
272 
273         if ( LOG.isTraceEnabled() )
274         {
275             for ( int i = 0; i < counterOffers2.length; i++ )
276             {
277                 LOG.trace( "Iteration-2: counter_offer: " + counterOffers2[i].xmlText() );
278             }
279         }
280 
281         LOG.info( "second iteration of negotiation is successful" );
282 
283         NegotiationOfferType selectedCounterOffer = counterOffers2[0];
284 
285         //
286         // check whether the negotiation (counter) offer is rejected
287         //
288         if ( selectedCounterOffer.getNegotiationOfferContext().getState().isSetRejected() )
289         {
290             String message =
291                 "Iteration-2: counter offer [" + selectedCounterOffer.getOfferId()
292                     + "] is rejected. Reason: "
293                     + selectedCounterOffer.getNegotiationOfferContext().getState().xmlText();
294             LOG.error( message );
295             fail( "Iteration-2: NegotiationException: " + message );
296         }
297         return selectedCounterOffer;
298     }
299 
300     /**
301      * @param negotiation
302      * @param negotiationTemplate
303      * @return
304      * @throws Exception
305      * @throws NegotiationException
306      * @throws ResourceUnknownException
307      * @throws ResourceUnavailableException
308      */
309     private NegotiationOfferType negotiateRound1( NegotiationClient negotiation,
310                                                   SampleAgreementTemplate negotiationTemplate )
311         throws Exception
312     {
313 
314         /******************************************************************
315          * First round of the Negotiation
316          ******************************************************************/
317         //
318         // This template includes the service description term 'RESOURCE_SDT' with a JSDL document
319         // describing the available compute resources.
320         //
321         // NegotiationOffer_1: 05 resources for 15 minutes duration with a time frame as
322         // startTime = current, endTime = startTime + 60
323         //
324         //
325         String offerID =
326             negotiationTemplate.getContext().getTemplateId() + "-" + negotiationTemplate.getName();
327 
328         ResourcesType jobResources1 = negotiationTemplate.getResourceDefinition();
329 
330         RangeValueType totalCountRange1 = RangeValueType.Factory.newInstance();
331         totalCountRange1.addNewExact().setDoubleValue( 5 );
332         jobResources1.setTotalResourceCount( totalCountRange1 );
333 
334         //
335         // The service description term 'TIME_CONSTRAINT_SDT' defines the time frame
336         // during which the resources can be available.
337         // The start and end time specified by a user is considered to be the earliest possible start time and
338         // the
339         // deadline
340         // We need an advance reservation of the resources for 15 minutes effective duration, however,
341         // within a same time frame as received from a resource provider
342         //
343         TimeConstraintType timeConstraint1 = negotiationTemplate.getTimeConstraint();
344 
345         Calendar startTime1 = (Calendar) timeConstraint1.getStartTime().clone();
346         Calendar endTime1 = (Calendar) timeConstraint1.getEndTime().clone();
347         timeConstraint1.setStartTime( startTime1 );
348         timeConstraint1.setEndTime( endTime1 );
349         timeConstraint1.setDuration( 15 );
350 
351         //
352         // now we create negotiation offer from a negotiable template for the reservation of
353         // required resources to fulfill the application execution requirements.
354         //
355         SampleNegotiationOffer negotiationOffer1 = negotiationTemplate.getNegotiationOffer();
356         negotiationOffer1.setOfferId( offerID );
357 
358         //
359         // creating negotiation offer context
360         //
361         NegotiationOfferContextType negOfferContext = NegotiationOfferContextType.Factory.newInstance();
362         negOfferContext.setCreator( NegotiationRoleType.NEGOTIATION_INITIATOR );
363         GregorianCalendar expireDate = new GregorianCalendar();
364         expireDate.add( Calendar.MINUTE, 5 );
365         negOfferContext.setExpirationTime( expireDate );
366         NegotiationOfferStateType negOfferState = NegotiationOfferStateType.Factory.newInstance();
367         negOfferState.addNewAdvisory();
368         negOfferContext.setState( negOfferState );
369         negOfferContext.setCounterOfferTo( offerID ); // a fully qualified name of the template
370                                                       // (templateID-TemplateName)
371 
372         negotiationOffer1.setNegotiationOfferContext( negOfferContext );
373 
374         //
375         // one negotiation constraint is added that basically define the preferred time frame window within
376         // which
377         // the user
378         // would like to have the reservation of resources (say within first 45 minutes)
379         //
380         NegotiationConstraintSectionType constraints1 =
381             addNeogtiationOfferConstraints( timeConstraint1.getStartTime() );
382         negotiationOffer1.setNegotiationConstraints( constraints1 );
383 
384         //
385         // Service description terms 'RESOURCE_SDT' and 'TIME_CONSTRAINT_SDT' are updated in a negotiation
386         // offer.
387         //
388         setResourcesSDT( negotiationOffer1, jobResources1 );
389         setTimeConstraintSDT( negotiationOffer1, timeConstraint1 );
390 
391         NegotiationOfferType[] negotiationOfferTypes1 = { negotiationOffer1.getXMLObject() };
392         if ( LOG.isTraceEnabled() )
393         {
394             for ( int i = 0; i < negotiationOfferTypes1.length; i++ )
395             {
396                 LOG.trace( "Iteration-1: negotiation offers: " + negotiationOfferTypes1[i].toString() );
397             }
398         }
399 
400         //
401         // invoking negotiate method from Negotiation instance and
402         // in return counter offers are received
403         //
404         NegotiationOfferType[] counterOffers1 = negotiation.negotiate( negotiationOfferTypes1 );
405         assertNotNull( counterOffers1 );
406         assertEquals( 2, counterOffers1.length );
407 
408         LOG.info( "Iteration-1: Number of counter offers received: " + counterOffers1.length );
409 
410         if ( LOG.isTraceEnabled() )
411         {
412             for ( int i = 0; i < counterOffers1.length; i++ )
413             {
414                 LOG.trace( "Iteration-1: counter_offer: " + counterOffers1[i].xmlText() );
415             }
416         }
417 
418         //
419         // first check whether the negotiation (counter) offer is rejected
420         //
421         NegotiationOfferType counterOffer1 = counterOffers1[0];
422         if ( counterOffer1.getNegotiationOfferContext().getState().isSetRejected() )
423         {
424             String message =
425                 "Iteration-1: counter offer [" + counterOffer1.getOfferId() + "] is rejected. Reason: "
426                     + counterOffer1.getNegotiationOfferContext().getState().xmlText();
427             LOG.error( message );
428             fail( "Iteration-1: NegotiationException: " + message );
429         }
430 
431         LOG.info( "first iteration of negotiation is successful" );
432         return counterOffer1;
433     }
434 
435     /**
436      * @param negotiation
437      * @return
438      * @throws ResourceUnknownException
439      * @throws ResourceUnavailableException
440      */
441     private SampleAgreementTemplate getNegotiableTemplate( NegotiationClient negotiation )
442         throws ResourceUnknownException, ResourceUnavailableException
443     {
444         //
445         // retrieve the agreement templates for which negotiation is supported,
446         // and select the one with template name "SAMPLE-TEMPLATE".
447         //
448         LOG.info( "getting negotiable templates" );
449 
450         AgreementTemplateType[] negotiableTemplates = negotiation.getNegotiableTemplates();
451         assertNotNull( negotiableTemplates );
452 
453         AgreementTemplateType template = null;
454         for ( int i = 0; i < negotiableTemplates.length; i++ )
455         {
456             AgreementTemplateType agreementTemplate = negotiableTemplates[i];
457             LOG.debug( "retrieved template: " + agreementTemplate.getName() + ":"
458                 + agreementTemplate.getTemplateId() );
459             LOG.trace( agreementTemplate.toString() );
460             if ( agreementTemplate.getName().equals( TEMPLATE_NAME ) )
461             {
462                 template = agreementTemplate;
463             }
464         }
465         assertEquals( TEMPLATE_NAME, template.getName() );
466 
467         //
468         // The "SAMPLE-TEMPLATE" template exposes the current availability of computing resources by a
469         // resource provider.
470         //
471         SampleAgreementTemplate negotiationTemplate = new SampleAgreementTemplate( template );
472         if ( LOG.isTraceEnabled() )
473         {
474             LOG.trace( "negotiation-template: " + negotiationTemplate.getXMLObject().xmlText() );
475         }
476         return negotiationTemplate;
477     }
478 
479     /**
480      * @param factory
481      * @param negotiation
482      * @return
483      */
484     private NegotiationClient initiateNegotiation()
485     {
486         try
487         {
488             AgreementFactoryClient factory = getAgreementFactoryClient( FACTORY_RESOURCE_ID );
489 
490             //
491             // Now creates a negotiation context that defines the roles and obligations
492             // of the negotiating parties and specifies the type of the negotiation process.
493             //
494             NegotiationContextDocument negContextDoc = NegotiationContextDocument.Factory.newInstance();
495             NegotiationContextType negContext = negContextDoc.addNewNegotiationContext();
496             negContext.setAgreementFactoryEPR( factory.getRemoteClient().getRemoteReference() );
497             negContext.setAgreementResponder( NegotiationRoleType.NEGOTIATION_RESPONDER );
498             GregorianCalendar expireDate = new GregorianCalendar();
499             expireDate.add( Calendar.HOUR, 1 );
500             negContext.setExpirationTime( expireDate );
501             //
502             // set the nature of the negotiation process (e.g. negotiation or re-negotiation).
503             //
504             NegotiationType negotiationType = negContext.addNewNegotiationType();
505             negotiationType.addNewNegotiation();
506             //
507             // creating negotiation instance based on a negotiation context from a selected agreement factory
508             //
509             NegotiationClient negotiation = factory.initiateNegotiation( negContext );
510             assertNotNull( "the created negotiatin client is not null", negotiation );
511 
512             LOG.info( "negotiation instance is created successfully" );
513 
514             return negotiation;
515         }
516         catch ( NegotiationFactoryException e )
517         {
518             fail( "NegotiationFactoryException: " + e.getMessage() );
519         }
520         catch ( ResourceUnavailableException e )
521         {
522             fail( "ResourceUnavailableException: " + e.getMessage() );
523         }
524         catch ( ResourceUnknownException e )
525         {
526             fail( "ResourceUnknownException: " + e.getMessage() );
527         }
528         catch ( Exception e )
529         {
530             fail( "Could not create negotiation client instance. Error: " + e.getMessage() );
531         }
532 
533         throw new RuntimeException( "test case implementation error" );
534     }
535 
536     private void setResourcesSDT( SampleNegotiationOffer negotiationOffer, ResourcesType jobResources )
537         throws Exception
538     {
539 
540         ServiceDescriptionTermType resourcesSDT = null;
541 
542         ServiceDescriptionTermType[] sdts =
543             negotiationOffer.getTerms().getAll().getServiceDescriptionTermArray();
544 
545         if ( sdts != null )
546         {
547             for ( int i = 0; i < sdts.length; i++ )
548             {
549                 if ( sdts[i].getName().equals( RESOURCES_SDT_NAME ) )
550                 {
551                     resourcesSDT = sdts[i];
552                     break;
553                 }
554             }
555         }
556 
557         String name = resourcesSDT.getName();
558         String serviceName = resourcesSDT.getServiceName();
559 
560         JobDefinitionDocument resourcesDoc = JobDefinitionDocument.Factory.newInstance();
561         resourcesDoc.addNewJobDefinition().addNewJobDescription().addNewResources();
562         resourcesDoc.getJobDefinition().getJobDescription().getResources().set( jobResources );
563 
564         resourcesSDT.set( resourcesDoc );
565         resourcesSDT.setName( name );
566         resourcesSDT.setServiceName( serviceName );
567     }
568 
569     private void setTimeConstraintSDT( SampleNegotiationOffer negotiationOffer,
570                                        TimeConstraintType timeConstraint )
571     {
572 
573         ServiceDescriptionTermType timeConstraintSDT = null;
574 
575         ServiceDescriptionTermType[] sdts =
576             negotiationOffer.getTerms().getAll().getServiceDescriptionTermArray();
577 
578         if ( sdts != null )
579         {
580             for ( int i = 0; i < sdts.length; i++ )
581             {
582                 if ( sdts[i].getName().equals( TIME_CONSTRAINT_SDT_NAME ) )
583                 {
584                     timeConstraintSDT = sdts[i];
585                     break;
586                 }
587             }
588         }
589 
590         String name = timeConstraintSDT.getName();
591         String serviceName = timeConstraintSDT.getServiceName();
592 
593         TimeConstraintDocument timeConstraintDoc = TimeConstraintDocument.Factory.newInstance();
594         timeConstraintDoc.addNewTimeConstraint();
595         timeConstraintDoc.getTimeConstraint().set( timeConstraint );
596 
597         timeConstraintSDT.set( timeConstraintDoc );
598         timeConstraintSDT.setName( name );
599         timeConstraintSDT.setServiceName( serviceName );
600     }
601 
602     private NegotiationConstraintSectionType addNeogtiationOfferConstraints( Calendar startTime )
603     {
604 
605         final String constraintItemName = "TimeConstraintSDT_TimeConstraint_START_TIME";
606         final String constraintXpath =
607             "declare namespace wsag-tc='http://schemas.wsag4j.org/2009/07/wsag4j-scheduling-extensions';"
608                 + "declare namespace wsag='http://schemas.ggf.org/graap/2007/03/ws-agreement';"
609                 + "$this/wsag:Terms/wsag:All/wsag:ServiceDescriptionTerm[@wsag:Name = 'TIME_CONSTRAINT_SDT']"
610                 + "/wsag4jt:TimeConstraint";
611 
612         NegotiationConstraintSectionType constraints = NegotiationConstraintSectionType.Factory.newInstance();
613 
614         // add one item constraint
615         NegotiationOfferItemType offerItem = constraints.addNewItem();
616         offerItem.setName( constraintItemName );
617         offerItem.setLocation( constraintXpath );
618 
619         ItemConstraint constraint = offerItem.addNewItemConstraint();
620 
621         constraint.addNewMinInclusive().setValue( XmlDateTime.Factory.newValue( startTime ) );
622         Calendar preferredEndTime = (Calendar) startTime.clone();
623         preferredEndTime.add( Calendar.MINUTE, END_TIME_OFFSET );
624         constraint.addNewMaxInclusive().setValue( XmlDateTime.Factory.newValue( preferredEndTime ) );
625 
626         return constraints;
627     }
628 }