1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package com.xpn.xwiki.objects

File BaseObject.java

 

Coverage histogram

../../../../img/srcFileCovDistChart8.png
56% of files have more coverage

Code metrics

62
118
29
1
428
292
67
0.57
4.07
29
2.31

Classes

Class Line # Actions
BaseObject 44 118 0% 67 52
0.7511961575.1%
 

Contributing tests

This file is covered by 134 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.objects;
21   
22    import java.io.Serializable;
23    import java.util.ArrayList;
24    import java.util.List;
25    import java.util.UUID;
26   
27    import org.apache.commons.lang3.builder.HashCodeBuilder;
28    import org.dom4j.Element;
29    import org.xwiki.model.EntityType;
30    import org.xwiki.model.reference.DocumentReference;
31    import org.xwiki.model.reference.DocumentReferenceResolver;
32    import org.xwiki.model.reference.EntityReference;
33    import org.xwiki.model.reference.SpaceReference;
34   
35    import com.xpn.xwiki.XWikiContext;
36    import com.xpn.xwiki.XWikiException;
37    import com.xpn.xwiki.doc.XWikiDocument;
38    import com.xpn.xwiki.doc.merge.MergeConfiguration;
39    import com.xpn.xwiki.doc.merge.MergeResult;
40    import com.xpn.xwiki.objects.classes.BaseClass;
41    import com.xpn.xwiki.objects.classes.PropertyClass;
42    import com.xpn.xwiki.web.Utils;
43   
 
44    public class BaseObject extends BaseCollection<BaseObjectReference> implements ObjectInterface, Serializable, Cloneable
45    {
46    private String guid;
47   
48    /**
49    * Used to resolve a string into a proper Document Reference using the current document's reference to fill the
50    * blanks, except for the page name for which the default page name is used instead and for the wiki name for which
51    * the current wiki is used instead of the current document reference's wiki.
52    */
53    private DocumentReferenceResolver<String> currentMixedDocumentReferenceResolver2;
54   
 
55  30663 toggle private DocumentReferenceResolver<String> getCurrentMixedDocumentReferenceResolver()
56    {
57  30662 if (this.currentMixedDocumentReferenceResolver2 == null) {
58  30664 this.currentMixedDocumentReferenceResolver2 =
59    Utils.getComponent(DocumentReferenceResolver.TYPE_STRING, "currentmixed");
60    }
61   
62  30662 return this.currentMixedDocumentReferenceResolver2;
63    }
64   
65    /**
66    * {@inheritDoc}
67    * <p>
68    * Note: This method is overridden to add the deprecation warning so that code using it can see it's deprecated.
69    * </p>
70    *
71    * @deprecated since 2.2M2 use {@link #getDocumentReference()}
72    */
 
73  39294 toggle @Deprecated
74    @Override
75    public String getName()
76    {
77  39294 return super.getName();
78    }
79   
80    /**
81    * {@inheritDoc}
82    * <p>
83    * Note: BaseElement.setName() does not support setting reference anymore since 2.4M2.
84    * </p>
85    *
86    * @deprecated since 2.2M2 use {@link #setDocumentReference(org.xwiki.model.reference.DocumentReference)}
87    */
 
88  30665 toggle @Deprecated
89    @Override
90    public void setName(String name)
91    {
92  30664 DocumentReference reference = getDocumentReference();
93   
94  30665 if (reference != null) {
95  2 EntityReference relativeReference = getRelativeEntityReferenceResolver().resolve(name, EntityType.DOCUMENT);
96  2 reference = new DocumentReference(relativeReference.extractReference(EntityType.DOCUMENT).getName(),
97    new SpaceReference(relativeReference.extractReference(EntityType.SPACE).getName(),
98    reference.getParent().getParent()));
99    } else {
100  30663 reference = getCurrentMixedDocumentReferenceResolver().resolve(name);
101    }
102  30666 setDocumentReference(reference);
103    }
104   
 
105  259849 toggle @Override
106    protected BaseObjectReference createReference()
107    {
108  259861 BaseObjectReference reference;
109   
110  259852 if (getXClassReference() != null && getDocumentReference() != null) {
111  259850 reference = new BaseObjectReference(getXClassReference(), getNumber(), getDocumentReference());
112    } else {
113  2 reference = null;
114    }
115   
116  259844 return reference;
117    }
118   
 
119  1171276 toggle @Override
120    public void setNumber(int number)
121    {
122  1171289 super.setNumber(number);
123   
124    // Reset reference cache
125  1171261 this.referenceCache = null;
126    }
127   
 
128  634732 toggle @Override
129    public void setXClassReference(EntityReference xClassReference)
130    {
131  634750 super.setXClassReference(xClassReference);
132   
133    // Reset reference cache
134  634755 this.referenceCache = null;
135    }
136   
 
137  0 toggle public void displayHidden(StringBuffer buffer, String name, String prefix, XWikiContext context)
138    {
139  0 ((PropertyClass) getXClass(context).get(name)).displayHidden(buffer, name, prefix, this, context);
140    }
141   
 
142  0 toggle public void displayView(StringBuffer buffer, String name, String prefix, XWikiContext context)
143    {
144  0 ((PropertyClass) getXClass(context).get(name)).displayView(buffer, name, prefix, this, context);
145    }
146   
 
147  0 toggle public void displayEdit(StringBuffer buffer, String name, String prefix, XWikiContext context)
148    {
149  0 ((PropertyClass) getXClass(context).get(name)).displayEdit(buffer, name, prefix, this, context);
150    }
151   
 
152  0 toggle public String displayHidden(String name, String prefix, XWikiContext context)
153    {
154  0 StringBuffer buffer = new StringBuffer();
155  0 ((PropertyClass) getXClass(context).get(name)).displayHidden(buffer, name, prefix, this, context);
156   
157  0 return buffer.toString();
158    }
159   
 
160  0 toggle public String displayView(String name, String prefix, XWikiContext context)
161    {
162  0 StringBuffer buffer = new StringBuffer();
163  0 ((PropertyClass) getXClass(context).get(name)).displayView(buffer, name, prefix, this, context);
164   
165  0 return buffer.toString();
166    }
167   
 
168  0 toggle public String displayEdit(String name, String prefix, XWikiContext context)
169    {
170  0 StringBuffer buffer = new StringBuffer();
171  0 ((PropertyClass) getXClass(context).get(name)).displayEdit(buffer, name, prefix, this, context);
172   
173  0 return buffer.toString();
174    }
175   
 
176  0 toggle public String displayHidden(String name, XWikiContext context)
177    {
178  0 return displayHidden(name, "", context);
179    }
180   
 
181  0 toggle public String displayView(String name, XWikiContext context)
182    {
183  0 return displayView(name, "", context);
184    }
185   
 
186  0 toggle public String displayEdit(String name, XWikiContext context)
187    {
188  0 return displayEdit(name, "", context);
189    }
190   
 
191  529482 toggle @Override
192    public BaseObject clone()
193    {
194  529495 BaseObject object = (BaseObject) super.clone();
195    // We don't use #getGuid() because we actually want the same value and not generate a new guid when null (which
196    // is expensive)
197  529487 object.setGuid(this.guid);
198   
199  529486 return object;
200    }
201   
202    /**
203    * Similar to {@link #clone()} but whereas a clone is an exact copy (with the same GUID), a duplicate keeps the same
204    * data but with a different identity.
205    *
206    * @since 2.2.3
207    */
 
208  346 toggle public BaseObject duplicate()
209    {
210  346 BaseObject object = clone();
211    // Reset GUID for the duplicate
212  346 object.setGuid(null);
213   
214  346 return object;
215    }
216   
217    /**
218    * @since 2.2.3
219    */
 
220  25 toggle public BaseObject duplicate(DocumentReference documentReference)
221    {
222  25 BaseObject object = duplicate();
223  25 object.setDocumentReference(documentReference);
224  25 return object;
225    }
226   
 
227  1928 toggle @Override
228    public boolean equals(Object obj)
229    {
230    // Same Java object, they sure are equal
231  1928 if (this == obj) {
232  53 return true;
233    }
234   
235  1875 if (!super.equals(obj)) {
236  90 return false;
237    }
238   
239  1785 if (getNumber() != ((BaseObject) obj).getNumber()) {
240  0 return false;
241    }
242   
243  1785 return true;
244    }
245   
 
246  2 toggle @Override
247    public int hashCode()
248    {
249  2 HashCodeBuilder builder = new HashCodeBuilder();
250   
251  2 builder.appendSuper(super.hashCode());
252  2 builder.append(getNumber());
253   
254  2 return builder.toHashCode();
255    }
256   
 
257  0 toggle @Override
258    public void fromXML(Element oel) throws XWikiException
259    {
260  0 super.fromXML(oel);
261    }
262   
 
263  4729 toggle @Override
264    public List<ObjectDiff> getDiff(Object oldEntity, XWikiContext context)
265    {
266  4729 ArrayList<ObjectDiff> difflist = new ArrayList<ObjectDiff>();
267  4729 BaseObject oldObject = (BaseObject) oldEntity;
268    // Iterate over the new properties first, to handle changed and added objects
269  4729 for (String propertyName : this.getPropertyList()) {
270  37510 BaseProperty newProperty = (BaseProperty) this.getField(propertyName);
271  37510 BaseProperty oldProperty = (BaseProperty) oldObject.getField(propertyName);
272  37510 BaseClass bclass = getXClass(context);
273  37510 PropertyClass pclass = (PropertyClass) ((bclass == null) ? null : bclass.getField(propertyName));
274  37510 String propertyType = (pclass == null) ? "" : pclass.getClassType();
275   
276  37510 if (oldProperty == null) {
277    // The property exist in the new object, but not in the old one
278  4597 if ((newProperty != null) && (!newProperty.toText().equals(""))) {
279  814 String newPropertyValue = (newProperty.getValue() instanceof String || pclass == null)
280    ? newProperty.toText() : pclass.displayView(propertyName, this, context);
281  814 difflist.add(new ObjectDiff(getXClassReference(), getNumber(), getGuid(),
282    ObjectDiff.ACTION_PROPERTYADDED, propertyName, propertyType, "", newPropertyValue));
283    }
284  32913 } else if (!oldProperty.toText().equals(((newProperty == null) ? "" : newProperty.toText()))) {
285    // The property exists in both objects and is different
286  807 if (pclass != null) {
287    // Put the values as they would be displayed in the interface
288  802 String newPropertyValue = (newProperty.getValue() instanceof String) ? newProperty.toText()
289    : pclass.displayView(propertyName, this, context);
290  802 String oldPropertyValue = (oldProperty.getValue() instanceof String) ? oldProperty.toText()
291    : pclass.displayView(propertyName, oldObject, context);
292  802 difflist.add(
293    new ObjectDiff(getXClassReference(), getNumber(), getGuid(), ObjectDiff.ACTION_PROPERTYCHANGED,
294    propertyName, propertyType, oldPropertyValue, newPropertyValue));
295    } else {
296    // Cannot get property definition, so use the plain value
297  5 difflist.add(
298    new ObjectDiff(getXClassReference(), getNumber(), getGuid(), ObjectDiff.ACTION_PROPERTYCHANGED,
299    propertyName, propertyType, oldProperty.toText(), newProperty.toText()));
300    }
301    }
302    }
303   
304    // Iterate over the old properties, in case there are some removed properties
305  4729 for (String propertyName : oldObject.getPropertyList()) {
306  33122 BaseProperty newProperty = (BaseProperty) this.getField(propertyName);
307  33122 BaseProperty oldProperty = (BaseProperty) oldObject.getField(propertyName);
308  33122 BaseClass bclass = getXClass(context);
309  33122 PropertyClass pclass = (PropertyClass) ((bclass == null) ? null : bclass.getField(propertyName));
310  33122 String propertyType = (pclass == null) ? "" : pclass.getClassType();
311   
312  33122 if (newProperty == null) {
313    // The property exists in the old object, but not in the new one
314  209 if ((oldProperty != null) && (!oldProperty.toText().equals(""))) {
315  117 if (pclass != null) {
316    // Put the values as they would be displayed in the interface
317  0 String oldPropertyValue = (oldProperty.getValue() instanceof String) ? oldProperty.toText()
318    : pclass.displayView(propertyName, oldObject, context);
319  0 difflist.add(
320    new ObjectDiff(oldObject.getXClassReference(), oldObject.getNumber(), oldObject.getGuid(),
321    ObjectDiff.ACTION_PROPERTYREMOVED, propertyName, propertyType, oldPropertyValue, ""));
322    } else {
323    // Cannot get property definition, so use the plain value
324  117 difflist.add(new ObjectDiff(oldObject.getXClassReference(), oldObject.getNumber(),
325    oldObject.getGuid(), ObjectDiff.ACTION_PROPERTYREMOVED, propertyName, propertyType,
326    oldProperty.toText(), ""));
327    }
328    }
329    }
330    }
331   
332  4729 return difflist;
333    }
334   
 
335  167805 toggle public com.xpn.xwiki.api.Object newObjectApi(BaseObject obj, XWikiContext context)
336    {
337  167807 return new com.xpn.xwiki.api.Object(obj, context);
338    }
339   
 
340  2006 toggle public void set(String fieldname, java.lang.Object value, XWikiContext context)
341    {
342  2006 BaseClass bclass = getXClass(context);
343  2006 PropertyClass pclass = (PropertyClass) bclass.get(fieldname);
344  2006 BaseProperty prop = (BaseProperty) safeget(fieldname);
345  2006 if ((value instanceof String) && (pclass != null)) {
346  1484 prop = pclass.fromString((String) value);
347    } else {
348  522 if ((prop == null) && (pclass != null)) {
349  378 prop = pclass.newProperty();
350    }
351  522 if (prop != null) {
352  522 prop.setValue(value);
353    }
354    }
355   
356  2006 if (prop != null) {
357  2006 prop.setOwnerDocument(getOwnerDocument());
358  2006 safeput(fieldname, prop);
359    }
360    }
361   
362    /**
363    * @return the unique identifier of the object, never null
364    */
 
365  84352 toggle public String getGuid()
366    {
367  84353 if (this.guid == null) {
368  2515 return generateGuid();
369    }
370   
371  81840 return this.guid;
372    }
373   
 
374  2515 toggle private synchronized String generateGuid()
375    {
376  2515 if (this.guid == null) {
377  2515 this.guid = UUID.randomUUID().toString();
378    }
379   
380  2515 return this.guid;
381    }
382   
383    /**
384    * @param guid the unique identifier of the object, if null a new one will be generated
385    */
 
386  600309 toggle public void setGuid(String guid)
387    {
388  600320 this.guid = guid;
389    }
390   
391    /**
392    * Set the owner document of this base object.
393    *
394    * @param ownerDocument The owner document.
395    * @since 4.3M2
396    */
 
397  1631350 toggle @Override
398    public void setOwnerDocument(XWikiDocument ownerDocument)
399    {
400  1631368 super.setOwnerDocument(ownerDocument);
401   
402  1631370 if (this.ownerDocument != null) {
403  1631310 setDocumentReference(this.ownerDocument.getDocumentReference());
404    }
405    }
406   
 
407  0 toggle @Override
408    protected void mergeField(PropertyInterface currentElement, ElementInterface previousElement,
409    ElementInterface newElement, MergeConfiguration configuration, XWikiContext context, MergeResult mergeResult)
410    {
411  0 BaseClass baseClass = getXClass(context);
412  0 if (baseClass != null) {
413  0 PropertyClass propertyClass = (PropertyClass) baseClass.get(currentElement.getName());
414  0 if (propertyClass != null) {
415  0 try {
416  0 propertyClass.mergeProperty((BaseProperty) currentElement, (BaseProperty) previousElement,
417    (BaseProperty) newElement, configuration, context, mergeResult);
418    } catch (Exception e) {
419  0 mergeResult.getLog().error("Failed to merge field [{}]", currentElement.getName(), e);
420    }
421   
422  0 return;
423    }
424    }
425   
426  0 super.mergeField(currentElement, previousElement, newElement, configuration, context, mergeResult);
427    }
428    }