KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencrx > kernel > layer > application > Cloneable


1 /*
2  * ====================================================================
3  * Project: opencrx, http://www.opencrx.org/
4  * Name: $Id: Cloneable.java,v 1.13 2006/03/21 22:24:41 wfro Exp $
5  * Description: openCRX application plugin (Cloneable)
6  * Revision: $Revision: 1.13 $
7  * Owner: CRIXP AG, Switzerland, http://www.crixp.com
8  * Date: $Date: 2006/03/21 22:24:41 $
9  * ====================================================================
10  *
11  * This software is published under the BSD license
12  * as listed below.
13  *
14  * Copyright (c) 2004-2005, 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.application;
57
58 import java.text.ParseException JavaDoc;
59 import java.util.ArrayList JavaDoc;
60 import java.util.Arrays JavaDoc;
61 import java.util.Date JavaDoc;
62 import java.util.HashSet JavaDoc;
63 import java.util.Iterator JavaDoc;
64 import java.util.List JavaDoc;
65 import java.util.Map JavaDoc;
66 import java.util.Set JavaDoc;
67 import java.util.StringTokenizer JavaDoc;
68
69 import org.openmdx.base.accessor.jmi.cci.RefPackage_1_0;
70 import org.openmdx.base.exception.ServiceException;
71 import org.openmdx.base.text.format.DateFormat;
72 import org.openmdx.compatibility.base.dataprovider.cci.AttributeSelectors;
73 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderObject;
74 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderObject_1_0;
75 import org.openmdx.compatibility.base.dataprovider.cci.Directions;
76 import org.openmdx.compatibility.base.dataprovider.cci.RequestCollection;
77 import org.openmdx.compatibility.base.dataprovider.cci.ServiceHeader;
78 import org.openmdx.compatibility.base.dataprovider.cci.SystemAttributes;
79 import org.openmdx.compatibility.base.marshalling.Marshaller;
80 import org.openmdx.compatibility.base.naming.Path;
81 import org.openmdx.kernel.exception.BasicException;
82 import org.openmdx.model1.accessor.basic.cci.ModelElement_1_0;
83 import org.openmdx.model1.accessor.basic.cci.Model_1_0;
84 import org.openmdx.model1.code.AggregationKind;
85
86 public class Cloneable {
87
88     //-------------------------------------------------------------------------
89
public Cloneable(
90         Model_1_0 model,
91         OpenCrxKernel_1 plugin,
92         RequestCollection delegation,
93         RefPackage_1_0 rootPkg
94     ) {
95         this.model = model;
96         this.delegation = delegation;
97         this.plugin = plugin;
98         this.rootPkg = rootPkg;
99     }
100     
101     //-------------------------------------------------------------------------
102
/**
103      * Model-driven object cloning. Copies the original object to the target
104      * toContainer. If a corresponding marshaller is found, the orginal object
105      * is marshalled before it is written to the target. The target is either
106      * replaced or newly created. If cloneContent=true the operation is recursive,
107      * i.e. the composite objects of original are cloned recursively.
108      */

109     public DataproviderObject cloneAndUpdateReferences(
110         ServiceHeader header,
111         DataproviderObject_1_0 original,
112         Path toContainer,
113         Map JavaDoc objectMarshallers,
114         String JavaDoc referenceFilterAsString,
115         boolean replaceExisting
116     ) throws ServiceException {
117         // Clone object
118
List JavaDoc referenceFilter = referenceFilterAsString == null ? null : new ArrayList JavaDoc();
119         if(referenceFilterAsString != null) {
120             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(referenceFilterAsString, " ;,", false);
121             while(tokenizer.hasMoreTokens()) {
122                 referenceFilter.add(
123                     new Path(original.path().toXri() + "/" + tokenizer.nextToken())
124                 );
125             }
126         }
127         List JavaDoc replacements = new ArrayList JavaDoc();
128         DataproviderObject cloned = this.cloneObject(
129             header,
130             original,
131             toContainer,
132             CLONE_EXCLUDE_ATTRIBUTES,
133             objectMarshallers,
134             referenceFilter,
135             replacements,
136             replaceExisting
137         );
138         // Update references
139
referenceFilter = referenceFilterAsString == null ? null : new ArrayList JavaDoc();
140         if(referenceFilterAsString != null) {
141             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(referenceFilterAsString, " ;,", false);
142             while(tokenizer.hasMoreTokens()) {
143                 referenceFilter.add(
144                     new Path(cloned.path().toXri() + "/" + tokenizer.nextToken())
145                 );
146             }
147         }
148         this.applyReplacements(
149             header,
150             cloned.path(),
151             true,
152             replacements,
153             referenceFilter
154         );
155         return cloned;
156     }
157     
158     //-------------------------------------------------------------------------
159
/**
160      * Model-driven object cloning. Copies the original object to the target
161      * toContainer. If a corresponding marshaller is found, the orginal object
162      * is marshalled before it is written to the target. The target is either
163      * replaced or newly created. If cloneContent=true the operation is recursive,
164      * i.e. the composite objects of original are cloned recursively.
165      */

166     private DataproviderObject cloneObject(
167         ServiceHeader header,
168         DataproviderObject_1_0 original,
169         Path toContainer,
170         Set JavaDoc excludeAttributes,
171         Map JavaDoc objectMarshallers,
172         List JavaDoc referenceFilter,
173         List JavaDoc replacements,
174         boolean replaceExisting
175     ) throws ServiceException {
176         
177         // Clone original
178
String JavaDoc originalType = (String JavaDoc)original.values(SystemAttributes.OBJECT_CLASS).get(0);
179         DataproviderObject clone = null;
180         if((objectMarshallers != null) && (objectMarshallers.get(originalType) != null)) {
181             clone = (DataproviderObject)((Marshaller)objectMarshallers.get(originalType)).marshal(
182                 original
183             );
184         }
185         else {
186             clone = new DataproviderObject(new Path(""));
187             clone.addClones(
188               original,
189               true
190             );
191         }
192         // Remove security settings of original. They will be set automatically
193
// by access control for the clone
194
clone.attributeNames().remove("owningUser");
195         clone.attributeNames().remove("owningGroup");
196         
197         // Cloned object has same qualifier as original in case of replacement.
198
clone.path().setTo(
199             toContainer.getChild(
200                 replaceExisting
201                     ? original.path().getBase()
202                     : original.path().getBase().length() < MANUAL_QUALIFIER_THRESHOLD
203                         ? original.path().getBase()
204                         : this.plugin.getUidAsString()
205             )
206         );
207         // Create ReferenceReplacement. References to cloned objects must be updated
208
DataproviderObject replacement = new DataproviderObject(new Path("xri:@openmdx:*"));
209         replacement.values(SystemAttributes.OBJECT_CLASS).add("org:opencrx:kernel:base:ReferenceReplacement");
210         replacement.values("oldReference").add(
211             new Path((String JavaDoc)original.values(SystemAttributes.OBJECT_IDENTITY).get(0))
212         );
213         replacement.values("newReference").add(clone.path());
214         replacements.add(replacement);
215         // Exclude attributes
216
if(excludeAttributes != null) {
217             clone.attributeNames().removeAll(excludeAttributes);
218         }
219         // Remove unknown and readonly features
220
try {
221             ModelElement_1_0 classDef = this.model.getElement(originalType);
222             for(
223                 Iterator JavaDoc i = clone.attributeNames().iterator();
224                 i.hasNext();
225             ) {
226                 String JavaDoc featureName = (String JavaDoc)i.next();
227                 ModelElement_1_0 featureDef = this.model.getFeatureDef(classDef, featureName, false);
228                 String JavaDoc qualifiedFeatureName = featureDef == null
229                     ? null
230                     : (String JavaDoc)featureDef.values("qualifiedName").get(0);
231                 if(
232                     !(SystemAttributes.OBJECT_CLASS.equals(featureName) || CLONEABLE_READONLY_FEATURES.contains(qualifiedFeatureName)) &&
233                     ((featureDef == null) ||
234                     !((Boolean JavaDoc)featureDef.values("isChangeable").get(0)).booleanValue())
235                 ) {
236                     i.remove();
237                 }
238             }
239         } catch(Exception JavaDoc e) {}
240         
241         // Either replace existing object with clone or create clone as new object
242
if(replaceExisting) {
243             try {
244                 DataproviderObject existing = this.plugin.retrieveObjectForModification(clone.path());
245                 existing.attributeNames().clear();
246                 existing.addClones(clone, true);
247             }
248             catch(ServiceException e) {
249                 // create object if not found
250
if(e.getExceptionCode() == BasicException.Code.NOT_FOUND) {
251                     this.delegation.addCreateRequest(
252                         clone
253                     );
254                 }
255             }
256         }
257         else {
258             this.delegation.addCreateRequest(
259                 clone
260             );
261         }
262         // Clone content (shared and composite)
263
Map JavaDoc references = (Map JavaDoc)this.model.getElement(
264             original.values(SystemAttributes.OBJECT_CLASS).get(0)
265         ).values("reference").get(0);
266         for(
267             Iterator JavaDoc i = references.values().iterator();
268             i.hasNext();
269         ) {
270             ModelElement_1_0 featureDef = (ModelElement_1_0)i.next();
271             ModelElement_1_0 referencedEnd = this.model.getElement(
272                 featureDef.values("referencedEnd").get(0)
273             );
274             boolean referenceIsCompositeAndChangeable =
275                 this.model.isReferenceType(featureDef) &&
276                 AggregationKind.COMPOSITE.equals(referencedEnd.values("aggregation").get(0)) &&
277                 ((Boolean JavaDoc)referencedEnd.values("isChangeable").get(0)).booleanValue();
278             boolean referenceIsShared =
279                 this.model.isReferenceType(featureDef) &&
280                 AggregationKind.SHARED.equals(referencedEnd.values("aggregation").get(0));
281             
282             // Only navigate changeable references which are either 'composite' or 'shared'
283
// Do not navigate references with aggregation 'none'.
284
if(referenceIsCompositeAndChangeable || referenceIsShared) {
285                 String JavaDoc reference = (String JavaDoc)featureDef.values("name").get(0);
286                 Path referencePath = original.path().getChild(reference);
287                 boolean matches = referenceFilter == null;
288                 if(!matches) {
289                     for(
290                         Iterator JavaDoc k = referenceFilter.iterator();
291                         k.hasNext();
292                     ) {
293                         Path f = (Path)k.next();
294                         // Wildcard does only apply for composite references
295
if(referencePath.isLike(f) && (!f.endsWith(new String JavaDoc[]{":*"}) || referenceIsCompositeAndChangeable)) {
296                             matches = true;
297                             break;
298                         }
299                     }
300                 }
301                 if(matches) {
302                     List JavaDoc content = this.delegation.addFindRequest(
303                         original.path().getChild(reference),
304                         null,
305                         AttributeSelectors.ALL_ATTRIBUTES,
306                         0,
307                         Integer.MAX_VALUE,
308                         Directions.ASCENDING
309                     );
310                     for(
311                         Iterator JavaDoc j = content.iterator();
312                         j.hasNext();
313                     ) {
314                         DataproviderObject contained = (DataproviderObject)j.next();
315                         Path containedIdentity = new Path((String JavaDoc)contained.values(SystemAttributes.OBJECT_IDENTITY).get(0));
316                         this.cloneObject(
317                             header,
318                             contained,
319                             // Contained is a composite to original if its access path matches its identity
320
// In this case case add the clone of contained as child of clone. Otherwise
321
// add the clone of contained to its composite parent
322
contained.path().equals(containedIdentity)
323                                 ? clone.path().getChild(reference)
324                                 : containedIdentity.getParent(),
325                             excludeAttributes,
326                             objectMarshallers,
327                             referenceFilter,
328                             replacements,
329                             replaceExisting
330                         );
331                     }
332                 }
333             }
334         }
335         // Clone referenced objects
336
Set JavaDoc referencedObjectIdentities = new HashSet JavaDoc();
337         this.plugin.collectReferencedObjects(
338             original,
339             referenceFilter,
340             referencedObjectIdentities
341         );
342         for(
343             Iterator JavaDoc i = referencedObjectIdentities.iterator();
344             i.hasNext();
345         ) {
346             Path referencedObjectPath = (Path)i.next();
347             DataproviderObject_1_0 referencedObject = null;
348             try {
349                 referencedObject = this.plugin.retrieveObjectFromLocal(header, referencedObjectPath);
350             } catch(Exception JavaDoc e) {}
351             if(referencedObject != null) {
352                 Path newReference =
353                     this.cloneObject(
354                         header,
355                         this.plugin.retrieveObjectFromLocal(header, referencedObjectPath),
356                         referencedObjectPath.getParent(),
357                         excludeAttributes,
358                         objectMarshallers,
359                         referenceFilter,
360                         replacements,
361                         replaceExisting
362                     ).path();
363                 // Create ReferenceReplacement. To references to cloned objects must be updated
364
replacement = new DataproviderObject(new Path("xri:@openmdx:*"));
365                 replacement.values(SystemAttributes.OBJECT_CLASS).add("org:opencrx:kernel:base:ReferenceReplacement");
366                 replacement.values("oldReference").add(referencedObjectPath);
367                 replacement.values("newReference").add(newReference);
368                 replacements.add(replacement);
369             }
370         }
371         return clone;
372     }
373
374     //-------------------------------------------------------------------------
375
public void deleteCompositeAndReferencedObjects(
376         DataproviderObject_1_0 object,
377         String JavaDoc referenceFilterAsString
378     ) throws ServiceException {
379         List JavaDoc referenceFilter = new ArrayList JavaDoc();
380         if(referenceFilterAsString != null) {
381             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(referenceFilterAsString, " ;,", false);
382             while(tokenizer.hasMoreTokens()) {
383                 referenceFilter.add(
384                     new Path(object.path().toXri() + "/" + tokenizer.nextToken())
385                 );
386             }
387         }
388         this.deleteReferencedObjects(
389             object,
390             referenceFilter
391         );
392         // Remove object and all composite objects (even composite not
393
// member of referenceFilter)
394
this.plugin.removeObject(
395             object.path()
396         );
397     }
398     
399     //-------------------------------------------------------------------------
400
private void deleteReferencedObjects(
401         DataproviderObject_1_0 object,
402         List JavaDoc referenceFilter
403     ) throws ServiceException {
404
405         Path objectIdentity = object.path();
406         
407         // Remove composite (and their referenced) objects
408
Map JavaDoc references = (Map JavaDoc)this.model.getElement(
409             object.values(SystemAttributes.OBJECT_CLASS).get(0)
410         ).values("reference").get(0);
411         for(
412             Iterator JavaDoc i = references.values().iterator();
413             i.hasNext();
414         ) {
415             ModelElement_1_0 featureDef = (ModelElement_1_0)i.next();
416             ModelElement_1_0 referencedEnd = this.model.getElement(
417                 featureDef.values("referencedEnd").get(0)
418             );
419             if(
420                 this.model.isReferenceType(featureDef) &&
421                 AggregationKind.COMPOSITE.equals(referencedEnd.values("aggregation").get(0))
422             ) {
423                 String JavaDoc reference = (String JavaDoc)featureDef.values("name").get(0);
424                 Path referencePath = objectIdentity.getChild(reference);
425                 boolean matches = referenceFilter == null;
426                 if(!matches) {
427                     for(
428                         Iterator JavaDoc k = referenceFilter.iterator();
429                         k.hasNext();
430                     ) {
431                         if(referencePath.isLike((Path)k.next())) {
432                             matches = true;
433                             break;
434                         }
435                     }
436                 }
437                 if(matches) {
438                     List JavaDoc content = this.delegation.addFindRequest(
439                         objectIdentity.getChild(reference),
440                         null,
441                         AttributeSelectors.ALL_ATTRIBUTES,
442                         0,
443                         Integer.MAX_VALUE,
444                         Directions.ASCENDING
445                     );
446                     for(
447                         Iterator JavaDoc j = content.iterator();
448                         j.hasNext();
449                     ) {
450                         DataproviderObject_1_0 composite = (DataproviderObject_1_0)j.next();
451                         this.deleteReferencedObjects(
452                             composite,
453                             referenceFilter
454                         );
455                     }
456                 }
457             }
458         }
459         
460         // Remove referenced objects
461
Set JavaDoc referencedObjectPaths = new HashSet JavaDoc();
462         this.plugin.collectReferencedObjects(
463             object,
464             referenceFilter,
465             referencedObjectPaths
466         );
467         for(
468             Iterator JavaDoc i = referencedObjectPaths.iterator();
469             i.hasNext();
470         ) {
471             Path referencedObject = (Path)i.next();
472             try {
473                 this.plugin.removeObject(
474                     referencedObject
475                 );
476             }
477             // Don't care if removal of referenced objects fails
478
catch(ServiceException e) {}
479         }
480     }
481     
482     //-------------------------------------------------------------------------
483
public int applyReplacements(
484         ServiceHeader header,
485         Path objectIdentity,
486         boolean isChangeable,
487         List JavaDoc replacements,
488         String JavaDoc referenceFilterAsString
489     ) throws ServiceException {
490         List JavaDoc referenceFilter = new ArrayList JavaDoc();
491         if(referenceFilterAsString != null) {
492             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(referenceFilterAsString, " ;,", false);
493             while(tokenizer.hasMoreTokens()) {
494                 referenceFilter.add(
495                     new Path(objectIdentity.toXri() + "/" + tokenizer.nextToken())
496                 );
497             }
498         }
499         return this.applyReplacements(
500             header,
501             objectIdentity,
502             isChangeable,
503             replacements,
504             referenceFilter
505         );
506     }
507     
508     //-------------------------------------------------------------------------
509
/**
510      * Applies the replacements to object and its content including the referenced
511      * objects specified by the reference filter.
512      *
513      * @param isChangeable object is changeable. Replacements are applied to changeble
514      * objects only.
515      * @param replacements list of TemplateReplacement
516      * @param baseValues map of 'basedOn' attribute names/values.
517      * @return number of replacements
518      */

519     private int applyReplacements(
520         ServiceHeader header,
521         Path objectIdentity,
522         boolean isChangeable,
523         List JavaDoc replacements,
524         List JavaDoc referenceFilter
525     ) throws ServiceException {
526
527         int numberOfReplacements = 0;
528         DataproviderObject_1_0 object = null;
529         try {
530             object = this.plugin.retrieveObjectFromLocal(header, objectIdentity);
531         } catch(Exception JavaDoc e) {}
532         if(object == null) return 0;
533         
534         if(isChangeable) {
535             DataproviderObject replacedObject = null;
536             for(
537                 Iterator JavaDoc i = object.attributeNames().iterator();
538                 i.hasNext();
539             ) {
540                 String JavaDoc name = (String JavaDoc)i.next();
541                 Object JavaDoc oldValue = object.values(name).get(0);
542                 Object JavaDoc newValue = null;
543                 for(
544                     Iterator JavaDoc j = replacements.iterator();
545                     j.hasNext();
546                 ) {
547                     DataproviderObject_1_0 replacement = (DataproviderObject_1_0)j.next();
548                     String JavaDoc replacementType = (String JavaDoc)replacement.values(SystemAttributes.OBJECT_CLASS).get(0);
549                     // matches?
550
boolean matches = replacement.getValues("name") != null
551                         ? replacement.values("name").contains(name)
552                         : true;
553                     // StringReplacement
554
if(
555                         matches &&
556                         (oldValue instanceof String JavaDoc) &&
557                         "org:opencrx:kernel:base:StringReplacement".equals(replacementType)
558                     ) {
559                         matches &= (replacement.getValues("oldString") != null) && (replacement.getValues("oldString").size() > 0)
560                             ? oldValue.equals(replacement.values("oldString").get(0))
561                             : true;
562                         newValue = replacement.values("newString").get(0);
563                     }
564                     // number
565
else if(
566                         matches &&
567                         (oldValue instanceof Comparable JavaDoc) &&
568                         "org:opencrx:kernel:base:NumberReplacement".equals(replacementType)
569                     ) {
570                         matches &= (replacement.getValues("oldNumber") != null) && (replacement.getValues("oldNumber").size() > 0)
571                             ? ((Comparable JavaDoc)oldValue).compareTo(replacement.values("oldNumber").get(0)) == 0
572                             : true;
573                         newValue = replacement.values("newNumber").get(0);
574                     }
575                     // DateTimeReplacement
576
else if(
577                         matches &&
578                         "org:opencrx:kernel:base:DateTimeReplacement".equals(replacementType)
579                     ) {
580                         matches &= (replacement.getValues("oldDateTime") != null) && (replacement.getValues("oldDateTime").size() > 0)
581                             ? oldValue.equals(replacement.values("oldDateTime").get(0))
582                             : true;
583                         if(
584                             (replacement.getValues("baseDateTime") != null) &&
585                             (replacement.values("baseDateTime").size() > 0)
586                         ) {
587                             try {
588                                 DateFormat dateFormat = DateFormat.getInstance();
589                                 Date JavaDoc baseDate = dateFormat.parse((String JavaDoc)replacement.values("baseDateTime").get(0));
590                                 Date JavaDoc oldDate = dateFormat.parse((String JavaDoc)oldValue);
591                                 Date JavaDoc newDate = dateFormat.parse((String JavaDoc)replacement.values("newDateTime").get(0));
592                                 newValue = dateFormat.format(new Date JavaDoc(newDate.getTime() + (oldDate.getTime() - baseDate.getTime())));
593                             }
594                             catch(ParseException JavaDoc e) {
595                                 newValue = replacement.values("newDateTime").get(0);
596                             }
597                         }
598                         else {
599                             newValue = replacement.values("newDateTime").get(0);
600                         }
601                     }
602                     // BooleanReplacement
603
else if(
604                         matches &&
605                         (oldValue instanceof Boolean JavaDoc) &&
606                         "org:opencrx:kernel:base:BooleanReplacement".equals(replacementType)
607                     ) {
608                         matches &= (replacement.getValues("oldBoolean") != null) && (replacement.getValues("oldBoolean").size() > 0)
609                             ? oldValue.equals(replacement.values("oldBoolean").get(0))
610                             : true;
611                         newValue = replacement.values("newBoolean").get(0);
612                     }
613                     // ReferenceReplacement
614
else if(
615                         matches &&
616                         (oldValue instanceof Path) &&
617                         "org:opencrx:kernel:base:ReferenceReplacement".equals(replacementType)
618                     ) {
619                         matches &= (replacement.getValues("oldReference") != null) && (replacement.getValues("oldReference").size() > 0)
620                             ? oldValue.equals(replacement.values("oldReference").get(0))
621                             : true;
622                         newValue = replacement.values("newReference").get(0);
623                     }
624                     else {
625                         matches = false;
626                     }
627                     // Replace
628
if(matches) {
629                         if(replacedObject == null) {
630                             replacedObject = this.plugin.retrieveObjectForModification(object.path());
631                         }
632                         replacedObject.clearValues(name);
633                         if(newValue != null) {
634                             replacedObject.values(name).add(newValue);
635                             numberOfReplacements++;
636                         }
637                     }
638                 }
639             }
640         }
641             
642         // Apply replacements to composite objects
643
Map JavaDoc references = (Map JavaDoc)this.model.getElement(
644             object.values(SystemAttributes.OBJECT_CLASS).get(0)
645         ).values("reference").get(0);
646         for(
647             Iterator JavaDoc i = references.values().iterator();
648             i.hasNext();
649         ) {
650             ModelElement_1_0 featureDef = (ModelElement_1_0)i.next();
651             ModelElement_1_0 referencedEnd = this.model.getElement(
652                 featureDef.values("referencedEnd").get(0)
653             );
654             boolean referenceIsCompositeAndChangeable =
655                 this.model.isReferenceType(featureDef) &&
656                 AggregationKind.COMPOSITE.equals(referencedEnd.values("aggregation").get(0)) &&
657                 ((Boolean JavaDoc)referencedEnd.values("isChangeable").get(0)).booleanValue();
658             boolean referenceIsSharedAndChangeable =
659                 this.model.isReferenceType(featureDef) &&
660                 AggregationKind.SHARED.equals(referencedEnd.values("aggregation").get(0)) &&
661                 ((Boolean JavaDoc)referencedEnd.values("isChangeable").get(0)).booleanValue();
662             // Only navigate changeable references which are either 'composite' or 'shared'
663
// Do not navigate references with aggregation 'none'.
664
if(referenceIsCompositeAndChangeable || referenceIsSharedAndChangeable) {
665                 String JavaDoc reference = (String JavaDoc)featureDef.values("name").get(0);
666                 Path referencePath = objectIdentity.getChild(reference);
667                 boolean matches = referenceFilter == null;
668                 if(!matches) {
669                     for(
670                         Iterator JavaDoc k = referenceFilter.iterator();
671                         k.hasNext();
672                     ) {
673                         if(referencePath.isLike((Path)k.next())) {
674                             matches = true;
675                             break;
676                         }
677                     }
678                 }
679                 if(matches) {
680                     List JavaDoc content = this.delegation.addFindRequest(
681                         objectIdentity.getChild(reference),
682                         null,
683                         AttributeSelectors.ALL_ATTRIBUTES,
684                         0,
685                         Integer.MAX_VALUE,
686                         Directions.ASCENDING
687                     );
688                     for(
689                         Iterator JavaDoc j = content.iterator();
690                         j.hasNext();
691                     ) {
692                         DataproviderObject_1_0 composite = (DataproviderObject_1_0)j.next();
693                         numberOfReplacements += this.applyReplacements(
694                             header,
695                             composite.path(),
696                             ((Boolean JavaDoc)referencedEnd.values("isChangeable").get(0)).booleanValue(),
697                             replacements,
698                             referenceFilter
699                         );
700                     }
701                 }
702             }
703         }
704         
705         // In addition apply replacement to referenced objects
706
Set JavaDoc referencedObjectPaths = new HashSet JavaDoc();
707         this.plugin.collectReferencedObjects(
708             object,
709             referenceFilter,
710             referencedObjectPaths
711         );
712         for(
713             Iterator JavaDoc i = referencedObjectPaths.iterator();
714             i.hasNext();
715         ) {
716             numberOfReplacements += this.applyReplacements(
717                 header,
718                 (Path)i.next(),
719                 true,
720                 replacements,
721                 referenceFilter
722             );
723         }
724         return numberOfReplacements;
725     }
726     
727     //-------------------------------------------------------------------------
728
// Variables
729
//-------------------------------------------------------------------------
730
public static final Set JavaDoc CLONE_EXCLUDE_ATTRIBUTES =
731         new HashSet JavaDoc(Arrays.asList(new String JavaDoc[]{"activityNumber"}));
732     
733     public static final Set JavaDoc CLONEABLE_READONLY_FEATURES =
734         new HashSet JavaDoc(Arrays.asList(new String JavaDoc[]{
735             "org:opencrx:kernel:product1:ProductOfferingPosition:basedOn",
736             "org:opencrx:kernel:product1:ProductBundlePosition:basedOn",
737             "org:opencrx:kernel:product1:BundledProductPosition:basedOn",
738             "org:opencrx:kernel:contract1:ContractPosition:lineItemNumber",
739             "org:opencrx:kernel:account1:AbstractAccount:fullName",
740             "org:opencrx:kernel:product1:ProductConfigurationSet:configType",
741             "org:opencrx:kernel:product1:ProductConfiguration:configType"
742         }));
743     
744     public static final int MANUAL_QUALIFIER_THRESHOLD = 10;
745     
746     private final Model_1_0 model;
747     private final RequestCollection delegation;
748     private final OpenCrxKernel_1 plugin;
749     private final RefPackage_1_0 rootPkg;
750 }
751
752 //--- End of File -----------------------------------------------------------
753
Popular Tags