Skip to content

Commit 68bb898

Browse files
committed
XWIKI-21417: BaseObject#set always set the metadata dirty flag of the owner doc to true (#4547)
* Only create the property when it doesn't exist in BaseObject#set * Provide unit test (cherry picked from commit 71ad5fa)
1 parent 3908406 commit 68bb898

File tree

2 files changed

+121
-2
lines changed

2 files changed

+121
-2
lines changed

xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/objects/BaseObject.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,18 +466,26 @@ public void set(String fieldname, java.lang.Object value, XWikiContext context)
466466
BaseClass bclass = getXClass(context);
467467
PropertyClass pclass = (PropertyClass) bclass.get(fieldname);
468468
BaseProperty prop = (BaseProperty) safeget(fieldname);
469+
boolean createProp = false;
469470
if ((value instanceof String) && (pclass != null)) {
470-
prop = pclass.fromString((String) value);
471+
BaseProperty newProp = pclass.fromString((String) value);
472+
if (prop == null) {
473+
prop = newProp;
474+
createProp = true;
475+
} else {
476+
prop.setValue(newProp.getValue());
477+
}
471478
} else {
472479
if ((prop == null) && (pclass != null)) {
473480
prop = pclass.newProperty();
481+
createProp = true;
474482
}
475483
if (prop != null) {
476484
prop.setValue(value);
477485
}
478486
}
479487

480-
if (prop != null) {
488+
if (prop != null && createProp) {
481489
prop.setOwnerDocument(getOwnerDocument());
482490
safeput(fieldname, prop);
483491
}

xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/objects/BaseObjectTest.java

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,29 @@
3131
import org.xwiki.store.merge.MergeManagerResult;
3232
import org.xwiki.test.junit5.mockito.MockComponent;
3333

34+
import com.xpn.xwiki.XWikiContext;
35+
import com.xpn.xwiki.XWikiException;
3436
import com.xpn.xwiki.doc.XWikiDocument;
3537
import com.xpn.xwiki.doc.merge.MergeConfiguration;
3638
import com.xpn.xwiki.doc.merge.MergeResult;
39+
import com.xpn.xwiki.objects.classes.BaseClass;
40+
import com.xpn.xwiki.objects.classes.PropertyClass;
3741
import com.xpn.xwiki.test.MockitoOldcore;
3842
import com.xpn.xwiki.test.junit5.mockito.InjectMockitoOldcore;
3943
import com.xpn.xwiki.test.junit5.mockito.OldcoreTest;
4044
import com.xpn.xwiki.test.reference.ReferenceComponentList;
4145

4246
import static org.junit.jupiter.api.Assertions.assertEquals;
47+
import static org.junit.jupiter.api.Assertions.assertFalse;
4348
import static org.junit.jupiter.api.Assertions.assertNotNull;
4449
import static org.junit.jupiter.api.Assertions.assertNotSame;
50+
import static org.junit.jupiter.api.Assertions.assertTrue;
4551
import static org.junit.jupiter.api.Assertions.fail;
4652
import static org.mockito.ArgumentMatchers.any;
4753
import static org.mockito.ArgumentMatchers.eq;
54+
import static org.mockito.Mockito.mock;
55+
import static org.mockito.Mockito.times;
56+
import static org.mockito.Mockito.verify;
4857
import static org.mockito.Mockito.when;
4958

5059
/**
@@ -224,4 +233,106 @@ void cloneWithoutDetach()
224233
assertNotSame(object.getOwnerDocument(), clonedObject.getOwnerDocument());
225234
assertNotNull(clonedObject.getOwnerDocument());
226235
}
236+
237+
@Test
238+
void setString() throws XWikiException
239+
{
240+
DocumentReference documentReference = new DocumentReference("wiki", "space", "document");
241+
DocumentReference classReference = new DocumentReference("wiki", "space", "class");
242+
XWikiDocument classDocument = new XWikiDocument(classReference);
243+
XWikiDocument ownerDocument = new XWikiDocument(new DocumentReference("wiki", "space", "page"));
244+
BaseObject object = new BaseObject();
245+
object.setDocumentReference(documentReference);
246+
object.setXClassReference(classReference);
247+
object.setOwnerDocument(ownerDocument);
248+
249+
XWikiContext context = this.oldcore.getXWikiContext();;
250+
String fieldName = "myField";
251+
String value = "myValue";
252+
253+
BaseClass baseClass = mock(BaseClass.class);
254+
classDocument.setXClass(baseClass);
255+
when(this.oldcore.getSpyXWiki().getDocument(classReference, context)).thenReturn(classDocument);
256+
257+
PropertyClass propertyClass = mock(PropertyClass.class);
258+
when(baseClass.get(fieldName)).thenReturn(propertyClass);
259+
260+
BaseProperty newProp = mock(BaseProperty.class);
261+
when(propertyClass.fromString(value)).thenReturn(newProp);
262+
263+
object.set(fieldName, value, context);
264+
assertTrue(object.isDirty());
265+
assertTrue(ownerDocument.isMetaDataDirty());
266+
verify(newProp, times(2)).setOwnerDocument(ownerDocument);
267+
verify(newProp).setName(fieldName);
268+
verify(newProp).setObject(object);
269+
assertTrue(object.getFieldList().contains(newProp));
270+
271+
ownerDocument.setMetaDataDirty(false);
272+
object.setDirty(false);
273+
274+
// Now the property exists let's call it again
275+
BaseProperty newProp2 = mock(BaseProperty.class);
276+
when(propertyClass.fromString(value)).thenReturn(newProp2);
277+
when(newProp2.getValue()).thenReturn(value);
278+
object.set(fieldName, value, context);
279+
verify(newProp).setValue(value);
280+
assertFalse(object.isDirty());
281+
assertFalse(ownerDocument.isMetaDataDirty());
282+
283+
// no new calls
284+
verify(newProp, times(2)).setOwnerDocument(ownerDocument);
285+
verify(newProp).setName(fieldName);
286+
verify(newProp).setObject(object);
287+
}
288+
289+
@Test
290+
void setObject() throws XWikiException
291+
{
292+
DocumentReference documentReference = new DocumentReference("wiki", "space", "document");
293+
DocumentReference classReference = new DocumentReference("wiki", "space", "class");
294+
XWikiDocument classDocument = new XWikiDocument(classReference);
295+
XWikiDocument ownerDocument = new XWikiDocument(new DocumentReference("wiki", "space", "page"));
296+
BaseObject object = new BaseObject();
297+
object.setDocumentReference(documentReference);
298+
object.setXClassReference(classReference);
299+
object.setOwnerDocument(ownerDocument);
300+
301+
XWikiContext context = this.oldcore.getXWikiContext();;
302+
String fieldName = "myField";
303+
Object value = 4545;
304+
305+
BaseClass baseClass = mock(BaseClass.class);
306+
classDocument.setXClass(baseClass);
307+
when(this.oldcore.getSpyXWiki().getDocument(classReference, context)).thenReturn(classDocument);
308+
309+
PropertyClass propertyClass = mock(PropertyClass.class);
310+
when(baseClass.get(fieldName)).thenReturn(propertyClass);
311+
312+
BaseProperty newProp = mock(BaseProperty.class);
313+
when(propertyClass.newProperty()).thenReturn(newProp);
314+
315+
object.set(fieldName, value, context);
316+
assertTrue(object.isDirty());
317+
assertTrue(ownerDocument.isMetaDataDirty());
318+
verify(newProp).setValue(value);
319+
verify(newProp, times(2)).setOwnerDocument(ownerDocument);
320+
verify(newProp).setName(fieldName);
321+
verify(newProp).setObject(object);
322+
assertTrue(object.getFieldList().contains(newProp));
323+
324+
ownerDocument.setMetaDataDirty(false);
325+
object.setDirty(false);
326+
327+
// Now the property exists let's call it again
328+
object.set(fieldName, value, context);
329+
verify(newProp, times(2)).setValue(value);
330+
assertFalse(object.isDirty());
331+
assertFalse(ownerDocument.isMetaDataDirty());
332+
333+
// no new calls
334+
verify(newProp, times(2)).setOwnerDocument(ownerDocument);
335+
verify(newProp).setName(fieldName);
336+
verify(newProp).setObject(object);
337+
}
227338
}

0 commit comments

Comments
 (0)