Skip to content

Commit

Permalink
Preliminary support for ".." and "@" in filter paths.
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Nov 27, 2015
1 parent 8fefe76 commit e9d7a23
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 53 deletions.
Expand Up @@ -16,8 +16,13 @@

package com.evolveum.midpoint.prism;

import com.evolveum.midpoint.prism.path.IdItemPathSegment;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.ItemPathSegment;
import com.evolveum.midpoint.prism.path.NameItemPathSegment;
import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment;
import com.evolveum.midpoint.prism.path.ParentPathSegment;
import com.evolveum.midpoint.prism.path.ReferencePathSegment;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.PrettyPrinter;

Expand Down Expand Up @@ -163,14 +168,14 @@ public PrismPropertyDefinition createPropertyDefinifion(QName name) {

public PrismPropertyDefinition createPropertyDefinition(String localName, QName typeName) {
QName name = new QName(getSchemaNamespace(),localName);
return createPropertyDefinifion(name,typeName);
return createPropertyDefinifion(name, typeName);
}


public PrismPropertyDefinition createPropertyDefinifion(String localName, String localTypeName) {
QName name = new QName(getSchemaNamespace(),localName);
QName typeName = new QName(getSchemaNamespace(),localTypeName);
return createPropertyDefinifion(name,typeName);
return createPropertyDefinifion(name, typeName);
}

/**
Expand Down Expand Up @@ -222,21 +227,37 @@ public <ID extends ItemDefinition> ID findItemDefinition(ItemPath path) {
}

public <ID extends ItemDefinition> ID findItemDefinition(ItemPath path, Class<ID> clazz) {
while (!path.isEmpty() && !(path.first() instanceof NameItemPathSegment)) {
path = path.rest();
}
if (path.isEmpty()) {
throw new IllegalArgumentException("Cannot resolve empty path on complex type definition "+this);
}
QName firstName = ((NameItemPathSegment)path.first()).getName();
for (ItemDefinition def : getDefinitions()) {
for (;;) {
if (path.isEmpty()) {
throw new IllegalArgumentException("Cannot resolve empty path on complex type definition "+this);
}
ItemPathSegment first = path.first();
if (first instanceof NameItemPathSegment) {
QName firstName = ((NameItemPathSegment)first).getName();
return findNamedItemDefinition(firstName, path.rest(), clazz);
} else if (first instanceof IdItemPathSegment) {
path = path.rest();
} else if (first instanceof ParentPathSegment) {
ComplexTypeDefinition parent = getSchemaRegistry().determineParentDefinition(this, path.rest());
return parent.findItemDefinition(path.rest(), clazz);
} else if (first instanceof ObjectReferencePathSegment) {
throw new IllegalStateException("Couldn't use '@' path segment in this context. CTD=" + getTypeName() + ", path=" + path);
} else {
throw new IllegalStateException("Unexpected path segment: " + first + " in " + path);
}
}
}

// path starts with NamedItemPathSegment
private <ID extends ItemDefinition> ID findNamedItemDefinition(QName firstName, ItemPath rest, Class<ID> clazz) {
for (ItemDefinition def : getDefinitions()) {
if (firstName != null && firstName.equals(def.getName())) {
return (ID) def.findItemDefinition(path.rest(), clazz);
return (ID) def.findItemDefinition(rest, clazz);
}
}
return null;
}
return null;
}

private <T extends ItemDefinition> boolean isItemValid(ItemDefinition def, QName name, Class<T> clazz, boolean caseInsensitive) {
if (def == null) {
return false;
Expand Down
Expand Up @@ -92,7 +92,10 @@ public class PrismConstants {
public static final QName Q_ORDER_BY = new QName(NS_QUERY, "orderBy");
public static final QName Q_ANY = new QName(NS_QUERY, "any");


// Path constants
public static final QName T_PARENT = new QName(NS_TYPES, "parent");
public static final QName T_OBJECT_REFERENCE = new QName(NS_TYPES, "objectReference");

// Misc

public static final Class DEFAULT_VALUE_CLASS = String.class;
Expand Down
Expand Up @@ -18,8 +18,12 @@

import com.evolveum.midpoint.prism.delta.ContainerDelta;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.path.IdItemPathSegment;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.ItemPathSegment;
import com.evolveum.midpoint.prism.path.NameItemPathSegment;
import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment;
import com.evolveum.midpoint.prism.path.ParentPathSegment;
import com.evolveum.midpoint.prism.schema.PrismSchema;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.DebugDumpable;
Expand Down Expand Up @@ -208,16 +212,33 @@ private <D extends ItemDefinition> D findRuntimeItemDefinition(QName firstName,
}

public <ID extends ItemDefinition> ID findItemDefinition(ItemPath path, Class<ID> clazz) {
while (!path.isEmpty() && !(path.first() instanceof NameItemPathSegment)) {
path = path.rest();
}
if (path.isEmpty()) {
return (ID) this;
for (;;) {
if (path.isEmpty()) {
if (clazz.isAssignableFrom(PrismContainerDefinition.class)) {
return (ID) this;
} else {
return null;
}
}
ItemPathSegment first = path.first();
if (first instanceof NameItemPathSegment) {
QName firstName = ((NameItemPathSegment)first).getName();
return findNamedItemDefinition(firstName, path.rest(), clazz);
} else if (first instanceof IdItemPathSegment) {
path = path.rest();
} else if (first instanceof ParentPathSegment) {
ComplexTypeDefinition parent = getSchemaRegistry().determineParentDefinition(getComplexTypeDefinition(), path.rest());
return parent.findItemDefinition(path.tail(), clazz);
} else if (first instanceof ObjectReferencePathSegment) {
throw new IllegalStateException("Couldn't use '@' path segment in this context. PCD=" + getTypeName() + ", path=" + path);
} else {
throw new IllegalStateException("Unexpected path segment: " + first + " in " + path);
}
}
QName firstName = ((NameItemPathSegment)path.first()).getName();
ItemPath rest = path.rest();
}

public <ID extends ItemDefinition> ID findNamedItemDefinition(QName firstName, ItemPath rest, Class<ID> clazz) {

// we need to be compatible with older versions..soo if the path does
// not contains qnames with namespaces defined (but the prefix was
// specified) match definition according to the local name
Expand Down
Expand Up @@ -21,6 +21,7 @@
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.ReferenceDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment;
import com.evolveum.midpoint.util.QNameUtil;


Expand Down Expand Up @@ -103,8 +104,19 @@ public boolean isValidFor(QName elementQName, Class<? extends ItemDefinition> cl
}
return false;
}

@Override

@Override
<T extends ItemDefinition> T findItemDefinition(ItemPath path, Class<T> clazz) {
if (path.isEmpty() || !(path.first() instanceof ObjectReferencePathSegment)) {
return super.findItemDefinition(path, clazz);
} else {
ItemPath rest = path.rest();
PrismObjectDefinition referencedObjectDefinition = getSchemaRegistry().determineReferencedObjectDefinition(targetTypeName, rest);
return (T) referencedObjectDefinition.findItemDefinition(rest, clazz);
}
}

@Override
public PrismReference instantiate() {
return instantiate(getName());
}
Expand Down
Expand Up @@ -82,6 +82,7 @@ protected ItemDelta(QName elementName, D itemDefinition, PrismContext prismConte

protected ItemDelta(ItemPath parentPath, QName elementName, D itemDefinition, PrismContext prismContext) {
//checkPrismContext(prismContext, itemDefinition);
ItemPath.checkNoReferences(parentPath);
this.prismContext = prismContext;
this.elementName = elementName;
this.parentPath = parentPath;
Expand All @@ -90,6 +91,7 @@ protected ItemDelta(ItemPath parentPath, QName elementName, D itemDefinition, Pr

protected ItemDelta(ItemPath path, D itemDefinition, PrismContext prismContext) {
//checkPrismContext(prismContext, itemDefinition);
ItemPath.checkNoReferences(path);
this.prismContext = prismContext;

if (path == null) {
Expand Down
Expand Up @@ -15,19 +15,19 @@
*/
package com.evolveum.midpoint.prism.path;

import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;
import org.apache.commons.lang.Validate;

import javax.xml.namespace.QName;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.QName;

import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;

/**
* @author semancik
Expand All @@ -54,22 +54,32 @@ public ItemPath() {
}

public ItemPath(QName... qnames) {
this.segments = new ArrayList<ItemPathSegment>(qnames.length);
this.segments = new ArrayList<>(qnames.length);
for (QName qname : qnames) {
add(qname);
}
}

public ItemPath(String... names) {
this.segments = new ArrayList<ItemPathSegment>(names.length);
this.segments = new ArrayList<>(names.length);
for (String name : names) {
add(new QName(name));
add(stringToQName(name));
}
}

private QName stringToQName(String name) {
Validate.notNull(name, "name");
if ("..".equals(name)) {
return PrismConstants.T_PARENT;
} else if ("@".equals(name)) {
return PrismConstants.T_OBJECT_REFERENCE;
} else {
return new QName(name);
}
}

public ItemPath(ItemPath parentPath, QName subName) {
this.segments = new ArrayList<ItemPathSegment>(parentPath.segments.size()+1);
public ItemPath(ItemPath parentPath, QName subName) {
this.segments = new ArrayList<>(parentPath.segments.size()+1);
segments.addAll(parentPath.segments);
add(subName);
}
Expand All @@ -82,31 +92,29 @@ public ItemPath(ItemPath parentPath, ItemPath childPath) {


public ItemPath(List<ItemPathSegment> segments) {
this.segments = new ArrayList<ItemPathSegment>(segments.size());
this.segments = new ArrayList<>(segments.size());
this.segments.addAll(segments);
}

public ItemPath(List<ItemPathSegment> segments, ItemPathSegment subSegment) {
this.segments = new ArrayList<ItemPathSegment>(segments.size()+1);
this.segments = new ArrayList<>(segments.size()+1);
this.segments.addAll(segments);
this.segments.add(subSegment);
}

public ItemPath(List<ItemPathSegment> segments, QName subName) {
this.segments = new ArrayList<ItemPathSegment>(segments.size()+1);
this.segments = new ArrayList<>(segments.size()+1);
this.segments.addAll(segments);
add(subName);
}

public ItemPath(ItemPathSegment... segments) {
this.segments = new ArrayList<ItemPathSegment>(segments.length);
for (ItemPathSegment seg : segments) {
this.segments.add(seg);
}
this.segments = new ArrayList<>(segments.length);
Collections.addAll(this.segments, segments);
}

public ItemPath(ItemPath parentPath, ItemPathSegment subSegment) {
this.segments = new ArrayList<ItemPathSegment>(parentPath.segments.size()+1);
this.segments = new ArrayList<>(parentPath.segments.size() + 1);
this.segments.addAll(parentPath.segments);
this.segments.add(subSegment);
}
Expand Down Expand Up @@ -139,7 +147,13 @@ public static ItemPath subPath(ItemPath prefix, ItemPathSegment subSegment) {
}

private void add(QName qname) {
this.segments.add(new NameItemPathSegment(qname));
if (qname.equals(PrismConstants.T_PARENT)) {
this.segments.add(new ParentPathSegment());
} else if (qname.equals(PrismConstants.T_OBJECT_REFERENCE)) {
this.segments.add(new ObjectReferencePathSegment());
} else {
this.segments.add(new NameItemPathSegment(qname));
}
}

public List<ItemPathSegment> getSegments() {
Expand All @@ -154,10 +168,7 @@ public ItemPathSegment first() {
}

public ItemPath rest() {
if (segments.size() == 0) {
return EMPTY_PATH;
}
return new ItemPath(segments.subList(1, segments.size()));
return tail();
}

public NameItemPathSegment lastNamed() {
Expand Down Expand Up @@ -341,6 +352,14 @@ public static boolean containsSingleNameSegment(ItemPath path) {
return path != null && path.size() == 1 && path.first() instanceof NameItemPathSegment;
}

public boolean startsWith(Class<? extends ItemPathSegment> clazz) {
if (isEmpty()) {
return false;
} else {
return clazz.isAssignableFrom(first().getClass());
}
}

public enum CompareResult {
EQUIVALENT,
SUPERPATH,
Expand Down Expand Up @@ -542,4 +561,23 @@ public ItemPath clone() {
return clone;
}

public static boolean containsReferences(ItemPath path) {
return path != null && path.containsReferences();
}

public boolean containsReferences() {
for (ItemPathSegment segment : segments) {
if (segment instanceof ReferencePathSegment) {
return true;
}
}
return false;
}

public static void checkNoReferences(ItemPath path) {
if (containsReferences(path)) {
throw new IllegalStateException("Item path shouldn't contain references but it does: " + path);
}
}

}

0 comments on commit e9d7a23

Please sign in to comment.