Skip to content

Commit

Permalink
Parsing abstractly typed fields (like LocalizableMessageType) without…
Browse files Browse the repository at this point in the history
… the need for xsi:type
  • Loading branch information
mederly committed Dec 5, 2017
1 parent 5737bd5 commit 92c415a
Show file tree
Hide file tree
Showing 19 changed files with 309 additions and 139 deletions.
Expand Up @@ -40,6 +40,8 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Collections.emptySet;

/**
* Used to represent combined definition of structural and auxiliary object classes.
*
Expand Down Expand Up @@ -709,4 +711,14 @@ public boolean isReferenceMarker() {
return structuralObjectClassDefinition.isReferenceMarker();
}

@NotNull
@Override
public Collection<TypeDefinition> getStaticSubTypes() {
return emptySet();
}

@Override
public Integer getInstantiationOrder() {
return null;
}
}
Expand Up @@ -37,6 +37,8 @@
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;
import org.jetbrains.annotations.NotNull;

import static java.util.Collections.emptySet;

/**
* @author semancik
* @author mederly
Expand Down Expand Up @@ -643,4 +645,14 @@ public boolean isShared() {
}
}

@NotNull
@Override
public Collection<TypeDefinition> getStaticSubTypes() {
return emptySet(); // not supported for now (this type itself is not statically defined)
}

@Override
public Integer getInstantiationOrder() {
return null;
}
}
Expand Up @@ -52,6 +52,8 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static java.util.Collections.emptySet;

/**
* @author semancik
*/
Expand Down Expand Up @@ -634,6 +636,12 @@ public PrismContext getPrismContext() {
return originalObjectClassDefinition.getPrismContext();
}

@NotNull
@Override
public Collection<TypeDefinition> getStaticSubTypes() {
return emptySet(); // not supported for now (this type itself is not statically defined)
}

@Nullable
@Override
public Class<?> getCompileTimeClass() {
Expand Down Expand Up @@ -1305,5 +1313,10 @@ public void trimTo(@NotNull Collection<ItemPath> paths) {
public boolean isShared() {
return shared;
}


@Override
public Integer getInstantiationOrder() {
return null;
}

}
Expand Up @@ -147,4 +147,8 @@ public interface ComplexTypeDefinition extends TypeDefinition, LocalDefinitionSt
* USE WITH CARE. Be sure no shared definitions would be affected by this operation!
*/
void trimTo(@NotNull Collection<ItemPath> paths);

default boolean containsItemDefinition(QName itemName) {
return findItemDefinition(itemName) != null;
}
}
Expand Up @@ -197,6 +197,7 @@ public PrismPropertyDefinition createPropertyDefinition(String localName, String
//region Finding definitions

// TODO deduplicate w.r.t. findNamedItemDefinition
// but beware, consider only local definitions!
@Override
public <T extends ItemDefinition> T findItemDefinition(@NotNull QName name, @NotNull Class<T> clazz, boolean caseInsensitive) {
for (ItemDefinition def : getDefinitions()) {
Expand Down Expand Up @@ -442,6 +443,12 @@ public String debugDump(int indent, IdentityHashMap<Definition, Object> seen) {
if (xsdAnyMarker) {
sb.append(",Ma");
}
if (instantiationOrder != null) {
sb.append(",o:").append(instantiationOrder);
}
if (!staticSubTypes.isEmpty()) {
sb.append(",st:").append(staticSubTypes.size());
}
extendDumpHeader(sb);
if (seen.containsKey(this)) {
sb.append(" (already shown)");
Expand Down
Expand Up @@ -163,6 +163,7 @@ default SchemaRegistry getSchemaRegistry() {
// TODO fix this!
Class getTypeClassIfKnown();

// todo suspicious, please investigate and document
Class getTypeClass();

@NotNull
Expand Down
Expand Up @@ -57,6 +57,7 @@ public class PrismConstants {

public static final QName A_PROPERTY_CONTAINER = new QName(NS_ANNOTATION, "container");
public static final QName A_OBJECT = new QName(NS_ANNOTATION, "object");
public static final QName A_INSTANTIATION_ORDER = new QName(NS_ANNOTATION, "instantiationOrder");

public static final QName A_DEFAULT_NAMESPACE = new QName(NS_ANNOTATION, "defaultNamespace");
public static final QName A_IGNORED_NAMESPACE = new QName(NS_ANNOTATION, "ignoredNamespace");
Expand Down
Expand Up @@ -16,9 +16,11 @@

package com.evolveum.midpoint.prism;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.xml.namespace.QName;
import java.util.Collection;

/**
* @author mederly
Expand All @@ -38,4 +40,12 @@ public interface TypeDefinition extends Definition {
*/
@Nullable
QName getSuperType();

/**
* Subtypes - but only these that are a part of the static schema. A little bit experimental. :)
*/
@NotNull
Collection<TypeDefinition> getStaticSubTypes();

Integer getInstantiationOrder();
}
Expand Up @@ -16,8 +16,13 @@

package com.evolveum.midpoint.prism;

import org.jetbrains.annotations.NotNull;

import javax.xml.namespace.QName;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
* @author mederly
Expand All @@ -26,6 +31,8 @@ public abstract class TypeDefinitionImpl extends DefinitionImpl implements TypeD

protected QName superType;
protected Class<?> compileTimeClass;
@NotNull protected final Set<TypeDefinition> staticSubTypes = new HashSet<>();
protected Integer instantiationOrder;

public TypeDefinitionImpl(QName typeName, PrismContext prismContext) {
super(typeName, prismContext);
Expand All @@ -40,6 +47,25 @@ public void setSuperType(QName superType) {
this.superType = superType;
}

@Override
@NotNull
public Collection<TypeDefinition> getStaticSubTypes() {
return staticSubTypes;
}

public void addStaticSubType(TypeDefinition subtype) {
staticSubTypes.add(subtype);
}

@Override
public Integer getInstantiationOrder() {
return instantiationOrder;
}

public void setInstantiationOrder(Integer instantiationOrder) {
this.instantiationOrder = instantiationOrder;
}

@Override
public Class<?> getCompileTimeClass() {
return compileTimeClass;
Expand Down
Expand Up @@ -249,17 +249,17 @@ private XNode marshalXmlTypeToMap(Object bean, SerializationContext ctx) throws
} else {
QName fieldTypeName = inspector.findTypeName(field, getterResult.getClass(), namespace);
Object valueToMarshall;
if (getterResult instanceof JAXBElement){
if (getterResult instanceof JAXBElement) {
valueToMarshall = ((JAXBElement) getterResult).getValue();
elementName = ((JAXBElement) getterResult).getName();
} else{
} else {
valueToMarshall = getterResult;
}
XNode marshaled = marshallValue(valueToMarshall, fieldTypeName, isAttribute, ctx);
// TODO reconcile with setExplioitTypeDeclarationIfNeeded
// TODO reconcile with setExplicitTypeDeclarationIfNeeded
if (!getter.getReturnType().equals(valueToMarshall.getClass()) && getter.getReturnType().isAssignableFrom(valueToMarshall.getClass()) && !(valueToMarshall instanceof Enum)) {
PrismObjectDefinition def = prismContext.getSchemaRegistry().determineDefinitionFromClass(valueToMarshall.getClass());
if (def != null){
TypeDefinition def = prismContext.getSchemaRegistry().findTypeDefinitionByCompileTimeClass(valueToMarshall.getClass(), TypeDefinition.class);
if (def != null) {
QName type = def.getTypeName();
marshaled.setTypeQName(type);
marshaled.setExplicitTypeDeclaration(true);
Expand Down
Expand Up @@ -47,6 +47,8 @@
import java.util.Map.Entry;
import java.util.stream.Collectors;

import static java.util.Collections.emptySet;

/**
* Analogous to PrismUnmarshaller, this class unmarshals atomic values from XNode tree structures.
* Atomic values are values that can be used as property values (i.e. either simple types, or
Expand Down Expand Up @@ -191,7 +193,7 @@ private <T> T unmarshalInternal(@NotNull XNode xnode, @NotNull Class<T> beanClas
*/
private <T> T unmarshallPrimitive(PrimitiveXNode<T> prim, Class<T> beanClass, ParsingContext pc) throws SchemaException {
if (prim.isEmpty()) {
return instantiate(beanClass); // Special case. Just return empty object
return instantiateWithSubtypeGuess(beanClass, emptySet()); // Special case. Just return empty object
}

Field valueField = XNodeProcessorUtil.findXmlValueField(beanClass);
Expand Down Expand Up @@ -260,11 +262,26 @@ private <T> T unmarshalFromMapOrHeteroList(@NotNull XNode mapOrList, @NotNull Cl
throw new SchemaException("SearchFilterType is not supported in combination of heterogeneous list.");
}
} else {
T bean = instantiate(beanClass);
T bean = instantiateWithSubtypeGuess(beanClass, mapOrList);
return unmarshalFromMapOrHeteroListToBean(bean, mapOrList, null, pc);
}
}

private <T> T instantiateWithSubtypeGuess(@NotNull Class<T> beanClass, XNode mapOrList) throws SchemaException {
if (!(mapOrList instanceof MapXNode)) {
return instantiate(beanClass); // guessing is supported only for traditional maps now
}
return instantiateWithSubtypeGuess(beanClass, ((MapXNode) mapOrList).keySet());
}

private <T> T instantiateWithSubtypeGuess(@NotNull Class<T> beanClass, Collection<QName> fields) throws SchemaException {
if (!Modifier.isAbstract(beanClass.getModifiers())) {
return instantiate(beanClass); // non-abstract classes are currently instantiated directly (could be changed)
}
Class<? extends T> subclass = inspector.findMatchingSubclass(beanClass, fields);
return instantiate(subclass);
}

private <T> T instantiate(@NotNull Class<T> beanClass) {
T bean;
try {
Expand Down

0 comments on commit 92c415a

Please sign in to comment.