KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencrx > kernel > layer > persistence > Audit_1


1 /*
2  * ====================================================================
3  * Project: opencrx, http://www.opencrx.org/
4  * Name: $Id: Audit_1.java,v 1.12 2006/01/30 00:41:55 wfro Exp $
5  * Description: openCRX audit plugin
6  * Revision: $Revision: 1.12 $
7  * Owner: CRIXP AG, Switzerland, http://www.crixp.com
8  * Date: $Date: 2006/01/30 00:41:55 $
9  * ====================================================================
10  *
11  * This software is published under the BSD license
12  * as listed below.
13  *
14  * Copyright (c) 2004, CRIXP Corp., Switzerland
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  *
21  * * Redistributions of source code must retain the above copyright
22  * notice, this list of conditions and the following disclaimer.
23  *
24  * * Redistributions in binary form must reproduce the above copyright
25  * notice, this list of conditions and the following disclaimer in
26  * the documentation and/or other materials provided with the
27  * distribution.
28  *
29  * * Neither the name of CRIXP Corp. nor the names of the contributors
30  * to openCRX may be used to endorse or promote products derived
31  * from this software without specific prior written permission
32  *
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
35  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
36  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
37  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
39  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
40  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
41  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
43  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46  * POSSIBILITY OF SUCH DAMAGE.
47  *
48  * ------------------
49  *
50  * This product includes software developed by the Apache Software
51  * Foundation (http://www.apache.org/).
52  *
53  * This product includes software developed by contributors to
54  * openMDX (http://www.openmdx.org/)
55  */

56 package org.opencrx.kernel.layer.persistence;
57
58 import java.math.BigDecimal JavaDoc;
59 import java.util.ArrayList JavaDoc;
60 import java.util.Arrays JavaDoc;
61 import java.util.Date JavaDoc;
62 import java.util.HashMap JavaDoc;
63 import java.util.HashSet JavaDoc;
64 import java.util.Iterator JavaDoc;
65 import java.util.List JavaDoc;
66 import java.util.Map JavaDoc;
67 import java.util.Set JavaDoc;
68
69 import org.opencrx.kernel.generic.SecurityKeys;
70 import org.openmdx.base.exception.ServiceException;
71 import org.openmdx.compatibility.base.application.configuration.Configuration;
72 import org.openmdx.compatibility.base.collection.SparseList;
73 import org.openmdx.compatibility.base.dataprovider.cci.AttributeSelectors;
74 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderObject;
75 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderObject_1_0;
76 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderOperations;
77 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderReply;
78 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderReplyContexts;
79 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderRequest;
80 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderRequestContexts;
81 import org.openmdx.compatibility.base.dataprovider.cci.Directions;
82 import org.openmdx.compatibility.base.dataprovider.cci.ServiceHeader;
83 import org.openmdx.compatibility.base.dataprovider.cci.SystemAttributes;
84 import org.openmdx.compatibility.base.dataprovider.spi.Layer_1_0;
85 import org.openmdx.compatibility.base.naming.Path;
86 import org.openmdx.compatibility.base.query.FilterOperators;
87 import org.openmdx.compatibility.base.query.FilterProperty;
88 import org.openmdx.compatibility.base.query.Quantors;
89
90 /**
91  * This plugin creates audit entries for modified objects.
92  */

93 public class Audit_1
94     extends ObjectMapping_1 {
95
96     //-------------------------------------------------------------------------
97
public void activate(
98         short id,
99         Configuration configuration,
100         Layer_1_0 delegation
101     ) throws Exception JavaDoc, ServiceException {
102         super.activate(id, configuration, delegation);
103     }
104     
105     //-------------------------------------------------------------------------
106
public void prolog(
107         ServiceHeader header,
108         DataproviderRequest[] requests
109     ) throws ServiceException {
110         super.prolog(
111           header,
112           requests
113         );
114         String JavaDoc unitOfWorkId = requests.length == 0
115           ? null
116           : requests[0].context(DataproviderRequestContexts.UNIT_OF_WORK_ID).size() == 0
117             ? null
118             : (String JavaDoc)requests[0].context(DataproviderRequestContexts.UNIT_OF_WORK_ID).get(0);
119         // guarantee that this.unitOfWorkId has always a valid value
120
this.unitOfWorkId = unitOfWorkId != null
121           ? unitOfWorkId
122           : this.unitOfWorkId != null
123             ? this.unitOfWorkId
124             : super.uidAsString();
125     }
126
127     //-------------------------------------------------------------------------
128
private boolean isAuditee(
129       DataproviderObject_1_0 object
130     ) throws ServiceException {
131         String JavaDoc objectClass = (String JavaDoc)object.values(SystemAttributes.OBJECT_CLASS).get(0);
132         return this.model.isSubtypeOf(
133             objectClass,
134             "org:opencrx:kernel:base:Auditee"
135         );
136     }
137
138     //-------------------------------------------------------------------------
139
private boolean isAuditSegment(
140         ServiceHeader header,
141         Path path
142     ) throws ServiceException {
143         Path p = path.getPrefix(5);
144         Boolean JavaDoc isAuditSegment = (Boolean JavaDoc)this.auditSegments.get(p);
145         if(isAuditSegment == null) {
146             DataproviderObject segment = super.get(
147                 header,
148                 new DataproviderRequest(
149                     new DataproviderObject(p),
150                     DataproviderOperations.OBJECT_RETRIEVAL,
151                     AttributeSelectors.ALL_ATTRIBUTES,
152                     null
153                 )
154             ).getObject();
155             this.auditSegments.put(
156                 p,
157                 isAuditSegment = new Boolean JavaDoc(this.isAuditee(segment))
158             );
159         }
160         return isAuditSegment.booleanValue();
161     }
162     
163     //-------------------------------------------------------------------------
164
private DataproviderObject createResult(
165       DataproviderRequest request,
166       String JavaDoc structName
167     ) {
168       DataproviderObject result = new DataproviderObject(
169         request.path().getDescendant(
170           new String JavaDoc[]{ "reply", super.uidAsString()}
171         )
172       );
173       result.clearValues(SystemAttributes.OBJECT_CLASS).add(
174         structName
175       );
176       return result;
177     }
178
179     //-------------------------------------------------------------------------
180
/**
181      * Return the set of attributes which's values changed in o2 relative to o1.
182      */

183     private Set JavaDoc getChangedAttributes(
184         DataproviderObject_1_0 o1,
185         DataproviderObject_1_0 o2
186     ) {
187         if(o2 == null) {
188           return new HashSet JavaDoc();
189         }
190         
191         // touch all o1 attributes in o2
192
for(
193           Iterator JavaDoc i = o1.attributeNames().iterator();
194           i.hasNext();
195         ) {
196           o2.values((String JavaDoc)i.next());
197         }
198         
199         // diff
200
Set JavaDoc changedAttributes = new HashSet JavaDoc();
201         for(
202             Iterator JavaDoc i = o2.attributeNames().iterator();
203             i.hasNext();
204         ) {
205             String JavaDoc attributeName = (String JavaDoc)i.next();
206             SparseList v1 = o1.values(attributeName);
207             SparseList v2 = o2.values(attributeName);
208             if(
209                 !SystemAttributes.OBJECT_INSTANCE_OF.equals(attributeName) &&
210                 !"identity".equals(attributeName)
211             ) {
212                 boolean isEqual = v1.size() == v2.size();
213                 if(isEqual) {
214                     for(int j = 0; j < v1.size(); j++) {
215                         if(v1.get(j) instanceof BigDecimal JavaDoc) {
216                             if(v2.get(j) instanceof BigDecimal JavaDoc) {
217                                 isEqual = ((BigDecimal JavaDoc)v1.get(j)).compareTo(v2.get(j)) == 0;
218                             }
219                             else {
220                                 isEqual = false;
221                             }
222                         }
223                         else if(v1.get(j) == null) {
224                             isEqual = v2.get(j) == null;
225                         }
226                         else {
227                             isEqual = v1.get(j).equals(v2.get(j));
228                         }
229                         if(!isEqual) break;
230                     }
231                 }
232                 if(!isEqual) {
233                     changedAttributes.add(attributeName);
234                 }
235             }
236         }
237         return changedAttributes;
238     }
239
240     //-----------------------------------------------------------------------
241
public String JavaDoc getBeforeImageAsString(
242         DataproviderObject_1_0 beforeImage
243     ) {
244         String JavaDoc beforeImageAsString = "";
245         for(
246             Iterator JavaDoc i = beforeImage.attributeNames().iterator();
247             i.hasNext();
248         ) {
249             String JavaDoc attributeName = (String JavaDoc)i.next();
250             beforeImageAsString += attributeName + ":\n";
251             int jj = 0;
252             for(
253                 Iterator JavaDoc j = beforeImage.values(attributeName).iterator();
254                 j.hasNext();
255                 jj++
256             ) {
257                 beforeImageAsString += "" + jj + ": " + j.next() + "\n";
258             }
259         }
260         return beforeImageAsString;
261     }
262     
263     //-----------------------------------------------------------------------
264
public DataproviderReply get(
265         ServiceHeader header,
266         DataproviderRequest request
267     ) throws ServiceException {
268         Path reference = request.path().getParent();
269         if("audit".equals(reference.getBase())) {
270             DataproviderObject auditEntry = super.get(
271                 header,
272                 new DataproviderRequest(
273                     new DataproviderObject(
274                         request.path().getPrefix(5).getDescendant(new String JavaDoc[]{"audit", request.path().getBase()})
275                     ),
276                     DataproviderOperations.OBJECT_RETRIEVAL,
277                     AttributeSelectors.ALL_ATTRIBUTES,
278                     null
279                 )
280             ).getObject();
281             DataproviderObject mappedAuditEntry = new DataproviderObject(
282                 request.path()
283             );
284             mappedAuditEntry.addClones(
285                 auditEntry,
286                 true
287             );
288             return new DataproviderReply(
289                 mappedAuditEntry
290             );
291         }
292         else {
293             return super.get(
294                 header,
295                 request
296             );
297         }
298     }
299     
300     //-----------------------------------------------------------------------
301
public DataproviderReply find(
302         ServiceHeader header,
303         DataproviderRequest request
304     ) throws ServiceException {
305         // If auditee is segment do not rewrite find request. Otherwise filter
306
// audit entries with auditee = requested reference
307
if(
308             (request.path().size() > 6) &&
309             "audit".equals(request.path().getBase())
310         ) {
311             // Find audit entries assigned to requesting object,
312
// request.path().getParent() IS_IN auditee of audit entry
313
List JavaDoc filterProperties = request.attributeFilter() == null
314                 ? new ArrayList JavaDoc()
315                 : new ArrayList JavaDoc(Arrays.asList(request.attributeFilter()));
316             filterProperties.add(
317                 new FilterProperty(
318                     Quantors.THERE_EXISTS,
319                     "auditee",
320                     FilterOperators.IS_IN,
321                     new String JavaDoc[]{request.path().getParent().toXri()}
322                 )
323             );
324             DataproviderObject[] auditEntries = super.find(
325                 header,
326                 new DataproviderRequest(
327                     new DataproviderObject(
328                         request.path().getPrefix(5).getChild("audit")
329                     ),
330                     DataproviderOperations.ITERATION_START,
331                     (FilterProperty[])filterProperties.toArray(new FilterProperty[filterProperties.size()]),
332                     0,
333                     Integer.MAX_VALUE,
334                     Directions.ASCENDING,
335                     AttributeSelectors.ALL_ATTRIBUTES,
336                     request.attributeSpecifier()
337                 )
338             ).getObjects();
339             
340             // Remap audit entries so that the parent of the mapped
341
// audit entries is the requesting object, i.e. the auditee.
342
List JavaDoc mappedAuditEntries = new ArrayList JavaDoc();
343             for(
344                 int i = 0;
345                 i < auditEntries.length;
346                 i++
347             ) {
348                 DataproviderObject mappedAuditEntry = new DataproviderObject(
349                     request.path().getChild(auditEntries[i].path().getBase())
350                 );
351                 mappedAuditEntry.addClones(
352                     auditEntries[i],
353                     true
354                 );
355                 mappedAuditEntries.add(
356                     mappedAuditEntry
357                 );
358             }
359             
360             // reply
361
DataproviderReply reply = new DataproviderReply(
362                 mappedAuditEntries
363             );
364             reply.context(
365                 DataproviderReplyContexts.HAS_MORE
366             ).set(0, Boolean.FALSE);
367             reply.context(
368                 DataproviderReplyContexts.TOTAL
369             ).set(
370                 0,
371                 new Integer JavaDoc(mappedAuditEntries.size())
372             );
373             reply.context(DataproviderReplyContexts.ATTRIBUTE_SELECTOR).set(
374                 0,
375                 new Short JavaDoc(request.attributeSelector())
376             );
377             return reply;
378         }
379         else {
380             return super.find(
381                 header,
382                 request
383             );
384         }
385     }
386     
387     //-----------------------------------------------------------------------
388
public DataproviderReply replace(
389         ServiceHeader header,
390         DataproviderRequest request
391     ) throws ServiceException {
392         
393         // Ignore replace requests for top-level objects such as segments,
394
// providers, authorities
395
if(request.path().size() > 5) {
396             if(this.isAuditSegment(header, request.path())) {
397     
398                 // Create audit entry
399
DataproviderObject_1_0 existing = super.get(
400                     header,
401                     new DataproviderRequest(
402                         request.object(),
403                         DataproviderOperations.OBJECT_RETRIEVAL,
404                         AttributeSelectors.ALL_ATTRIBUTES,
405                         null
406                     )
407                 ).getObject();
408                 
409                 // Create ObjectModificationAuditEntry and add it to segment
410
if(this.isAuditee(existing)) {
411                     DataproviderObject auditEntry = new DataproviderObject(
412                         request.path().getPrefix(5).getDescendant(new String JavaDoc[]{"audit", super.uidAsString()})
413                     );
414                     auditEntry.values(SystemAttributes.OBJECT_CLASS).add(
415                         "org:opencrx:kernel:base:ObjectModificationAuditEntry"
416                     );
417                     auditEntry.values("auditee").add(
418                         request.path().toXri()
419                     );
420                     if(this.unitOfWorkId != null) {
421                         auditEntry.values("unitOfWork").add(
422                             this.unitOfWorkId
423                         );
424                     }
425                     // Remove all attribute names from existing object (before
426
// image) which are not modified. This produces a before image
427
// which contains the attribute values before modification of
428
// modified object attributes.
429
DataproviderObject beforeImage = new DataproviderObject(existing);
430                     beforeImage.attributeNames().retainAll(
431                         request.object().attributeNames()
432                     );
433                     Set JavaDoc modifiedFeatures = this.getChangedAttributes(
434                         beforeImage,
435                         request.object()
436                     );
437                     // do not create audit entry if modifiedAt is only modified attribute
438
// --> trivial update
439
if(
440                         (modifiedFeatures.size() > 1) ||
441                         !modifiedFeatures.contains(SystemAttributes.MODIFIED_AT)
442                     ) {
443                         beforeImage.attributeNames().retainAll(
444                             modifiedFeatures
445                         );
446                         auditEntry.values("beforeImage").add(
447                             this.getBeforeImageAsString(beforeImage)
448                         );
449                         String JavaDoc modifiedFeaturesAsString = modifiedFeatures.toString();
450                         auditEntry.values("modifiedFeatures").add(
451                             modifiedFeaturesAsString.length() > 300
452                                 ? modifiedFeaturesAsString.substring(0, 280) + "..."
453                                 : modifiedFeaturesAsString
454                         );
455                         auditEntry.values(SystemAttributes.MODIFIED_AT).addAll(
456                             request.object().values(SystemAttributes.MODIFIED_AT)
457                         );
458                         auditEntry.values(SystemAttributes.MODIFIED_BY).addAll(
459                             request.object().values(SystemAttributes.MODIFIED_BY)
460                         );
461                         auditEntry.values(SystemAttributes.CREATED_AT).addAll(
462                             request.object().values(SystemAttributes.MODIFIED_AT)
463                         );
464                         auditEntry.values(SystemAttributes.CREATED_BY).addAll(
465                             request.object().values(SystemAttributes.MODIFIED_BY)
466                         );
467                         auditEntry.values("owner").addAll(
468                             existing.values("owner")
469                         );
470                         auditEntry.values("accessLevelBrowse").addAll(
471                             existing.values("accessLevelBrowse")
472                         );
473                         auditEntry.values("accessLevelUpdate").add(
474                             new Short JavaDoc(SecurityKeys.ACCESS_LEVEL_NA)
475                         );
476                         auditEntry.values("accessLevelDelete").add(
477                             new Short JavaDoc(SecurityKeys.ACCESS_LEVEL_NA)
478                         );
479                 
480                         // create entry
481
try {
482                             super.create(
483                                 header,
484                                 new DataproviderRequest(
485                                     auditEntry,
486                                     DataproviderOperations.OBJECT_CREATION,
487                                     AttributeSelectors.NO_ATTRIBUTES,
488                                     null
489                                 )
490                             );
491                         }
492                         catch(ServiceException e) {
493                             e.log();
494                         }
495                     }
496                 }
497             }
498             
499             // Replace object
500
return super.replace(
501                 header,
502                 request
503             );
504         }
505         else {
506             return new DataproviderReply(
507                 request.object()
508             );
509         }
510     }
511
512     //-----------------------------------------------------------------------
513
public DataproviderReply create(
514         ServiceHeader header,
515         DataproviderRequest request
516     ) throws ServiceException {
517
518         // Create audit log entries for non-root-level objects only
519
// and for objects which are contained in an auditable segment
520
if(
521             (request.path().size() > 5) &&
522              this.isAuditSegment(header, request.path()) &&
523              this.isAuditee(request.object())
524         ) {
525
526             // Create audit entry
527
DataproviderObject auditEntry = new DataproviderObject(
528                 request.path().getPrefix(5).getDescendant(new String JavaDoc[]{"audit", super.uidAsString()})
529             );
530             auditEntry.values(SystemAttributes.OBJECT_CLASS).add(
531                 "org:opencrx:kernel:base:ObjectCreationAuditEntry"
532             );
533             auditEntry.values("auditee").add(
534                 request.path().toXri()
535             );
536             if(this.unitOfWorkId != null) {
537                 auditEntry.values("unitOfWork").add(
538                     this.unitOfWorkId
539                 );
540             }
541             auditEntry.values(SystemAttributes.MODIFIED_AT).addAll(
542                 request.object().values(SystemAttributes.MODIFIED_AT)
543             );
544             auditEntry.values(SystemAttributes.MODIFIED_BY).addAll(
545                 request.object().values(SystemAttributes.MODIFIED_BY)
546             );
547             auditEntry.values(SystemAttributes.CREATED_AT).addAll(
548                 request.object().values(SystemAttributes.MODIFIED_AT)
549             );
550             auditEntry.values(SystemAttributes.CREATED_BY).addAll(
551                 request.object().values(SystemAttributes.MODIFIED_BY)
552             );
553             auditEntry.values("owner").addAll(
554                 request.object().values("owner")
555             );
556             auditEntry.values("accessLevelBrowse").addAll(
557                 request.object().values("accessLevelBrowse")
558             );
559             auditEntry.values("accessLevelUpdate").add(
560                 new Short JavaDoc(SecurityKeys.ACCESS_LEVEL_NA)
561             );
562             auditEntry.values("accessLevelDelete").add(
563                 new Short JavaDoc(SecurityKeys.ACCESS_LEVEL_NA)
564             );
565             
566             // create entry
567
try {
568                 super.create(
569                     header,
570                     new DataproviderRequest(
571                         auditEntry,
572                         DataproviderOperations.OBJECT_CREATION,
573                         AttributeSelectors.NO_ATTRIBUTES,
574                         null
575                     )
576                 );
577             }
578             catch(ServiceException e) {
579                 e.log();
580             }
581         }
582         
583         // Create object
584
return super.create(
585             header,
586             request
587         );
588     }
589     
590     //-----------------------------------------------------------------------
591
public DataproviderReply remove(
592         ServiceHeader header,
593         DataproviderRequest request
594     ) throws ServiceException {
595         
596         // Create audit log entries for non-root-level objects only
597
// and for objects which are contained in an auditable segment
598
if(
599             (request.path().size() > 5) &&
600              this.isAuditSegment(header, request.path())
601         ) {
602
603             // Create audit entry
604
DataproviderObject_1_0 existing = super.get(
605                 header,
606                 new DataproviderRequest(
607                     request.object(),
608                     DataproviderOperations.OBJECT_RETRIEVAL,
609                     AttributeSelectors.ALL_ATTRIBUTES,
610                     null
611                 )
612             ).getObject();
613
614             // Create ObjectRemovalAuditEntry and add it to segment
615
if(this.isAuditee(existing)) {
616                 DataproviderObject auditEntry = new DataproviderObject(
617                     request.path().getPrefix(5).getDescendant(new String JavaDoc[]{"audit", super.uidAsString()})
618                 );
619                 auditEntry.values(SystemAttributes.OBJECT_CLASS).add(
620                     "org:opencrx:kernel:base:ObjectRemovalAuditEntry"
621                 );
622                 auditEntry.values("auditee").add(
623                     request.path().toXri()
624                 );
625                 if(this.unitOfWorkId != null) {
626                     auditEntry.values("unitOfWork").add(
627                         this.unitOfWorkId
628                     );
629                 }
630                 auditEntry.values("beforeImage").add(
631                     this.getBeforeImageAsString(existing)
632                 );
633                 auditEntry.values(SystemAttributes.MODIFIED_AT).addAll(
634                     request.object().values(SystemAttributes.MODIFIED_AT)
635                 );
636                 auditEntry.values(SystemAttributes.MODIFIED_BY).addAll(
637                     request.object().values(SystemAttributes.MODIFIED_BY)
638                 );
639                 auditEntry.values(SystemAttributes.CREATED_AT).addAll(
640                     request.object().values(SystemAttributes.MODIFIED_AT)
641                 );
642                 auditEntry.values(SystemAttributes.CREATED_BY).addAll(
643                     request.object().values(SystemAttributes.MODIFIED_BY)
644                 );
645                 auditEntry.values("owner").addAll(
646                     existing.values("owner")
647                 );
648                 auditEntry.values("accessLevelBrowse").addAll(
649                     existing.values("accessLevelBrowse")
650                 );
651                 auditEntry.values("accessLevelUpdate").add(
652                     new Short JavaDoc(SecurityKeys.ACCESS_LEVEL_NA)
653                 );
654                 auditEntry.values("accessLevelDelete").add(
655                     new Short JavaDoc(SecurityKeys.ACCESS_LEVEL_NA)
656                 );
657                 
658                 // create entry
659
try {
660                     super.create(
661                         header,
662                         new DataproviderRequest(
663                             auditEntry,
664                             DataproviderOperations.OBJECT_CREATION,
665                             AttributeSelectors.NO_ATTRIBUTES,
666                             null
667                         )
668                     );
669                 }
670                 catch(ServiceException e) {
671                     e.log();
672                 }
673             }
674         }
675         
676         // Remove object
677
return super.remove(
678             header,
679             request
680         );
681         
682     }
683     
684     //-----------------------------------------------------------------------
685
protected DataproviderObject otherOperation(
686         ServiceHeader header,
687         DataproviderRequest request,
688         String JavaDoc operation,
689         Path replyPath
690     ) throws ServiceException {
691         if("testAndSetVisitedBy".equals(operation)) {
692             Path auditEntryIdentity = request.path().getPrefix(request.path().size() - 2);
693             DataproviderObject auditEntry = super.get(
694                 header,
695                 new DataproviderRequest(
696                     new DataproviderObject(auditEntryIdentity),
697                     DataproviderOperations.OBJECT_RETRIEVAL,
698                     AttributeSelectors.ALL_ATTRIBUTES,
699                     null
700                 )
701             ).getObject();
702             String JavaDoc visitorId = (String JavaDoc)request.object().values("visitorId").get(0);
703             DataproviderObject reply = this.createResult(
704                 request,
705                 "org:opencrx:kernel:base:TestAndSetVisitedByResult"
706             );
707             if(visitorId == null) {
708                 reply.values("visitStatus").add(
709                     new Short JavaDoc((short)2)
710                 );
711             }
712             else if(auditEntry.values("visitedBy").contains(visitorId)) {
713                 reply.values("visitStatus").add(
714                     new Short JavaDoc((short)1)
715                 );
716             }
717             else {
718                 auditEntry.values("visitedBy").add(
719                     visitorId
720                 );
721                 String JavaDoc visitedAt = auditEntry.values("visitedAt").size() > 0
722                     ? (String JavaDoc)auditEntry.values("visitedAt").get(0) + "\n"
723                     : "";
724                 visitedAt += visitorId + ": " + org.openmdx.base.text.format.DateFormat.getInstance().format(new Date JavaDoc());
725                 auditEntry.values("visitedAt").add(
726                     visitedAt
727                 );
728                 super.replace(
729                     header,
730                     new DataproviderRequest(
731                         auditEntry,
732                         DataproviderOperations.OBJECT_REPLACEMENT,
733                         AttributeSelectors.NO_ATTRIBUTES,
734                         null
735                     )
736                 );
737                 reply.values("visitStatus").add(
738                     new Short JavaDoc((short)0)
739                 );
740             }
741             return reply;
742         }
743         // Delegate
744
else {
745             return super.otherOperation(
746                 header,
747                 request,
748                 operation,
749                 replyPath
750             );
751         }
752     }
753     
754     //-----------------------------------------------------------------------
755
private String JavaDoc unitOfWorkId = null;
756     private final Map JavaDoc auditSegments = new HashMap JavaDoc();
757     
758 }
759
760 //--- End of File -----------------------------------------------------------
761
Popular Tags