Skip to content

Commit

Permalink
Merge branch 'master' of github.com:Evolveum/midpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Jun 23, 2015
2 parents bf9df41 + 93e14da commit e6ddebc
Show file tree
Hide file tree
Showing 93 changed files with 3,686 additions and 676 deletions.
Expand Up @@ -331,9 +331,11 @@ protected String debugDump(int indent, LayerType layer) {
for (int i = 0; i < indent; i++) {
sb.append(INDENT_STRING);
}
sb.append(getDebugDumpClassName()).append("(");
sb.append(getDebugDumpClassName()).append(": ");
sb.append(SchemaDebugUtil.prettyPrint(getTypeName()));
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "structural", structuralObjectClassDefinition, indent + 1);
sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "auxiliary", auxiliaryObjectClassDefinitions, indent + 1);
return sb.toString();
}
Expand All @@ -353,4 +355,19 @@ public String getHumanReadableName() {
return getKind()+":"+getIntent();
}
}

@Override
public String toString() {
if (auxiliaryObjectClassDefinitions == null || auxiliaryObjectClassDefinitions.isEmpty()) {
return getDebugDumpClassName() + " ("+getTypeName()+")";
} else {
StringBuilder sb = new StringBuilder();
sb.append(getDebugDumpClassName()).append("(").append(getTypeName());
for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition: auxiliaryObjectClassDefinitions) {
sb.append("+").append(auxiliaryObjectClassDefinition.getTypeName());
}
sb.append(")");
return sb.toString();
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014 Evolveum
* Copyright (c) 2014-2015 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -61,8 +61,12 @@ public ShadowKindType getKind() {
public Collection<String> getIntents() {
return resourceObjectAssociationType.getIntent();
}

public QName getAuxiliaryObjectClass() {
return resourceObjectAssociationType.getAuxiliaryObjectClass();
}

public MappingType getOutboundMappingType() {
public MappingType getOutboundMappingType() {
return resourceObjectAssociationType.getOutbound();
}

Expand Down
Expand Up @@ -253,6 +253,18 @@ public Collection<? extends QName> getNamesOfAssociationsWithOutboundExpressions
public Collection<RefinedObjectClassDefinition> getAuxiliaryObjectClassDefinitions() {
return auxiliaryObjectClassDefinitions;
}

public boolean hasAuxiliaryObjectClass(QName expectedObjectClassName) {
if (auxiliaryObjectClassDefinitions == null) {
return false;
}
for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition: auxiliaryObjectClassDefinitions) {
if (auxiliaryObjectClassDefinition.getTypeName().equals(expectedObjectClassName)) {
return true;
}
}
return false;
}

public Collection<ResourceObjectPattern> getProtectedObjectPatterns() {
if (protectedObjectPatterns == null) {
Expand Down Expand Up @@ -445,6 +457,9 @@ static RefinedObjectClassDefinition parse(ResourceObjectTypeDefinitionType entTy
kind = ShadowKindType.ACCOUNT;
}
String intent = entTypeDefType.getIntent();
if (intent == null) {
intent = SchemaConstants.INTENT_DEFAULT;
}
RefinedObjectClassDefinition rObjectClassDef = parseRefinedObjectClass(entTypeDefType,
resourceType, rSchema, prismContext, kind, intent, kind.value(), kind.value() + " type definition '"+intent+"' in " + contextDescription);

Expand Down Expand Up @@ -500,7 +515,7 @@ static RefinedObjectClassDefinition parseFromSchema(ObjectClassComplexTypeDefini
RefinedObjectClassDefinition rOcDef = new RefinedObjectClassDefinition(prismContext, resourceType, objectClassDef);

String intent = objectClassDef.getIntent();
if (intent == null) {
if (intent == null && objectClassDef.isDefaultInAKind()) {
intent = SchemaConstants.INTENT_DEFAULT;
}
rOcDef.setIntent(intent);
Expand Down Expand Up @@ -613,6 +628,9 @@ private static RefinedObjectClassDefinition parseRefinedObjectClass(ResourceObje
}

public void parseAssociations(RefinedResourceSchema rSchema) throws SchemaException {
if (schemaHandlingObjectTypeDefinitionType == null) {
return;
}
for (ResourceObjectAssociationType resourceObjectAssociationType: schemaHandlingObjectTypeDefinitionType.getAssociation()) {
RefinedAssociationDefinition rAssocDef = new RefinedAssociationDefinition(resourceObjectAssociationType);
ShadowKindType assocKind = rAssocDef.getKind();
Expand All @@ -623,6 +641,9 @@ public void parseAssociations(RefinedResourceSchema rSchema) throws SchemaExcept
}

public void parseAuxiliaryObjectClasses(RefinedResourceSchema rSchema) throws SchemaException {
if (schemaHandlingObjectTypeDefinitionType == null) {
return;
}
List<QName> auxiliaryObjectClassQNames = schemaHandlingObjectTypeDefinitionType.getAuxiliaryObjectClass();
auxiliaryObjectClassDefinitions = new ArrayList<>(auxiliaryObjectClassQNames.size());
for (QName auxiliaryObjectClassQName: auxiliaryObjectClassQNames) {
Expand Down
Expand Up @@ -110,7 +110,10 @@ public RefinedObjectClassDefinition getRefinedDefinition(ShadowKindType kind, St
if (intent == null && acctDef.isDefault()) {
return acctDef;
}
if (acctDef.getIntent().equals(intent)) {
if (acctDef.getIntent() != null && acctDef.getIntent().equals(intent)) {
return acctDef;
}
if (acctDef.getIntent() == null && intent == null) {
return acctDef;
}
}
Expand Down Expand Up @@ -138,36 +141,35 @@ public CompositeRefinedObjectClassDefinition determineCompositeObjectClassDefini
ShadowType shadowType = shadow.asObjectable();

RefinedObjectClassDefinition structuralObjectClassDefinition = null;
Collection<RefinedObjectClassDefinition> auxiliaryObjectClassDefinitions;
ShadowKindType kind = shadowType.getKind();
String intent = shadowType.getIntent();
QName structuralObjectClassQName = shadowType.getObjectClass();

if (kind != null) {
structuralObjectClassDefinition = getRefinedDefinition(kind, intent);
}
}

if (structuralObjectClassDefinition == null) {
// Fallback to objectclass only
if (structuralObjectClassQName == null) {
return null;
}
structuralObjectClassDefinition = getRefinedDefinition(structuralObjectClassQName);
List<QName> auxiliaryObjectClassQNames = shadowType.getAuxiliaryObjectClass();
auxiliaryObjectClassDefinitions = new ArrayList<>(auxiliaryObjectClassQNames.size());
for (QName auxiliaryObjectClassQName: auxiliaryObjectClassQNames) {
RefinedObjectClassDefinition auxiliaryObjectClassDef = getRefinedDefinition(auxiliaryObjectClassQName);
if (auxiliaryObjectClassDef == null) {
throw new SchemaException("Auxiliary object class "+auxiliaryObjectClassQName+" specified in "+shadow+" does not exist");
}
auxiliaryObjectClassDefinitions.add(auxiliaryObjectClassDef);
}
} else {
auxiliaryObjectClassDefinitions = structuralObjectClassDefinition.getAuxiliaryObjectClassDefinitions();
}

if (structuralObjectClassDefinition == null) {
return null;
}

return null;
}
List<QName> auxiliaryObjectClassQNames = shadowType.getAuxiliaryObjectClass();
Collection<RefinedObjectClassDefinition> auxiliaryObjectClassDefinitions = new ArrayList<>(auxiliaryObjectClassQNames.size());
for (QName auxiliaryObjectClassQName: auxiliaryObjectClassQNames) {
RefinedObjectClassDefinition auxiliaryObjectClassDef = getRefinedDefinition(auxiliaryObjectClassQName);
if (auxiliaryObjectClassDef == null) {
throw new SchemaException("Auxiliary object class "+auxiliaryObjectClassQName+" specified in "+shadow+" does not exist");
}
auxiliaryObjectClassDefinitions.add(auxiliaryObjectClassDef);
}

return new CompositeRefinedObjectClassDefinition(structuralObjectClassDefinition, auxiliaryObjectClassDefinitions);
}

Expand Down Expand Up @@ -405,6 +407,13 @@ public static RefinedResourceSchema parse(ResourceType resourceType, PrismContex
parseObjectTypesFromSchema(rSchema, resourceType, prismContext,
"definition of "+resourceType);

// We need to parse associations and auxiliary object classes in a second pass. We need to have all object classes parsed before correctly setting association
// targets
for (RefinedObjectClassDefinition rOcDef: rSchema.getRefinedDefinitions()) {
rOcDef.parseAssociations(rSchema);
rOcDef.parseAuxiliaryObjectClasses(rSchema);
}

return rSchema;
}

Expand Down Expand Up @@ -442,24 +451,17 @@ private static void parseObjectTypeDefsFromSchemaHandling(RefinedResourceSchema

rSchema.add(rOcDef);
}

// We need to parse associations and auxiliary object classes in a second pass. We need to have all object classes parsed before correctly setting association
// targets
for (RefinedObjectClassDefinition rOcDef: rSchema.getRefinedDefinitions()) {
rOcDef.parseAssociations(rSchema);
rOcDef.parseAuxiliaryObjectClasses(rSchema);
}
}

private static void parseObjectTypesFromSchema(RefinedResourceSchema rSchema, ResourceType resourceType,
PrismContext prismContext, String contextDescription) throws SchemaException {

RefinedObjectClassDefinition rAccountDefDefault = null;
for(ObjectClassComplexTypeDefinition objectClassDef: rSchema.getOriginalResourceSchema().getObjectClassDefinitions()) {
if (rSchema.getRefinedDefinition(objectClassDef.getTypeName()) != null) {
QName objectClassname = objectClassDef.getTypeName();
if (rSchema.getRefinedDefinition(objectClassname) != null) {
continue;
}
QName objectClassname = objectClassDef.getTypeName();
RefinedObjectClassDefinition rOcDef = RefinedObjectClassDefinition.parseFromSchema(objectClassDef, resourceType, rSchema, prismContext,
"object class " + objectClassname + ", in " + contextDescription);

Expand Down
Expand Up @@ -268,6 +268,19 @@ public Collection<T> union() {
return MiscUtil.union(zeroSet, plusSet, minusSet);
}

public T getAnyValue() {
if (zeroSet != null && !zeroSet.isEmpty()) {
return zeroSet.iterator().next();
}
if (plusSet != null && !plusSet.isEmpty()) {
return plusSet.iterator().next();
}
if (minusSet != null && !minusSet.isEmpty()) {
return minusSet.iterator().next();
}
return null;
}

public Collection<T> getAllValues() {
Collection<T> allValues = new ArrayList<T>(size());
addAllValuesSet(allValues, zeroSet);
Expand Down
Expand Up @@ -100,19 +100,6 @@ public Class<?> getRealValueClass() {
}
}

private V getAnyValue() {
if (zeroSet != null && !zeroSet.isEmpty()) {
return zeroSet.iterator().next();
}
if (plusSet != null && !plusSet.isEmpty()) {
return plusSet.iterator().next();
}
if (minusSet != null && !minusSet.isEmpty()) {
return minusSet.iterator().next();
}
return null;
}

public boolean isRaw() {
return (isRaw(zeroSet) || isRaw(plusSet) || isRaw(minusSet));
}
Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package com.evolveum.midpoint.prism.parser;

import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.Objectable;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
Expand Down Expand Up @@ -224,14 +225,27 @@ public <T> T unmarshall(MapXNode xnode, Class<T> beanClass) throws SchemaExcepti
objectFactory = instantiateObjectFactory(objectFactoryClass);
elementMethod = inspector.findElementMethodInObjectFactory(objectFactoryClass, propName);
if (elementMethod == null) {
throw new SchemaException("No field "+propName+" in class "+beanClass+" (and no element method in object factory too)");
// Check for "any" method
elementMethod = inspector.findAnyMethod(beanClass);
if (elementMethod == null) {
throw new SchemaException("No field "+propName+" in class "+beanClass+" (and no element method in object factory too)");
}
unmarshallToAny(bean, elementMethod, key, xsubnode);
continue;

}
field = inspector.lookupSubstitution(beanClass, elementMethod);
if (field == null) {
// Check for "any" field
field = inspector.findAnyField(beanClass);
if (field == null) {
throw new SchemaException("No field "+propName+" in class "+beanClass+" (no suitable substitution and no 'any' field)");
elementMethod = inspector.findAnyMethod(beanClass);
if (elementMethod == null) {
throw new SchemaException("No field "+propName+" in class "+beanClass+" (and no element method in object factory too)");
}
unmarshallToAny(bean, elementMethod, key, xsubnode);
continue;
// throw new SchemaException("No field "+propName+" in class "+beanClass+" (no suitable substitution and no 'any' field)");
}
unmarshallToAny(bean, field, key, xsubnode);
continue;
Expand Down Expand Up @@ -501,23 +515,36 @@ protected boolean processSchemaException(SchemaException e, XNode xsubnode) thro
return problem;
}

private <T,S> void unmarshallToAny(T bean, Field anyField, QName elementName, XNode xsubnode) throws SchemaException{
private <T,S> void unmarshallToAny(T bean, Method getter, QName elementName, XNode xsubnode) throws SchemaException{
Class<T> beanClass = (Class<T>) bean.getClass();

Class objectFactoryClass = inspector.getObjectFactoryClass(elementName.getNamespaceURI());
Object objectFactory = instantiateObjectFactory(objectFactoryClass);
Method elementFactoryMethod = inspector.findElementMethodInObjectFactory(objectFactoryClass, elementName.getLocalPart());
Class<S> subBeanClass = (Class<S>) elementFactoryMethod.getParameterTypes()[0];

if (xsubnode instanceof ListXNode){
for (XNode xsubSubNode : ((ListXNode) xsubnode)){
S subBean = unmarshall(xsubSubNode, subBeanClass);
unmarshallToAnyValue(bean, beanClass, subBean, objectFactoryClass, objectFactory, elementFactoryMethod, getter);
}
} else{
S subBean = unmarshall(xsubnode, subBeanClass);
unmarshallToAnyValue(bean, beanClass, subBean, objectFactoryClass, objectFactory, elementFactoryMethod, getter);
}

}

private <T, S> void unmarshallToAnyValue(T bean, Class beanClass, S subBean, Class objectFactoryClass, Object objectFactory, Method elementFactoryMethod, Method getter){


S subBean = unmarshall(xsubnode, subBeanClass);
JAXBElement<S> subBeanElement;
try {
subBeanElement = (JAXBElement<S>) elementFactoryMethod.invoke(objectFactory, subBean);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
throw new IllegalArgumentException("Cannot invoke factory method "+elementFactoryMethod+" on "+objectFactoryClass+" with "+subBean+": "+e1, e1);
}

Method getter = inspector.findPropertyGetter(beanClass, anyField.getName());
Collection<Object> col;
Object getterReturn;
try {
Expand All @@ -530,7 +557,12 @@ private <T,S> void unmarshallToAny(T bean, Field anyField, QName elementName, XN
} catch (ClassCastException e) {
throw new SystemException("Getter "+getter+" on bean of type "+beanClass+" returned "+getterReturn+" instead of collection");
}
col.add(subBeanElement);
col.add(subBeanElement != null ? subBeanElement.getValue() : subBeanElement);
}

private <T,S> void unmarshallToAny(T bean, Field anyField, QName elementName, XNode xsubnode) throws SchemaException{
Method getter = inspector.findPropertyGetter(bean.getClass(), anyField.getName());
unmarshallToAny(bean, getter, elementName, xsubnode);
}

private Object instantiateObjectFactory(Class objectFactoryClass) {
Expand Down Expand Up @@ -770,7 +802,6 @@ public <T> XNode marshall(T bean) throws SchemaException {
} else if (prismContext != null && prismContext.getSchemaRegistry().determineDefinitionFromClass(bean.getClass()) != null){
return prismContext.getXnodeProcessor().serializeObject(((Objectable)bean).asPrismObject()).getSubnode();
}

// Note: SearchFilterType is treated below

Class<? extends Object> beanClass = bean.getClass();
Expand Down
Expand Up @@ -504,6 +504,19 @@ private Field findField(Class classType, Handler<Field> selector) {
}
return findField(superclass, selector);
}

private Method findMethod(Class classType, Handler<Method> selector) {
for (Method field: classType.getDeclaredMethods()) {
if (selector.handle(field)) {
return field;
}
}
Class superclass = classType.getSuperclass();
if (superclass.equals(Object.class)) {
return null;
}
return findMethod(superclass, selector);
}

private List<String> getPropOrderUncached(Class<? extends Object> beanClass) {
List<String> propOrder;
Expand Down Expand Up @@ -664,4 +677,13 @@ public boolean handle(Field field) {
}
});
}

public <T> Method findAnyMethod(Class<T> beanClass) {
return findMethod(beanClass, new Handler<Method>() {
@Override
public boolean handle(Method method) {
return (method.getAnnotation(XmlAnyElement.class) != null);
}
});
}
}

0 comments on commit e6ddebc

Please sign in to comment.