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

File BaseProperty.java

 

Coverage histogram

../../../../img/srcFileCovDistChart7.png
66% of files have more coverage

Code metrics

44
78
26
1
355
219
52
0.67
3
26
2

Classes

Class Line # Actions
BaseProperty 44 78 0% 52 43
0.709459570.9%
 

Contributing tests

This file is covered by 207 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.Objects;
24   
25    import org.apache.commons.lang3.ObjectUtils;
26    import org.dom4j.Element;
27    import org.xwiki.model.reference.EntityReference;
28    import org.xwiki.model.reference.ObjectPropertyReference;
29    import org.xwiki.model.reference.ObjectReference;
30    import org.xwiki.xml.XMLUtils;
31   
32    import com.xpn.xwiki.XWikiContext;
33    import com.xpn.xwiki.doc.XWikiDocument;
34    import com.xpn.xwiki.doc.merge.MergeConfiguration;
35    import com.xpn.xwiki.doc.merge.MergeResult;
36    import com.xpn.xwiki.objects.classes.BaseClass;
37    import com.xpn.xwiki.objects.classes.PropertyClass;
38   
39    /**
40    * @version $Id: bf99868fbf0639632a69275e45c5ac29d2656375 $
41    */
42    // TODO: shouldn't this be abstract? toFormString and toText
43    // will never work unless getValue is overriden
 
44    public class BaseProperty<R extends EntityReference> extends BaseElement<R>
45    implements PropertyInterface, Serializable, Cloneable
46    {
47    private BaseCollection object;
48   
49    private long id;
50   
51    /**
52    * Set to true if value is not the same as the database value.
53    */
54    private boolean isValueDirty = true;
55   
 
56  651592 toggle @Override
57    protected R createReference()
58    {
59  651596 R reference;
60  651590 if (this.object.getReference() instanceof ObjectReference) {
61  651593 reference = (R) new ObjectPropertyReference(getName(), (ObjectReference) this.object.getReference());
62    } else {
63  0 reference = super.createReference();
64    }
65   
66  651595 return reference;
67    }
68   
 
69  12921267 toggle @Override
70    public BaseCollection getObject()
71    {
72  12921462 return this.object;
73    }
74   
 
75  24167711 toggle @Override
76    public void setObject(BaseCollection object)
77    {
78  24167205 this.object = object;
79    }
80   
 
81  147207 toggle @Override
82    public boolean equals(Object el)
83    {
84    // Same Java object, they sure are equal
85  147207 if (this == el) {
86  0 return true;
87    }
88   
89  147207 if (el == null) {
90  0 return false;
91    }
92   
93    // I hate this.. needed for hibernate to find the object
94    // when loading the collections..
95  147207 if ((this.object == null) || ((BaseProperty) el).getObject() == null) {
96  5 return (hashCode() == el.hashCode());
97    }
98   
99  147202 if (!super.equals(el)) {
100  1 return false;
101    }
102   
103  147201 return (getId() == ((BaseProperty) el).getId());
104    }
105   
 
106  1648940 toggle @Override
107    public long getId()
108    {
109    // I hate this.. needed for hibernate to find the object
110    // when loading the collections..
111  1649327 if (this.object == null) {
112  8490 return this.id;
113    } else {
114  1640779 return getObject().getId();
115    }
116    }
117   
 
118  2512 toggle @Override
119    public void setId(long id)
120    {
121    // I hate this.. needed for hibernate to find the object
122    // when loading the collections..
123  2512 this.id = id;
124    }
125   
 
126  14 toggle @Override
127    public int hashCode()
128    {
129    // I hate this.. needed for hibernate to find the object
130    // when loading the collections..
131  14 return ("" + getId() + getName()).hashCode();
132    }
133   
 
134  201917 toggle public String getClassType()
135    {
136  201917 return getClass().getName();
137    }
138   
 
139  209001 toggle public void setClassType(String type)
140    {
141    }
142   
 
143  10391809 toggle @Override
144    public BaseProperty<R> clone()
145    {
146  10391824 BaseProperty<R> property = (BaseProperty<R>) super.clone();
147   
148  10391625 property.ownerDocument = null;
149   
150  10391630 cloneInternal(property);
151   
152  10391599 property.isValueDirty = this.isValueDirty;
153  10391686 property.ownerDocument = this.ownerDocument;
154   
155  10391705 property.setObject(getObject());
156   
157  10391531 return property;
158    }
159   
160    /**
161    * Subclasses override this to copy values during cloning.
162    *
163    * @param clone The cloned value.
164    */
 
165  0 toggle protected void cloneInternal(BaseProperty clone)
166    {
167    }
168   
 
169  0 toggle public Object getValue()
170    {
171  0 return null;
172    }
173   
 
174  0 toggle public void setValue(Object value)
175    {
176    }
177   
 
178  0 toggle @Override
179    public Element toXML()
180    {
181  0 return super.toXML();
182    }
183   
 
184  4 toggle @Override
185    public String toFormString()
186    {
187  4 return XMLUtils.escape(toText());
188    }
189   
 
190  0 toggle public String toText()
191    {
192  0 Object value = getValue();
193   
194  0 return (value == null) ? "" : value.toString();
195    }
196   
197    /**
198    * Return a XML version of this collection.
199    * <p>
200    * The XML is not formated. to get formatted XML you can use {@link #toXMLString(boolean)} instead.
201    *
202    * @return the XML as a String
203    */
 
204  0 toggle public String toXMLString()
205    {
206  0 return super.toXMLString(true);
207    }
208   
 
209  8675 toggle public Object getCustomMappingValue()
210    {
211  8675 return getValue();
212    }
213   
 
214  1 toggle @Override
215    public void merge(ElementInterface previousElement, ElementInterface newElement, MergeConfiguration configuration,
216    XWikiContext context, MergeResult mergeResult)
217    {
218  1 super.merge(previousElement, newElement, configuration, context, mergeResult);
219   
220    // Value
221  1 Object previousValue = ((BaseProperty<R>) previousElement).getValue();
222  1 Object newValue = ((BaseProperty<R>) newElement).getValue();
223  1 if (previousValue == null) {
224  0 if (newValue != null) {
225  0 if (getValue() == null) {
226  0 setValue(newValue);
227    } else {
228    // collision between current and new
229  0 mergeResult.getLog().error("Collision found on property [{}] between from value [{}] and to [{}]",
230    getName(), getValue(), newValue);
231    }
232    }
233  1 } else if (newValue == null) {
234  0 if (Objects.equals(previousValue, getValue())) {
235  0 setValue(null);
236    } else {
237    // collision between current and new
238  0 mergeResult.getLog().error("Collision found on property [{}] between from value [{}] and to [{}]",
239    getName(), getValue(), newValue);
240    }
241    } else {
242  1 if (Objects.equals(previousValue, getValue())) {
243  0 setValue(newValue);
244  1 } else if (previousValue.getClass() != newValue.getClass()) {
245    // collision between current and new
246  0 mergeResult.getLog().error("Collision found on property [{}] between from value [] and to []",
247    getName(), getValue(), newValue);
248  1 } else if (!Objects.equals(newValue, getValue())) {
249  1 mergeValue(previousValue, newValue, mergeResult);
250    }
251    }
252    }
253   
254    /**
255    * Try to apply 3 ways merge on property value.
256    *
257    * @param previousValue the previous version of the value
258    * @param newValue the new version of the value
259    * @param mergeResult merge report
260    * @since 3.2M1
261    */
 
262  0 toggle protected void mergeValue(Object previousValue, Object newValue, MergeResult mergeResult)
263    {
264    // collision between current and new: don't know how to apply 3 way merge on unknown type
265  0 mergeResult.getLog().error("Collision found on property [{}] between from value [{}] and to [{}]", getName(),
266    getValue(), newValue);
267    }
268   
 
269  230041 toggle @Override
270    public boolean apply(ElementInterface newProperty, boolean clean)
271    {
272  230041 boolean modified = super.apply(newProperty, clean);
273   
274  230041 BaseProperty<R> newBaseProperty = (BaseProperty<R>) newProperty;
275   
276    // Value
277  230041 if (ObjectUtils.notEqual(newBaseProperty.getValue(), getValue())) {
278  576 setValue(newBaseProperty.getValue());
279  576 modified = true;
280    }
281   
282  230041 return modified;
283    }
284   
285    /**
286    * @return {@literal true} if the property value doesn't match the value in the database.
287    * @since 4.3M2
288    */
 
289  5 toggle public boolean isValueDirty()
290    {
291  5 return this.isValueDirty;
292    }
293   
294    /**
295    * Set the dirty flag if the new value isn't equal to the old value.
296    *
297    * @param newValue The new value.
298    */
 
299  13659033 toggle protected void setValueDirty(Object newValue)
300    {
301  13659094 if (!this.isValueDirty && !Objects.equals(newValue, getValue())) {
302  379 setValueDirty(true);
303    }
304    }
305   
306    /**
307    * @param valueDirty Indicate if the dirty flag should be set or cleared.
308    * @since 4.3M2
309    */
 
310  323354 toggle public void setValueDirty(boolean valueDirty)
311    {
312  323420 this.isValueDirty = valueDirty;
313  323451 if (valueDirty && this.ownerDocument != null) {
314  45063 this.ownerDocument.setMetaDataDirty(true);
315    }
316    }
317   
318    /**
319    * Set the owner document of this base property.
320    *
321    * @param ownerDocument The owner document.
322    * @since 4.3M2
323    */
 
324  52159419 toggle @Override
325    public void setOwnerDocument(XWikiDocument ownerDocument)
326    {
327  52159464 super.setOwnerDocument(ownerDocument);
328   
329  52158429 if (ownerDocument != null && this.isValueDirty) {
330  27765151 ownerDocument.setMetaDataDirty(true);
331    }
332    }
333   
334    /**
335    * @param xcontext the XWiki Context
336    * @return the definition of the property
337    * @since 8.3M1
338    */
 
339  665441 toggle public PropertyClass getPropertyClass(XWikiContext xcontext)
340    {
341  665450 if (getObject() instanceof BaseObject) {
342  598181 XWikiDocument document = getOwnerDocument();
343  598184 if (document != null) {
344  598186 BaseObject xobject = document.getXObject(getReference().getParent());
345  598189 if (xobject != null) {
346  598188 BaseClass xclass = xobject.getXClass(xcontext);
347   
348  598175 return (PropertyClass) xclass.get(getName());
349    }
350    }
351    }
352   
353  67265 return null;
354    }
355    }