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

File BaseObjectReference.java

 

Coverage histogram

../../../../img/srcFileCovDistChart9.png
41% of files have more coverage

Code metrics

18
50
12
1
273
124
21
0.42
4.17
12
1.75

Classes

Class Line # Actions
BaseObjectReference 53 50 0% 21 11
0.862586.3%
 

Contributing tests

This file is covered by 89 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.util.regex.Matcher;
23    import java.util.regex.Pattern;
24   
25    import org.xwiki.model.EntityType;
26    import org.xwiki.model.reference.DocumentReference;
27    import org.xwiki.model.reference.DocumentReferenceResolver;
28    import org.xwiki.model.reference.EntityReference;
29    import org.xwiki.model.reference.EntityReferenceSerializer;
30    import org.xwiki.model.reference.ObjectReference;
31    import org.xwiki.model.reference.RegexEntityReference;
32   
33    import com.xpn.xwiki.web.Utils;
34   
35    /**
36    * Object reference implementation for object names generated in {@code className[objectNumber]} format. It provides
37    * helper functions to extract the class name as specified by the caller, and object number.
38    * <p>
39    * Accepted formats for the object name are:
40    * <dl>
41    * <dt>className[objectNumber]
42    * <dd>interpreted as the object of class className with number objectNumber. refers the object returned by
43    * XWikiDocument.getObject(String className, int objectNumber). In this case, className is obtained by calling
44    * {@link #getXClassReference()} and object index by calling {@link #getObjectNumber()}.
45    * <dt>className
46    * <dd>interpreted as the first object of class className. refers the object returned by XWikiDocument.getObject(String
47    * className). In this case, {@link #getObjectNumber()} will return {@code null} and {@code className} is obtained by
48    * calling {@link #getXClassReference()}.
49    * </dl>
50    *
51    * @version $Id: fed7003d97b250de06df7d12f42a6cdb2c3ef337 $
52    */
 
53    public class BaseObjectReference extends ObjectReference
54    {
55    /**
56    * The version identifier for this Serializable class. Increment only if the <i>serialized</i> form of the class
57    * changes.
58    */
59    private static final long serialVersionUID = 1L;
60   
61    /**
62    * Used to match number part of the object reference name.
63    */
64    private static final Pattern NUMBERPATTERN = Pattern.compile("(\\\\*)\\[(\\d*)\\]$");
65   
66    /**
67    * The class reference of this object.
68    */
69    protected DocumentReference xclassReference;
70   
71    /**
72    * The number of this object.
73    */
74    protected Integer objectNumber;
75   
76    /**
77    * True if the name and the metadata (class reference and number) are in sync.
78    */
79    private boolean nameParsed;
80   
81    /**
82    * Constructor which would raise exceptions if the source entity reference does not have the appropriate type or
83    * parent, etc.
84    *
85    * @param reference the raw reference to build this object reference from
86    */
 
87  650558 toggle public BaseObjectReference(EntityReference reference)
88    {
89  650552 super(reference);
90    }
91   
92    /**
93    * Builds an indexed object reference for the object of class {@code className} with index {@code objectNumber} in
94    * the document referenced by {@code parent}.
95    *
96    * @param classReference the name of the class of the object
97    * @param objectNumber the number of the object in the document, or {@code null} if the default object should be
98    * referenced
99    * @param parent reference to the parent document where the object is
100    */
 
101  259931 toggle public BaseObjectReference(DocumentReference classReference, Integer objectNumber, DocumentReference parent)
102    {
103  259925 this((EntityReference) classReference, objectNumber, parent);
104    }
105   
106    /**
107    * Builds an indexed object reference for the object of class {@code className} with index {@code objectNumber} in
108    * the document referenced by {@code parent}.
109    *
110    * @param classReference the name of the class of the object
111    * @param objectNumber the number of the object in the document, or {@code null} if the default object should be
112    * referenced
113    * @param parent reference to the parent document where the object is
114    */
 
115  259930 toggle public BaseObjectReference(EntityReference classReference, Integer objectNumber, DocumentReference parent)
116    {
117  259912 super(toName(classReference, objectNumber, parent), parent);
118   
119  259937 this.xclassReference = resolveClassReference(classReference);
120  259927 this.objectNumber = objectNumber;
121   
122    // Indicate that the name does not need to be parsed
123  259920 this.nameParsed = true;
124    }
125   
126    /**
127    * Clone an BaseObjectReference, but use the specified parent for its new parent.
128    *
129    * @param reference the reference to clone
130    * @param parent the new parent to use
131    * @since 10.8RC1
132    */
 
133  0 toggle public BaseObjectReference(EntityReference reference, EntityReference parent)
134    {
135  0 super(reference, parent);
136    }
137   
138    /**
139    * @param classReference the local reference of the class (e.g. "XWiki.XWikiPreferences")
140    * @return a reference used to match on object reference with the passed xclass
141    * @since 9.4RC1
142    */
 
143  610 toggle public static RegexEntityReference any(String classReference)
144    {
145  610 return any(classReference, null);
146    }
147   
148    /**
149    * @param classReference the local reference of the class (e.g. "XWiki.XWikiPreferences")
150    * @param parent the parent of the object reference
151    * @return a reference used to match on object reference with the passed xclass
152    * @since 9.4RC1
153    */
 
154  698 toggle public static RegexEntityReference any(String classReference, EntityReference parent)
155    {
156  698 return new RegexEntityReference(Pattern.compile("([^:]*:)?" + Pattern.quote(classReference) + "\\[\\d*\\]"),
157    EntityType.OBJECT, parent);
158    }
159   
 
160  259932 toggle private DocumentReference resolveClassReference(EntityReference classReference)
161    {
162  259938 if (classReference instanceof DocumentReference) {
163  259927 return (DocumentReference) classReference;
164    }
165   
166  0 return Utils.<DocumentReferenceResolver<EntityReference>>getComponent(DocumentReferenceResolver.TYPE_REFERENCE)
167    .resolve(classReference, getParent());
168    }
169   
170    /**
171    * Convert provided class reference and object number into object reference name.
172    *
173    * @param classReference the class reference
174    * @param objectNumber the object number
175    * @return the object reference name
176    */
 
177  259923 toggle private static String toName(EntityReference classReference, Integer objectNumber, DocumentReference parent)
178    {
179    // Optimize the reference of the class to avoid useless wiki part in most cases (which also make impossible to
180    // get a local version of the object reference)
181  259931 String name =
182    Utils.<EntityReferenceSerializer<String>>getComponent(EntityReferenceSerializer.TYPE_STRING, "compactwiki")
183    .serialize(classReference, parent);
184   
185  259937 if (objectNumber != null) {
186  259922 StringBuilder builder = new StringBuilder(name);
187  259936 builder.append('[');
188  259932 builder.append(objectNumber);
189  259931 builder.append(']');
190  259931 name = builder.toString();
191    } else {
192  3 Matcher matcher = NUMBERPATTERN.matcher(name);
193  3 if (matcher.find()) {
194  2 if (matcher.group(1).length() % 2 == 0) {
195  2 StringBuilder builder = new StringBuilder(name);
196  2 builder.insert(matcher.start(), '\\');
197  2 name = builder.toString();
198    }
199    }
200    }
201   
202  259921 return name;
203    }
204   
 
205  2031730 toggle private void maybeParseName()
206    {
207  2031744 if (!this.nameParsed) {
208  650564 String name = getName();
209   
210  650561 String classReferenceStr;
211  650561 String objectNumberStr;
212   
213  650563 Matcher matcher = NUMBERPATTERN.matcher(name);
214  650563 if (matcher.find()) {
215  650545 if (matcher.group(1).length() % 2 == 0) {
216  650544 classReferenceStr = name.substring(0, matcher.end(1));
217  650560 objectNumberStr = matcher.group(2);
218    } else {
219  2 classReferenceStr = name;
220  2 objectNumberStr = null;
221    }
222    } else {
223  6 classReferenceStr = name;
224  6 objectNumberStr = null;
225    }
226   
227  650565 this.xclassReference =
228    Utils.<DocumentReferenceResolver<String>>getComponent(DocumentReferenceResolver.TYPE_STRING)
229    .resolve(classReferenceStr, getParent());
230  650565 if (objectNumberStr != null) {
231  650558 this.objectNumber = Integer.valueOf(objectNumberStr);
232    }
233   
234    // Indicate that the name does not need to be parsed
235  650560 this.nameParsed = true;
236    }
237    }
238   
239    /**
240    * @return the reference of the class of this object.
241    */
 
242  691956 toggle public DocumentReference getXClassReference()
243    {
244    // Make sure metadata are in sync with the name
245  691958 maybeParseName();
246   
247  691956 return this.xclassReference;
248    }
249   
250    /**
251    * @return the number of this object among the objects of the same class in the document, as set by the caller in
252    * [objectNumber] format after the class name (i.e. no resolving is done, existence of this object is not
253    * guaranteed). If no number can be parsed (i.e. [number] cannot be parsed) this function returns
254    * {@code null} and object should be interpreted as the first object of this class in the document.
255    */
 
256  1339765 toggle public Integer getObjectNumber()
257    {
258    // Make sure metadata are in sync with the name
259  1339765 maybeParseName();
260   
261  1339775 return this.objectNumber;
262    }
263   
 
264  0 toggle @Override
265    public BaseObjectReference replaceParent(EntityReference newParent)
266    {
267  0 if (newParent == getParent()) {
268  0 return this;
269    }
270   
271  0 return new BaseObjectReference(this, newParent);
272    }
273    }