Skip to content

Commit

Permalink
Support for cert work items in query interpreter. Multivalued referen…
Browse files Browse the repository at this point in the history
…ce queries.
  • Loading branch information
mederly committed Mar 31, 2017
1 parent f4e70ed commit b110687
Show file tree
Hide file tree
Showing 22 changed files with 824 additions and 414 deletions.
Expand Up @@ -28,9 +28,11 @@
import org.apache.commons.lang.Validate;

import javax.xml.namespace.QName;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author mederly
Expand Down Expand Up @@ -216,8 +218,12 @@ public S_MatchingRuleEntry containsPoly(String orig) {
}

@Override
public S_AtomicFilterExit ref(PrismReferenceValue value) {
return ref(value != null ? Collections.singleton(value) : Collections.<PrismReferenceValue>emptyList());
public S_AtomicFilterExit ref(PrismReferenceValue... values) {
if (values.length == 1 && values[0] == null) {
return ref(Collections.emptyList());
} else {
return ref(Arrays.asList(values));
}
}

@Override
Expand All @@ -226,16 +232,20 @@ public S_AtomicFilterExit ref(Collection<PrismReferenceValue> values) {
}

@Override
public S_AtomicFilterExit ref(String oid) {
return ref(oid != null ? new PrismReferenceValue(oid) : null);
public S_AtomicFilterExit ref(String... oids) {
if (oids.length == 1 && oids[0] == null) {
return ref(Collections.emptyList());
} else {
return ref(Arrays.stream(oids).map(oid -> new PrismReferenceValue(oid)).collect(Collectors.toList()));
}
}

@Override
public S_AtomicFilterExit ref(String oid, QName targetTypeName) {
if (oid != null) {
return ref(new PrismReferenceValue(oid, targetTypeName));
} else {
return ref((PrismReferenceValue) null);
return ref(Collections.emptyList());
}
}

Expand All @@ -244,7 +254,7 @@ public S_AtomicFilterExit isNull() {
if (propertyDefinition != null) {
return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, owner.getPrismContext()));
} else if (referenceDefinition != null) {
return new R_AtomicFilter(this, RefFilter.createReferenceEqual(itemPath, referenceDefinition, Collections.<PrismReferenceValue>emptyList()));
return new R_AtomicFilter(this, RefFilter.createReferenceEqual(itemPath, referenceDefinition, Collections.emptyList()));
} else {
throw new IllegalStateException("No definition");
}
Expand Down
Expand Up @@ -50,9 +50,9 @@ public interface S_ConditionEntry {
S_MatchingRuleEntry contains(Object value);
S_MatchingRuleEntry containsPoly(String orig, String norm);
S_MatchingRuleEntry containsPoly(String orig);
S_AtomicFilterExit ref(PrismReferenceValue value);
S_AtomicFilterExit ref(Collection<PrismReferenceValue> values); // not supported by repo QueryInterpreter yet
S_AtomicFilterExit ref(String oid);
S_AtomicFilterExit ref(PrismReferenceValue... value);
S_AtomicFilterExit ref(Collection<PrismReferenceValue> values);
S_AtomicFilterExit ref(String... oid);
S_AtomicFilterExit ref(String oid, QName targetTypeName);
S_AtomicFilterExit isNull();

Expand Down
Expand Up @@ -346,10 +346,15 @@ public void initialize() throws SAXException, IOException, SchemaException {
throw new IllegalStateException("Namespace prefix mapper not set");
}
try {
LOGGER.trace("initialize() starting"); // TODO remove (all of these)
initResolver();
LOGGER.trace("initResolver() done");
parsePrismSchemas();
LOGGER.trace("parsePrismSchemas() done");
parseJavaxSchema();
LOGGER.trace("parseJavaxSchema() done");
compileCompileTimeClassList();
LOGGER.trace("compileCompileTimeClassList() done");
initialized = true;

} catch (SAXException ex) {
Expand Down Expand Up @@ -405,15 +410,16 @@ private void parsePrismSchema(SchemaDescription schemaDescription, boolean allow

Element domElement = schemaDescription.getDomElement();
boolean isRuntime = schemaDescription.getCompileTimeClassesPackage() == null;
long started = System.currentTimeMillis();
LOGGER.trace("Parsing schema {}, namespace: {}, isRuntime: {}",
schemaDescription.getSourceDescription(), namespace, isRuntime);
PrismSchema schema = PrismSchemaImpl.parse(domElement, entityResolver, isRuntime,
schemaDescription.getSourceDescription(), allowDelayedItemDefinitions, getPrismContext());
if (StringUtils.isEmpty(namespace)) {
namespace = schema.getNamespace();
}
LOGGER.trace("Parsed schema {}, namespace: {}, isRuntime: {}",
schemaDescription.getSourceDescription(), namespace, isRuntime);
LOGGER.trace("Parsed schema {}, namespace: {}, isRuntime: {} in {} ms",
schemaDescription.getSourceDescription(), namespace, isRuntime, System.currentTimeMillis()-started);
schemaDescription.setSchema(schema);
detectExtensionSchema(schema);
}
Expand Down Expand Up @@ -938,43 +944,63 @@ public QName qualifyTypeName(QName typeName) throws SchemaException {
return resolveUnqualifiedTypeName(typeName);
}

// private class ParentChildPair {
// final ComplexTypeDefinition parentDef;
// final ItemDefinition childDef;
// public ParentChildPair(ComplexTypeDefinition parentDef, ItemDefinition childDef) {
// this.parentDef = parentDef;
// this.childDef = childDef;
// }
// }

// current implementation tries to find all references to the child CTD and select those that are able to resolve path of 'rest'
// fails on ambiguity
// it's a bit fragile, as adding new references to child CTD in future may break existing code
@Override
public ComplexTypeDefinition determineParentDefinition(@NotNull ComplexTypeDefinition child, @NotNull ItemPath rest) {
ComplexTypeDefinition parent = null;
Map<ComplexTypeDefinition, ItemDefinition> found = new HashMap<>();
for (PrismSchema schema : getSchemas()) {
if (schema == null) {
continue;
}
for (ComplexTypeDefinition ctd : schema.getComplexTypeDefinitions()) {
for (ItemDefinition item : ctd.getDefinitions()) {
if (item instanceof PrismContainerDefinition) {
PrismContainerDefinition<?> itemPcd = (PrismContainerDefinition<?>) item;
if (itemPcd.getComplexTypeDefinition() != null) {
if (child.getTypeName().equals(itemPcd.getComplexTypeDefinition().getTypeName())) {
if (!rest.isEmpty() && ctd.findItemDefinition(rest) == null) {
continue;
}
if (parent != null && !parent.getTypeClass().equals(ctd.getTypeName())) {
throw new IllegalStateException("Couldn't find parent definition for " + child.getTypeName() + ": More than one candidate found: "
+ parent.getTypeName() + ", " + itemPcd.getTypeName());
}
parent = ctd;
}
if (!(item instanceof PrismContainerDefinition)) {
continue;
}
PrismContainerDefinition<?> itemPcd = (PrismContainerDefinition<?>) item;
if (itemPcd.getComplexTypeDefinition() == null) {
continue;
}
if (child.getTypeName().equals(itemPcd.getComplexTypeDefinition().getTypeName())) {
if (!rest.isEmpty() && ctd.findItemDefinition(rest) == null) {
continue;
}
found.put(ctd, itemPcd);
}
}
}
}
// ComplexTypeDefinition def = findComplexTypeDefinition(new QName(
// "http://midpoint.evolveum.com/xml/ns/public/common/common-3",
// "ObjectType")); // FIXME BRUTAL HACK
if (parent == null) {
if (found.isEmpty()) {
throw new IllegalStateException("Couldn't find definition for parent for " + child.getTypeName() + ", path=" + rest);
} else if (found.size() > 1) {
Map<ComplexTypeDefinition, ItemDefinition> notInherited = found.entrySet().stream()
.filter(e -> !e.getValue().isInherited())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
if (notInherited.isEmpty()) {
throw new IllegalStateException(
"Couldn't find parent definition for " + child.getTypeName() + ": More than one candidate found: "
+ notInherited);
} else if (notInherited.isEmpty()) {
throw new IllegalStateException(
"Couldn't find parent definition for " + child.getTypeName() + ": More than one candidate found - and all are inherited: "
+ found);
} else {
return notInherited.keySet().iterator().next();
}
} else {
return found.keySet().iterator().next();
}
return parent;
}

@Override
Expand Down
Expand Up @@ -917,8 +917,8 @@
<xsd:annotation>
<xsd:documentation>
Original reviewer for this work item.
TODO allow also roles/orgs here.
</xsd:documentation>
<!-- TODO allow also roles/orgs here. -->
<xsd:appinfo>
<a:objectReferenceTargetType>tns:UserType</a:objectReferenceTargetType>
</xsd:appinfo>
Expand All @@ -928,13 +928,20 @@
<xsd:annotation>
<xsd:documentation>
Current reviewer(s) for this work item.
TODO allow also roles/orgs here.
</xsd:documentation>
<!-- TODO allow also roles/orgs here. -->
<xsd:appinfo>
<a:objectReferenceTargetType>tns:UserType</a:objectReferenceTargetType>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="closedTimestamp" type="xsd:dateTime" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
When was this work item closed. (If null, it is considered open.)
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:long" use="optional"/>
</xsd:complexType>
Expand Down
11 changes: 11 additions & 0 deletions infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java
Expand Up @@ -42,6 +42,7 @@
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;

/**
* @author semancik
Expand Down Expand Up @@ -562,4 +563,14 @@ public static String getFirstNonNullString(Object... values) {
Object value = getFirstNonNull(values);
return value != null ? value.toString() : null;
}

public static <T> T extractSingleton(Collection<T> collection) {
if (collection == null || collection.isEmpty()) {
return null;
} else if (collection.size() == 1) {
return collection.iterator().next();
} else {
throw new IllegalArgumentException("Expected a collection with at most one item; got the one with " + collection.size() + " items");
}
}
}

0 comments on commit b110687

Please sign in to comment.