1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.objects

File BaseProperty.java

 

Coverage histogram

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

Code metrics

42
76
26
1
351
216
51
0.67
2.92
26
1.96

Classes

Class Line # Actions
BaseProperty 44 76 0% 51 41
0.715277871.5%
 

Contributing tests

This file is covered by 155 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: 09891adecc028d61acbcfa03fdab95d7100e975f $
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  21517 toggle @Override
57    protected R createReference()
58    {
59  21516 R reference;
60  21516 if (this.object.getReference() instanceof ObjectReference) {
61  21515 reference = (R) new ObjectPropertyReference(getName(), (ObjectReference) this.object.getReference());
62    } else {
63  0 reference = super.createReference();
64    }
65   
66  21515 return reference;
67    }
68   
 
69  1189726 toggle @Override
70    public BaseCollection getObject()
71    {
72  1189700 return this.object;
73    }
74   
 
75  2618163 toggle @Override
76    public void setObject(BaseCollection object)
77    {
78  2618102 this.object = object;
79    }
80   
 
81  58922 toggle @Override
82    public boolean equals(Object el)
83    {
84    // Same Java object, they sure are equal
85  58922 if (this == el) {
86  1 return true;
87    }
88   
89    // I hate this.. needed for hibernate to find the object
90    // when loading the collections..
91  58921 if ((this.object == null) || ((BaseProperty) el).getObject() == null) {
92  5 return (hashCode() == el.hashCode());
93    }
94   
95  58916 if (!super.equals(el)) {
96  0 return false;
97    }
98   
99  58916 return (getId() == ((BaseProperty) el).getId());
100    }
101   
 
102  270507 toggle @Override
103    public long getId()
104    {
105    // I hate this.. needed for hibernate to find the object
106    // when loading the collections..
107  270507 if (this.object == null) {
108  387 return this.id;
109    } else {
110  270120 return getObject().getId();
111    }
112    }
113   
 
114  96 toggle @Override
115    public void setId(long id)
116    {
117    // I hate this.. needed for hibernate to find the object
118    // when loading the collections..
119  96 this.id = id;
120    }
121   
 
122  10 toggle @Override
123    public int hashCode()
124    {
125    // I hate this.. needed for hibernate to find the object
126    // when loading the collections..
127  10 return ("" + getId() + getName()).hashCode();
128    }
129   
 
130  50488 toggle public String getClassType()
131    {
132  50488 return getClass().getName();
133    }
134   
 
135  16378 toggle public void setClassType(String type)
136    {
137    }
138   
 
139  791154 toggle @Override
140    public BaseProperty<R> clone()
141    {
142  791151 BaseProperty<R> property = (BaseProperty<R>) super.clone();
143   
144  791151 property.ownerDocument = null;
145   
146  791152 cloneInternal(property);
147   
148  791159 property.isValueDirty = this.isValueDirty;
149  791161 property.ownerDocument = this.ownerDocument;
150   
151  791159 property.setObject(getObject());
152   
153  791157 return property;
154    }
155   
156    /**
157    * Subclasses override this to copy values during cloning.
158    *
159    * @param clone The cloned value.
160    */
 
161  0 toggle protected void cloneInternal(BaseProperty clone)
162    {
163    }
164   
 
165  0 toggle public Object getValue()
166    {
167  0 return null;
168    }
169   
 
170  0 toggle public void setValue(Object value)
171    {
172    }
173   
 
174  0 toggle @Override
175    public Element toXML()
176    {
177  0 return super.toXML();
178    }
179   
 
180  1 toggle @Override
181    public String toFormString()
182    {
183  1 return XMLUtils.escape(toText());
184    }
185   
 
186  0 toggle public String toText()
187    {
188  0 Object value = getValue();
189   
190  0 return (value == null) ? "" : value.toString();
191    }
192   
193    /**
194    * Return a XML version of this collection.
195    * <p>
196    * The XML is not formated. to get formatted XML you can use {@link #toXMLString(boolean)} instead.
197    *
198    * @return the XML as a String
199    */
 
200  0 toggle public String toXMLString()
201    {
202  0 return super.toXMLString(true);
203    }
204   
 
205  394 toggle public Object getCustomMappingValue()
206    {
207  394 return getValue();
208    }
209   
 
210  1 toggle @Override
211    public void merge(ElementInterface previousElement, ElementInterface newElement, MergeConfiguration configuration,
212    XWikiContext context, MergeResult mergeResult)
213    {
214  1 super.merge(previousElement, newElement, configuration, context, mergeResult);
215   
216    // Value
217  1 Object previousValue = ((BaseProperty<R>) previousElement).getValue();
218  1 Object newValue = ((BaseProperty<R>) newElement).getValue();
219  1 if (previousValue == null) {
220  0 if (newValue != null) {
221  0 if (getValue() == null) {
222  0 setValue(newValue);
223    } else {
224    // collision between current and new
225  0 mergeResult.getLog().error("Collision found on property [{}] between from value [{}] and to [{}]",
226    getName(), getValue(), newValue);
227    }
228    }
229  1 } else if (newValue == null) {
230  0 if (Objects.equals(previousValue, getValue())) {
231  0 setValue(null);
232    } else {
233    // collision between current and new
234  0 mergeResult.getLog().error("Collision found on property [{}] between from value [{}] and to [{}]",
235    getName(), getValue(), newValue);
236    }
237    } else {
238  1 if (Objects.equals(previousValue, getValue())) {
239  0 setValue(newValue);
240  1 } else if (previousValue.getClass() != newValue.getClass()) {
241    // collision between current and new
242  0 mergeResult.getLog().error("Collision found on property [{}] between from value [] and to []",
243    getName(), getValue(), newValue);
244  1 } else if (!Objects.equals(newValue, getValue())) {
245  1 mergeValue(previousValue, newValue, mergeResult);
246    }
247    }
248    }
249   
250    /**
251    * Try to apply 3 ways merge on property value.
252    *
253    * @param previousValue the previous version of the value
254    * @param newValue the new version of the value
255    * @param mergeResult merge report
256    * @since 3.2M1
257    */
 
258  0 toggle protected void mergeValue(Object previousValue, Object newValue, MergeResult mergeResult)
259    {
260    // collision between current and new: don't know how to apply 3 way merge on unknown type
261  0 mergeResult.getLog().error("Collision found on property [{}] between from value [{}] and to [{}]", getName(),
262    getValue(), newValue);
263    }
264   
 
265  34 toggle @Override
266    public boolean apply(ElementInterface newProperty, boolean clean)
267    {
268  34 boolean modified = super.apply(newProperty, clean);
269   
270  34 BaseProperty<R> newBaseProperty = (BaseProperty<R>) newProperty;
271   
272    // Value
273  34 if (ObjectUtils.notEqual(newBaseProperty.getValue(), getValue())) {
274  3 setValue(newBaseProperty.getValue());
275  3 modified = true;
276    }
277   
278  34 return modified;
279    }
280   
281    /**
282    * @return {@literal true} if the property value doesn't match the value in the database.
283    * @since 4.3M2
284    */
 
285  5 toggle public boolean isValueDirty()
286    {
287  5 return this.isValueDirty;
288    }
289   
290    /**
291    * Set the dirty flag if the new value isn't equal to the old value.
292    *
293    * @param newValue The new value.
294    */
 
295  1820891 toggle protected void setValueDirty(Object newValue)
296    {
297  1820963 if (!this.isValueDirty && !Objects.equals(newValue, getValue())) {
298  15 setValueDirty(true);
299    }
300    }
301   
302    /**
303    * @param valueDirty Indicate if the dirty flag should be set or cleared.
304    * @since 4.3M2
305    */
 
306  37818 toggle public void setValueDirty(boolean valueDirty)
307    {
308  37817 this.isValueDirty = valueDirty;
309  37818 if (valueDirty && this.ownerDocument != null) {
310  5096 this.ownerDocument.setMetaDataDirty(true);
311    }
312    }
313   
314    /**
315    * Set the owner document of this base property.
316    *
317    * @param ownerDocument The owner document.
318    * @since 4.3M2
319    */
 
320  5544423 toggle @Override
321    public void setOwnerDocument(XWikiDocument ownerDocument)
322    {
323  5544445 super.setOwnerDocument(ownerDocument);
324   
325  5544874 if (ownerDocument != null && this.isValueDirty) {
326  3775830 ownerDocument.setMetaDataDirty(true);
327    }
328    }
329   
330    /**
331    * @param xcontext the XWiki Context
332    * @return the definition of the property
333    * @since 8.3M1
334    */
 
335  65190 toggle public PropertyClass getPropertyClass(XWikiContext xcontext)
336    {
337  65189 if (getObject() instanceof BaseObject) {
338  6215 XWikiDocument document = getOwnerDocument();
339  6216 if (document != null) {
340  6216 BaseObject xobject = document.getXObject(getReference().getParent());
341  6215 if (xobject != null) {
342  6215 BaseClass xclass = xobject.getXClass(xcontext);
343   
344  6216 return (PropertyClass) xclass.get(getName());
345    }
346    }
347    }
348   
349  58974 return null;
350    }
351    }