diff --git a/celements-model/src/main/java/com/celements/convert/bean/BeanConverter.java b/celements-model/src/main/java/com/celements/convert/bean/BeanConverter.java
index 1a1ed301d..d1d481ade 100644
--- a/celements-model/src/main/java/com/celements/convert/bean/BeanConverter.java
+++ b/celements-model/src/main/java/com/celements/convert/bean/BeanConverter.java
@@ -1,5 +1,7 @@
package com.celements.convert.bean;
+import java.util.function.Supplier;
+
import javax.validation.constraints.NotNull;
import org.xwiki.component.annotation.ComponentRole;
@@ -9,7 +11,6 @@
import com.celements.common.reflect.ReflectiveInstanceSupplier;
import com.celements.component.ComponentInstanceSupplier;
import com.celements.convert.Converter;
-import com.google.common.base.Supplier;
/**
*
diff --git a/celements-model/src/main/java/com/celements/convert/bean/BeanFieldAccessor.java b/celements-model/src/main/java/com/celements/convert/bean/BeanFieldAccessor.java
index f9fb85146..f585b4927 100644
--- a/celements-model/src/main/java/com/celements/convert/bean/BeanFieldAccessor.java
+++ b/celements-model/src/main/java/com/celements/convert/bean/BeanFieldAccessor.java
@@ -11,7 +11,6 @@
import com.celements.model.classes.fields.ClassField;
import com.celements.model.classes.fields.list.ListField;
-import com.celements.model.field.AbstractFieldAccessor;
import com.celements.model.field.FieldAccessException;
import com.celements.model.field.FieldAccessor;
import com.celements.model.field.FieldMissingException;
@@ -23,7 +22,7 @@
* {{@link #getBeanMethodName(ClassField)} to check expected naming.
*/
@Component(BeanFieldAccessor.NAME)
-public class BeanFieldAccessor extends AbstractFieldAccessor {
+public class BeanFieldAccessor implements FieldAccessor {
private static final Logger LOGGER = LoggerFactory.getLogger(BeanFieldAccessor.class);
diff --git a/celements-model/src/main/java/com/celements/convert/bean/BeanXObjectConverter.java b/celements-model/src/main/java/com/celements/convert/bean/BeanXObjectConverter.java
index 31c88c94d..c53536f73 100644
--- a/celements-model/src/main/java/com/celements/convert/bean/BeanXObjectConverter.java
+++ b/celements-model/src/main/java/com/celements/convert/bean/BeanXObjectConverter.java
@@ -1,5 +1,7 @@
package com.celements.convert.bean;
+import java.util.function.Supplier;
+
import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.annotation.Requirement;
@@ -7,7 +9,6 @@
import com.celements.convert.classes.XObjectDeconverter;
import com.celements.model.field.FieldAccessor;
-import com.google.common.base.Supplier;
import com.xpn.xwiki.objects.BaseObject;
/**
diff --git a/celements-model/src/main/java/com/celements/convert/bean/CelObjectBeanConverter.java b/celements-model/src/main/java/com/celements/convert/bean/CelObjectBeanConverter.java
new file mode 100644
index 000000000..e290f99be
--- /dev/null
+++ b/celements-model/src/main/java/com/celements/convert/bean/CelObjectBeanConverter.java
@@ -0,0 +1,73 @@
+package com.celements.convert.bean;
+
+import static com.google.common.base.Preconditions.*;
+
+import java.util.function.Supplier;
+
+import javax.inject.Inject;
+
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.xwiki.component.annotation.ComponentRole;
+
+import com.celements.common.reflect.ReflectiveInstanceSupplier;
+import com.celements.component.ComponentInstanceSupplier;
+import com.celements.convert.classes.AbstractObjectConverter;
+import com.celements.model.field.CelObjectFieldAccessor;
+import com.celements.model.field.FieldAccessor;
+import com.xpn.xwiki.doc.CelObject;
+
+/** Converts an immutable {@link CelObject} to a bean. */
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class CelObjectBeanConverter extends AbstractObjectConverter implements
+ BeanClassDefConverter {
+
+ private final FieldAccessor celObjectAccessor;
+ private final FieldAccessor beanAccessor;
+ private Supplier supplier;
+
+ @Inject
+ public CelObjectBeanConverter(
+ CelObjectFieldAccessor celObjectAccessor,
+ BeanFieldAccessor beanAccessor) {
+ this.celObjectAccessor = celObjectAccessor;
+ this.beanAccessor = beanAccessor;
+ }
+
+ @Override
+ public void initialize(Supplier instanceSupplier) {
+ supplier = checkNotNull(instanceSupplier);
+ }
+
+ @Override
+ public void initialize(Class token) {
+ checkNotNull(token);
+ initialize(token.isAnnotationPresent(ComponentRole.class)
+ ? new ComponentInstanceSupplier<>(token)
+ : new ReflectiveInstanceSupplier<>(token));
+ }
+
+ @Override
+ public String getName() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public FieldAccessor getFromFieldAccessor() {
+ return celObjectAccessor;
+ }
+
+ @Override
+ public FieldAccessor getToFieldAccessor() {
+ return beanAccessor;
+ }
+
+ @Override
+ protected Supplier getInstanceSupplier() {
+ checkState(supplier != null, "not initialized");
+ return supplier;
+ }
+
+}
diff --git a/celements-model/src/main/java/com/celements/convert/bean/XObjectBeanConverter.java b/celements-model/src/main/java/com/celements/convert/bean/XObjectBeanConverter.java
index afd7a0512..0386a3946 100644
--- a/celements-model/src/main/java/com/celements/convert/bean/XObjectBeanConverter.java
+++ b/celements-model/src/main/java/com/celements/convert/bean/XObjectBeanConverter.java
@@ -2,6 +2,8 @@
import static com.google.common.base.Preconditions.*;
+import java.util.function.Supplier;
+
import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.ComponentRole;
import org.xwiki.component.annotation.InstantiationStrategy;
@@ -11,9 +13,9 @@
import com.celements.common.reflect.ReflectiveInstanceSupplier;
import com.celements.component.ComponentInstanceSupplier;
import com.celements.convert.classes.ClassDefinitionConverter;
-import com.celements.convert.classes.XObjectConverter;
+import com.celements.convert.classes.AbstractObjectConverter;
import com.celements.model.field.FieldAccessor;
-import com.google.common.base.Supplier;
+import com.celements.model.field.XObjectFieldAccessor;
import com.xpn.xwiki.objects.BaseObject;
/**
@@ -22,13 +24,16 @@
*/
@Component(XObjectBeanConverter.NAME)
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
-public class XObjectBeanConverter extends XObjectConverter implements
+public class XObjectBeanConverter extends AbstractObjectConverter implements
BeanClassDefConverter {
public static final String NAME = "xobjectbean";
private Supplier supplier;
+ @Requirement(XObjectFieldAccessor.NAME)
+ private FieldAccessor xObjAccessor;
+
@Requirement(BeanFieldAccessor.NAME)
private FieldAccessor beanAccessor;
@@ -52,6 +57,11 @@ public String getName() {
return NAME;
}
+ @Override
+ public FieldAccessor getFromFieldAccessor() {
+ return xObjAccessor;
+ }
+
@Override
public FieldAccessor getToFieldAccessor() {
return beanAccessor;
diff --git a/celements-model/src/main/java/com/celements/convert/classes/AbstractClassDefConverter.java b/celements-model/src/main/java/com/celements/convert/classes/AbstractClassDefConverter.java
index 65e1d8e52..e017bdc03 100644
--- a/celements-model/src/main/java/com/celements/convert/classes/AbstractClassDefConverter.java
+++ b/celements-model/src/main/java/com/celements/convert/classes/AbstractClassDefConverter.java
@@ -3,6 +3,8 @@
import static com.celements.common.MoreObjectsCel.*;
import static com.google.common.base.Preconditions.*;
+import java.util.function.Supplier;
+
import javax.validation.constraints.NotNull;
import org.slf4j.Logger;
@@ -14,7 +16,6 @@
import com.celements.model.field.FieldAccessException;
import com.celements.model.field.FieldAccessor;
import com.celements.model.field.FieldMissingException;
-import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
public abstract class AbstractClassDefConverter implements ClassDefinitionConverter {
diff --git a/celements-model/src/main/java/com/celements/convert/classes/XObjectConverter.java b/celements-model/src/main/java/com/celements/convert/classes/AbstractObjectConverter.java
similarity index 66%
rename from celements-model/src/main/java/com/celements/convert/classes/XObjectConverter.java
rename to celements-model/src/main/java/com/celements/convert/classes/AbstractObjectConverter.java
index 2641e0a9d..04dcbb46c 100644
--- a/celements-model/src/main/java/com/celements/convert/classes/XObjectConverter.java
+++ b/celements-model/src/main/java/com/celements/convert/classes/AbstractObjectConverter.java
@@ -6,25 +6,14 @@
import com.celements.model.classes.ClassDefinition;
import com.celements.model.classes.fields.ClassField;
-import com.celements.model.field.FieldAccessor;
-import com.celements.model.field.XObjectFieldAccessor;
import com.celements.web.classes.oldcore.XWikiObjectClass;
import com.google.common.collect.ImmutableList;
-import com.xpn.xwiki.objects.BaseObject;
-public abstract class XObjectConverter extends AbstractClassDefConverter {
+public abstract class AbstractObjectConverter extends AbstractClassDefConverter {
@Requirement(XWikiObjectClass.CLASS_DEF_HINT)
private ClassDefinition xObjClassDef;
- @Requirement(XObjectFieldAccessor.NAME)
- private FieldAccessor xObjAccessor;
-
- @Override
- public FieldAccessor getFromFieldAccessor() {
- return xObjAccessor;
- }
-
@Override
protected ImmutableList.Builder> aggregateClassFields(
ImmutableList.Builder> iter) {
diff --git a/celements-model/src/main/java/com/celements/convert/classes/XObjectDeconverter.java b/celements-model/src/main/java/com/celements/convert/classes/XObjectDeconverter.java
index 2fdd0970f..7ca0232f1 100644
--- a/celements-model/src/main/java/com/celements/convert/classes/XObjectDeconverter.java
+++ b/celements-model/src/main/java/com/celements/convert/classes/XObjectDeconverter.java
@@ -1,11 +1,12 @@
package com.celements.convert.classes;
+import java.util.function.Supplier;
+
import org.xwiki.component.annotation.Requirement;
import com.celements.model.field.FieldAccessor;
import com.celements.model.field.XObjectFieldAccessor;
import com.celements.model.object.xwiki.XWikiObjectSupplier;
-import com.google.common.base.Supplier;
import com.xpn.xwiki.objects.BaseObject;
public abstract class XObjectDeconverter extends AbstractClassDefConverter {
diff --git a/celements-model/src/main/java/com/celements/model/access/DefaultModelAccessFacade.java b/celements-model/src/main/java/com/celements/model/access/DefaultModelAccessFacade.java
index 97ba8e9f4..a5ca12069 100644
--- a/celements-model/src/main/java/com/celements/model/access/DefaultModelAccessFacade.java
+++ b/celements-model/src/main/java/com/celements/model/access/DefaultModelAccessFacade.java
@@ -14,9 +14,9 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
+import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
@@ -152,6 +152,11 @@ public Document getApiDocument(XWikiDocument doc) throws NoAccessRightsException
EAccessLevel.VIEW);
}
+ @Override
+ public Optional getCelDocument(DocumentReference docRef) {
+ return getCelDocument(docRef, DEFAULT_LANG);
+ }
+
@Override
public Optional getCelDocument(DocumentReference docRef, String lang) {
checkNotNull(docRef);
@@ -445,28 +450,37 @@ public boolean isTranslation(XWikiDocument doc) {
@Override
public Stream streamParents(XWikiDocument doc) {
- return StreamEx.of(new Iterator() {
+ return streamParents(doc, XWikiDocument::getParentReference, this::getDocumentOpt);
+ }
+
+ @Override
+ public Stream streamParents(CelDocument doc) {
+ return streamParents(doc, CelDocument::getParentReference, this::getCelDocument);
+ }
+
+ private Stream streamParents(D doc,
+ Function parentRef,
+ Function> loader) {
+ return StreamEx.of(new Iterator() {
- private XWikiDocument current = doc;
+ private D current = doc;
private Set seen = new HashSet<>();
@Override
public boolean hasNext() {
- return (current != null)
- && (current.getParentReference() != null)
- && exists(current.getParentReference());
+ return Optional.ofNullable(current)
+ .map(parentRef)
+ .filter(DefaultModelAccessFacade.this::exists)
+ .isPresent();
}
@Override
- public XWikiDocument next() {
- try {
- if (seen.add(current.getParentReference())) {
- return current = getDocument(current.getParentReference());
- } else {
- throw new IllegalStateException("cyclic parent referencing: " + seen);
- }
- } catch (DocumentNotExistsException | NullPointerException exc) {
- throw new NoSuchElementException(exc.getClass().getSimpleName() + " " + exc.getMessage());
+ public D next() {
+ DocumentReference ref = Optional.ofNullable(current).map(parentRef).orElseThrow();
+ if (seen.add(ref)) {
+ return current = loader.apply(ref).orElseThrow();
+ } else {
+ throw new IllegalStateException("cyclic parent referencing: " + seen);
}
}
});
diff --git a/celements-model/src/main/java/com/celements/model/access/IModelAccessFacade.java b/celements-model/src/main/java/com/celements/model/access/IModelAccessFacade.java
index 50b4bbcf1..436c04a55 100644
--- a/celements-model/src/main/java/com/celements/model/access/IModelAccessFacade.java
+++ b/celements-model/src/main/java/com/celements/model/access/IModelAccessFacade.java
@@ -51,6 +51,9 @@ XWikiDocument getDocument(@NotNull DocumentReference docRef, @Nullable String la
@NotNull
Optional getDocumentOpt(@NotNull DocumentReference docRef, @Nullable String lang);
+ @NotNull
+ Optional getCelDocument(@NotNull DocumentReference docRef);
+
@NotNull
Optional getCelDocument(@NotNull DocumentReference docRef,
@Nullable String lang);
@@ -131,6 +134,9 @@ void deleteDocumentWithoutTranslations(@NotNull XWikiDocument doc, boolean totra
@NotNull
Stream streamParents(@NotNull XWikiDocument doc);
+ @NotNull
+ Stream streamParents(@NotNull CelDocument doc);
+
/**
* @deprecated instead use {@link XWikiObjectFetcher}
* @param docRef
diff --git a/celements-model/src/main/java/com/celements/model/field/AbstractDocumentFieldAccessor.java b/celements-model/src/main/java/com/celements/model/field/AbstractDocumentFieldAccessor.java
new file mode 100644
index 000000000..81341f173
--- /dev/null
+++ b/celements-model/src/main/java/com/celements/model/field/AbstractDocumentFieldAccessor.java
@@ -0,0 +1,48 @@
+package com.celements.model.field;
+
+import static com.celements.web.classes.oldcore.XWikiDocumentClass.*;
+import static com.google.common.base.Preconditions.*;
+import static com.google.common.base.Strings.*;
+import static java.text.MessageFormat.*;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.celements.model.classes.fields.ClassField;
+
+public abstract class AbstractDocumentFieldAccessor implements FieldAccessor {
+
+ protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final Optional get(D doc, ClassField field) {
+ checkNotNull(doc);
+ checkField(field);
+ Function getter = getters().get(field.getName());
+ if (getter == null) {
+ throw new FieldAccessException("undefined field: " + field);
+ }
+ Object value = getter.apply(doc);
+ if (value instanceof String) {
+ value = emptyToNull(value.toString().trim());
+ }
+ logger.info("get: '{}' for '{}' from '{}'", value, field, doc);
+ return Optional.ofNullable((V) value);
+ }
+
+ private void checkField(ClassField> field) {
+ checkNotNull(field);
+ if (!CLASS_REF.equals(field.getClassReference())) {
+ throw new FieldAccessException(format("uneligible for [{0}], it is of class [{1}]",
+ CLASS_REF, field.getClassReference()));
+ }
+ }
+
+ protected abstract Map> getters();
+
+}
diff --git a/celements-model/src/main/java/com/celements/model/field/AbstractFieldAccessor.java b/celements-model/src/main/java/com/celements/model/field/AbstractFieldAccessor.java
deleted file mode 100644
index d3962e388..000000000
--- a/celements-model/src/main/java/com/celements/model/field/AbstractFieldAccessor.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.celements.model.field;
-
-import com.celements.model.classes.fields.ClassField;
-
-public abstract class AbstractFieldAccessor implements FieldAccessor {
-
- @Override
- @Deprecated
- public com.google.common.base.Optional getValue(T instance, ClassField field) {
- return com.google.common.base.Optional.fromJavaUtil(get(instance, field));
- }
-
- @Override
- @Deprecated
- public boolean setValue(T instance, ClassField field, V value) {
- return set(instance, field, value);
- }
-
-}
diff --git a/celements-model/src/main/java/com/celements/model/field/AbstractObjectFieldAccessor.java b/celements-model/src/main/java/com/celements/model/field/AbstractObjectFieldAccessor.java
new file mode 100644
index 000000000..f04ccdf73
--- /dev/null
+++ b/celements-model/src/main/java/com/celements/model/field/AbstractObjectFieldAccessor.java
@@ -0,0 +1,80 @@
+package com.celements.model.field;
+
+import static com.celements.web.classes.oldcore.XWikiObjectClass.*;
+import static com.google.common.base.Preconditions.*;
+import static com.google.common.base.Strings.*;
+import static java.text.MessageFormat.*;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xwiki.model.reference.ClassReference;
+
+import com.celements.model.classes.fields.ClassField;
+import com.celements.model.classes.fields.CustomClassField;
+
+public abstract class AbstractObjectFieldAccessor implements FieldAccessor {
+
+ protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Override
+ public final Optional get(O obj, ClassField field) {
+ checkNotNull(obj);
+ checkNotNull(field);
+ Optional value;
+ if (field.getClassReference().equals(CLASS_REF)) {
+ value = Optional.of(getObjectFieldValue(obj, field));
+ } else {
+ checkClassRef(obj, field);
+ value = getRawValue(obj, field.getName())
+ .map(val -> (val instanceof String str) ? emptyToNull(str.trim()) : val)
+ .flatMap(val -> resolvePropertyValue(field, val));
+ }
+ logger.trace("get - obj [{}], field [{}], value [{}]", obj, field, value);
+ return value;
+ }
+
+ protected abstract Optional