1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package org.ogf.graap.wsag.server.engine;
36
37 import java.text.MessageFormat;
38 import java.util.Collection;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.UUID;
43 import java.util.Vector;
44
45 import org.apache.log4j.Logger;
46 import org.apache.xmlbeans.XmlObject;
47 import org.ogf.graap.wsag.api.Negotiation;
48 import org.ogf.graap.wsag.api.exceptions.NegotiationException;
49 import org.ogf.graap.wsag.api.logging.LogMessage;
50 import org.ogf.graap.wsag.server.actions.impl.AgreementFactoryAction;
51 import org.ogf.graap.wsag.server.api.IAgreementFactory;
52 import org.ogf.schemas.graap.wsAgreement.AgreementTemplateType;
53 import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationContextType;
54 import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationOfferContextType;
55 import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationOfferDocument;
56 import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationOfferStateType;
57 import org.ogf.schemas.graap.wsAgreement.negotiation.NegotiationOfferType;
58 import org.w3c.dom.Node;
59
60
61
62
63
64
65
66
67
68 public class GenericNegotiation
69 implements Negotiation
70 {
71
72
73
74
75 private static final Logger LOG = Logger.getLogger( GenericNegotiation.class );
76
77
78
79
80 public static final String CRITICAL_EXTENSIONS = "org.wsag4j.negotiation.properties.critical";
81
82
83
84
85 public static final String NON_CRITICAL_EXTENSIONS = "org.wsag4j.negotiation.properties.noncritical";
86
87
88
89
90 public static final String NEGOTIATION_CONTEXT = "org.wsag4j.negotiation.context";
91
92
93
94
95 @SuppressWarnings( "unused" )
96 private final IAgreementFactory factory;
97
98
99
100
101 private final TemplateRegistry registry;
102
103
104
105
106 private final NegotiationContextType context;
107
108
109
110
111 private final Map<String, Object> negotiationProperties;
112
113 private final Map<String, NegotiationOfferType> offerHistory =
114 new HashMap<String, NegotiationOfferType>();
115
116 private final TemplateValidator templateValidator;
117
118
119
120
121
122
123
124
125
126
127
128 public GenericNegotiation( IAgreementFactory factory, TemplateRegistry registry,
129 NegotiationContextType context )
130 {
131
132 this( factory, registry, context, new HashMap<String, Object>() );
133 }
134
135 private void checkOfferIntegrity( NegotiationOfferType offer ) throws NegotiationException
136 {
137 NegotiationOfferContextType negotiationOfferContext = offer.getNegotiationOfferContext();
138 if ( negotiationOfferContext == null )
139 {
140 String message = "missing negotiation offer context";
141 throw new NegotiationException( message );
142 }
143
144 String parentOfferId = negotiationOfferContext.getCounterOfferTo();
145 if ( parentOfferId == null )
146 {
147 String message = "missing counter-offer-to-id in negotiation offer context";
148 throw new NegotiationException( message );
149 }
150
151 String offerTemplateId = offer.getContext().getTemplateId();
152 if ( offerTemplateId == null )
153 {
154 String message = "missing template-id in context";
155 throw new NegotiationException( message );
156 }
157
158 String offerTemplateName = offer.getContext().getTemplateName();
159 if ( offerTemplateName == null )
160 {
161 String message = "missing template name in context";
162 throw new NegotiationException( message );
163 }
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 public GenericNegotiation( IAgreementFactory factory, TemplateRegistry registry,
181 NegotiationContextType context, Map<String, Object> negotiationProperties )
182 {
183
184 this.factory = factory;
185 this.registry = registry;
186 this.context = context;
187 this.negotiationProperties = negotiationProperties;
188
189 this.templateValidator = new TemplateValidator();
190 this.templateValidator.setConfiguration( factory.getEngine().getConfiguration().getValidator() );
191 }
192
193
194
195
196
197
198 public void advertise( NegotiationOfferType[] quotes, XmlObject[] noncriticalExtensions )
199 throws NegotiationException
200 {
201
202
203
204 throw new UnsupportedOperationException( "not implemented" );
205 }
206
207
208
209
210
211
212 public NegotiationOfferType[] negotiate( NegotiationOfferType[] counterOffers,
213 XmlObject[] noncriticalExtensions ) throws NegotiationException
214 {
215
216 List<NegotiationOfferType> result = new Vector<NegotiationOfferType>();
217
218
219 Map<String, Object> invocationContext = new HashMap<String, Object>();
220 invocationContext.put( NON_CRITICAL_EXTENSIONS, noncriticalExtensions );
221 invocationContext.put( NEGOTIATION_CONTEXT, negotiationProperties );
222
223
224 for ( int i = 0; i < counterOffers.length; i++ )
225 {
226 NegotiationOfferType counterOffer = counterOffers[i];
227
228 try
229 {
230
231
232
233 checkOfferIntegrity( counterOffer );
234 NegotiationOfferContextType negotiationOfferContext =
235 counterOffer.getNegotiationOfferContext();
236 String parentOfferId = negotiationOfferContext.getCounterOfferTo();
237 String offerTemplateId = counterOffer.getContext().getTemplateId();
238 String offerTemplateName = counterOffer.getContext().getTemplateName();
239
240
241
242
243 checkParentOffer( counterOffer, parentOfferId );
244
245
246
247
248 AgreementTemplateType templateType =
249 registry.findTemplate( offerTemplateName, offerTemplateId );
250
251 if ( templateType == null )
252 {
253 throw new NegotiationException( "Could not load any template for passed offer." );
254 }
255
256 boolean isValid = templateValidator.validate( counterOffer, templateType );
257 if ( isValid )
258 {
259 LOG.debug( "Counter offer validated against template." );
260
261
262
263
264 String templateId = MessageFormat.format( "{0}-{1}", offerTemplateId, offerTemplateName );
265 if ( offerHistory.containsKey( parentOfferId ) )
266 {
267 String message = "Found parent offer with ID ''{0}''.";
268 LOG.debug( LogMessage.getMessage( message, parentOfferId ) );
269
270 NegotiationOfferType parentOffer = offerHistory.get( parentOfferId );
271
272
273
274
275 isValid = templateValidator.validate( counterOffer, parentOffer );
276 if ( isValid )
277 {
278 LOG.debug( "Counter offer validated against parent offer." );
279
280 Vector<NegotiationOfferType> results =
281 performNegotiation( counterOffer, invocationContext, offerTemplateId,
282 offerTemplateName );
283
284
285
286
287 for ( NegotiationOfferType negotiatedOffer : results )
288 {
289 offerHistory.put( negotiatedOffer.getOfferId(),
290 (NegotiationOfferType) negotiatedOffer.copy() );
291 result.add( negotiatedOffer );
292 }
293 }
294 else
295 {
296 String msgValidationFailed = "offer / counter offer validation failed";
297 throw new NegotiationException( msgValidationFailed );
298 }
299 }
300 else if ( parentOfferId.equals( templateId ) )
301 {
302 final String message =
303 "Found root node. Start negotiation process for template ''{0}''.";
304 LOG.debug( LogMessage.getMessage( message, templateId ) );
305
306 Vector<NegotiationOfferType> results =
307 performNegotiation( counterOffer, invocationContext, offerTemplateId,
308 offerTemplateName );
309
310
311
312
313
314 for ( NegotiationOfferType negotiatedOffer : results )
315 {
316 negotiatedOffer.getNegotiationOfferContext().setCounterOfferTo( templateId );
317
318 offerHistory.put( negotiatedOffer.getOfferId(),
319 (NegotiationOfferType) negotiatedOffer.copy() );
320 result.add( negotiatedOffer );
321 }
322 }
323 else
324 {
325 String msgUnknownOffer =
326 "Negotiation process did not start from root or any other node.";
327 throw new NegotiationException( msgUnknownOffer );
328 }
329 }
330 else
331 {
332
333
334
335
336 throw new NegotiationException(
337 "Validation of the negotiation offer against template failed." );
338 }
339 }
340 catch ( NegotiationException ex )
341 {
342 String errorMessage = "Negotiation process aborted. Building REJECT-counter-offer.";
343 LOG.error( errorMessage );
344
345 NegotiationOfferType rejected = buildRejectOffer( counterOffer, ex );
346 result.add( rejected );
347 }
348 }
349
350 NegotiationOfferType[] offerArray = result.toArray( new NegotiationOfferType[result.size()] );
351
352 return offerArray;
353 }
354
355
356
357
358
359
360
361 private void checkParentOffer( NegotiationOfferType counterOffer, String parentOfferId )
362 throws NegotiationException
363 {
364 LOG.debug( LogMessage.getMessage( "Processing offer ''{0}''.", counterOffer.getOfferId() ) );
365
366
367
368
369
370 if ( offerHistory.containsKey( parentOfferId ) )
371 {
372 if ( offerHistory.get( parentOfferId ).getNegotiationOfferContext().getState().isSetRejected() )
373 {
374 String errorMessage = "Negotiation based on a rejected counter offer is not possible.";
375 LOG.error( errorMessage );
376
377 throw new NegotiationException( errorMessage );
378 }
379 }
380 }
381
382 private Vector<NegotiationOfferType>
383 performNegotiation( NegotiationOfferType counterOffer, Map<String, Object> invocationContext,
384 String offerTemplateId, String offerTemplateName ) throws NegotiationException
385 {
386 Vector<NegotiationOfferType> results = new Vector<NegotiationOfferType>();
387
388
389
390
391
392
393
394 AgreementFactoryAction action = loadAction( counterOffer );
395
396 if ( action == null )
397 {
398 String msgText = "No action for template id ''{0}'' and template name ''{1}'' found.";
399 String message = MessageFormat.format( msgText, offerTemplateId, offerTemplateName );
400 throw new NegotiationException( message );
401 }
402 else
403 {
404
405
406
407
408
409
410 try
411 {
412 final String message =
413 "Negotiate (counter) offer [offer id=''{0}'', counterOfferTo=''{1}''].";
414 LOG.debug( LogMessage.getMessage( message, counterOffer.getOfferId(),
415 counterOffer.getNegotiationOfferContext().getCounterOfferTo() ) );
416
417 NegotiationOfferType[] negotiatedOffers = action.negotiate( counterOffer, invocationContext );
418
419 for ( NegotiationOfferType negotiatedOffer : negotiatedOffers )
420 {
421
422
423
424
425 String negotiatedOfferTemplateId = negotiatedOffer.getContext().getTemplateId();
426 String negotiatedOfferTemplateName = negotiatedOffer.getContext().getTemplateName();
427
428 if ( !offerTemplateId.equals( negotiatedOfferTemplateId ) )
429 {
430 String exMessageText =
431 "Template IDs of offer ''{0}'' and counter offer ''{1}'' not equal.";
432 String exMessage =
433 MessageFormat.format( exMessageText, offerTemplateId, negotiatedOfferTemplateId );
434
435 throw new NegotiationException( exMessage );
436 }
437 else if ( !offerTemplateName.equals( negotiatedOfferTemplateName ) )
438 {
439 String exMessageText =
440 "Template names of offer ''{0}'' and counter offer ''{1}'' not equal.";
441 String exMessage =
442 MessageFormat.format( exMessageText, offerTemplateName,
443 negotiatedOfferTemplateName );
444
445 throw new NegotiationException( exMessage );
446 }
447
448
449
450
451
452 String offerUuid = UUID.randomUUID().toString();
453
454 while ( offerHistory.containsKey( offerUuid ) )
455 {
456 offerUuid = UUID.randomUUID().toString();
457 }
458
459 negotiatedOffer.setOfferId( offerUuid );
460 negotiatedOffer.getNegotiationOfferContext()
461 .setCounterOfferTo( counterOffer.getOfferId() );
462 results.add( negotiatedOffer );
463 }
464 }
465 catch ( NegotiationException ex )
466 {
467 String errorMessage = "Negotiation of offer failed.";
468 LOG.error( errorMessage );
469
470 NegotiationOfferType rejected = buildRejectOffer( counterOffer, ex );
471 results.add( rejected );
472 }
473 }
474
475 return results;
476 }
477
478 private NegotiationOfferType
479 buildRejectOffer( NegotiationOfferType counterOffer, NegotiationException ex )
480 {
481
482
483
484 NegotiationOfferDocument negotiationOfferDocument = NegotiationOfferDocument.Factory.newInstance();
485 negotiationOfferDocument.addNewNegotiationOffer().set( counterOffer.copy() );
486
487 NegotiationOfferType rejected = negotiationOfferDocument.getNegotiationOffer();
488 rejected.getNegotiationOfferContext().setState( NegotiationOfferStateType.Factory.newInstance() );
489 rejected.getNegotiationOfferContext().getState().addNewRejected();
490
491 String offerUuid = UUID.randomUUID().toString();
492 while ( offerHistory.containsKey( offerUuid ) )
493 {
494 offerUuid = UUID.randomUUID().toString();
495 }
496 rejected.setOfferId( offerUuid );
497 offerHistory.put( offerUuid, (NegotiationOfferType) rejected.copy() );
498
499 Node imported =
500 rejected.getDomNode().getOwnerDocument().importNode( ex.getBaseFault().getDomNode(), true );
501 rejected.getDomNode().appendChild( imported );
502
503 return rejected;
504 }
505
506
507
508
509
510
511 public NegotiationContextType getNegotiationContext()
512 {
513 return context;
514 }
515
516
517
518
519
520
521 public NegotiationOfferType[] getNegotiationOffers()
522 {
523 Collection<NegotiationOfferType> offers = offerHistory.values();
524 NegotiationOfferType[] offerArray = offers.toArray( new NegotiationOfferType[offers.size()] );
525
526 return offerArray;
527 }
528
529
530
531
532 public void terminate()
533 {
534
535
536
537 }
538
539
540
541
542
543
544
545
546
547 public AgreementFactoryAction loadAction( NegotiationOfferType quote )
548 {
549 String templateName = quote.getContext().getTemplateName();
550 String templateId = quote.getContext().getTemplateId();
551 AgreementFactoryAction action = registry.findAction( templateName, templateId );
552
553 return action;
554 }
555
556
557
558
559
560
561
562
563
564 public AgreementTemplateType[] getNegotiableTemplates()
565 {
566 return registry.getNegotiableTemplates();
567 }
568 }