You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2011/03/25 14:42:57 UTC
svn commit: r1085359 - in /cayenne/main/trunk: docs/doc/src/main/resources/
framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/
framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/
framework/caye...
Author: aadamchik
Date: Fri Mar 25 13:42:56 2011
New Revision: 1085359
URL: http://svn.apache.org/viewvc?rev=1085359&view=rev
Log:
CAY-1553 cayenne-lifecycle: @SortWeight annotation
Added:
cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/
cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java
cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java
cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java
cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java
cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java
cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java
cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/
cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java
Modified:
cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java
cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml
Modified: cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=1085359&r1=1085358&r2=1085359&view=diff
==============================================================================
--- cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt Fri Mar 25 13:42:56 2011
@@ -17,6 +17,7 @@ CAY-1544 Remove jdk1.6 module from Cayen
CAY-1545 cayenne-lifecycle Referenceable handler refactoring
CAY-1547 cayenne-lifecycle: support for setting UuidRelationships
CAY-1549 Migrate BatchQueryBuilderFactory to DI
+CAY-1553 cayenne-lifecycle: @SortWeight annotation
Bug Fixes Since 3.1M2:
Modified: cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java?rev=1085359&r1=1085358&r2=1085359&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java (original)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/UuidRelationshipFilter.java Fri Mar 25 13:42:56 2011
@@ -30,6 +30,8 @@ import org.apache.cayenne.annotation.Pos
import org.apache.cayenne.annotation.PostPersist;
import org.apache.cayenne.annotation.PostUpdate;
import org.apache.cayenne.graph.GraphDiff;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.query.Query;
/**
@@ -43,6 +45,29 @@ public class UuidRelationshipFilter impl
public void init(DataChannel channel) {
this.faultingStrategy = createFaultingStrategy();
+ registerUuidRelationships(channel);
+ }
+
+ protected void registerUuidRelationships(DataChannel channel) {
+
+ // TODO: create a DI-managed chain of mapping post processors, and extract this
+ // code to a UuidRelationshipModule. The following code in DataDomainProvider
+ // should be in the standard chain, and this method code - in an extension
+ // dataDomain.getEntityResolver().applyDBLayerDefaults();
+ // dataDomain.getEntityResolver().applyObjectLayerDefaults();
+
+ EntityResolver resolver = channel.getEntityResolver();
+ for (ObjEntity entity : resolver.getObjEntities()) {
+
+ Class<?> type = resolver
+ .getClassDescriptor(entity.getName())
+ .getObjectClass();
+
+ UuidRelationship a = type.getAnnotation(UuidRelationship.class);
+ if(a != null) {
+
+ }
+ }
}
protected UuidRelationshipFaultingStrategy createFaultingStrategy() {
Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/SortWeight.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,47 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.lifecycle.sort;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation that defines the insertion sorting "weight" of an entity that is used
+ * when sorting DB operations. This annotation allows to override the topological sorting
+ * algorithm used by Cayenne by default in special occasions.
+ *
+ * @since 3.1
+ */
+@Target( {
+ ElementType.TYPE
+})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SortWeight {
+
+ /**
+ * Returns the "weight" of the entity used for the purpose of the DB operations
+ * sorting. Entities with lower values will be inserted before entities with higher
+ * values. The opposite is true for the delete operations.
+ */
+ int value() default 1;
+}
Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorter.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,116 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.lifecycle.sort;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cayenne.ashwood.AshwoodEntitySorter;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.commons.collections.comparators.ReverseComparator;
+
+/**
+ * EntitySorter that takes into account entity "weights", and otherwise delegating to
+ * another (topological) sorter.
+ *
+ * @since 3.1
+ */
+public class WeightedAshwoodEntitySorter extends AshwoodEntitySorter {
+
+ private Comparator<DbEntity> weightedDbEntityComparator;
+ private Comparator<ObjEntity> weightedObjEntityComparator;
+
+ private Map<DbEntity, Integer> entityWeights;
+
+ public WeightedAshwoodEntitySorter() {
+ this.weightedDbEntityComparator = new WeightedDbEntityComparator();
+ this.weightedObjEntityComparator = new WeightedObjEntityComparator();
+ this.entityWeights = Collections.EMPTY_MAP;
+ }
+
+ @Override
+ protected void doIndexSorter() {
+ super.doIndexSorter();
+
+ entityWeights = new HashMap<DbEntity, Integer>();
+
+ for (ObjEntity entity : entityResolver.getObjEntities()) {
+
+ Class<?> type = entityResolver
+ .getClassDescriptor(entity.getName())
+ .getObjectClass();
+ SortWeight weight = type.getAnnotation(SortWeight.class);
+ if (weight != null) {
+ entityWeights.put(entity.getDbEntity(), weight.value());
+ }
+ }
+ }
+
+ @Override
+ protected Comparator<DbEntity> getDbEntityComparator(boolean dependantFirst) {
+ Comparator<DbEntity> c = weightedDbEntityComparator;
+ if (dependantFirst) {
+ c = new ReverseComparator(c);
+ }
+ return c;
+ }
+
+ @Override
+ protected Comparator<ObjEntity> getObjEntityComparator(boolean dependantFirst) {
+ Comparator<ObjEntity> c = weightedObjEntityComparator;
+ if (dependantFirst) {
+ c = new ReverseComparator(c);
+ }
+ return c;
+ }
+
+ private int getWeight(DbEntity e) {
+ Integer w = entityWeights.get(e);
+ return w != null ? w.intValue() : 1;
+ }
+
+ private final class WeightedDbEntityComparator implements Comparator<DbEntity> {
+
+ public int compare(DbEntity t1, DbEntity t2) {
+ if (t1 == t2) {
+ return 0;
+ }
+
+ int delta = getWeight(t1) - getWeight(t2);
+ return delta != 0 ? delta : dbEntityComparator.compare(t1, t2);
+ }
+ }
+
+ private final class WeightedObjEntityComparator implements Comparator<ObjEntity> {
+
+ public int compare(ObjEntity o1, ObjEntity o2) {
+ if (o1 == o2) {
+ return 0;
+ }
+
+ DbEntity t1 = o1.getDbEntity();
+ DbEntity t2 = o2.getDbEntity();
+
+ return weightedDbEntityComparator.compare(t1, t2);
+ }
+ }
+}
Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortDep.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,7 @@
+package org.apache.cayenne.lifecycle.db;
+
+import org.apache.cayenne.lifecycle.db.auto._SortDep;
+
+public class SortDep extends _SortDep {
+
+}
Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/SortRoot.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,9 @@
+package org.apache.cayenne.lifecycle.db;
+
+import org.apache.cayenne.lifecycle.db.auto._SortRoot;
+import org.apache.cayenne.lifecycle.sort.SortWeight;
+
+@SortWeight(2)
+public class SortRoot extends _SortRoot {
+
+}
Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortDep.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,27 @@
+package org.apache.cayenne.lifecycle.db.auto;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.lifecycle.db.SortRoot;
+
+/**
+ * Class _SortDep was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _SortDep extends CayenneDataObject {
+
+ public static final String ROOT_PROPERTY = "root";
+
+ public static final String ID_PK_COLUMN = "ID";
+
+ public void setRoot(SortRoot root) {
+ setToOneTarget("root", root, true);
+ }
+
+ public SortRoot getRoot() {
+ return (SortRoot)readProperty("root");
+ }
+
+
+}
Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/db/auto/_SortRoot.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,32 @@
+package org.apache.cayenne.lifecycle.db.auto;
+
+import java.util.List;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.lifecycle.db.SortDep;
+
+/**
+ * Class _SortRoot was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _SortRoot extends CayenneDataObject {
+
+ public static final String DEPS_PROPERTY = "deps";
+
+ public static final String ID_PK_COLUMN = "ID";
+
+ public void addToDeps(SortDep obj) {
+ addToManyTarget("deps", obj, true);
+ }
+ public void removeFromDeps(SortDep obj) {
+ removeToManyTarget("deps", obj, true);
+ }
+ @SuppressWarnings("unchecked")
+ public List<SortDep> getDeps() {
+ return (List<SortDep>)readProperty("deps");
+ }
+
+
+}
Added: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java?rev=1085359&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java (added)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/sort/WeightedAshwoodEntitySorterTest.java Fri Mar 25 13:42:56 2011
@@ -0,0 +1,79 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.lifecycle.sort;
+
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.lifecycle.relationship.UuidRelationshipFilter;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.EntityResolver;
+
+public class WeightedAshwoodEntitySorterTest extends TestCase {
+
+ private ServerRuntime runtime;
+
+ @Override
+ protected void setUp() throws Exception {
+
+ runtime = new ServerRuntime("cayenne-lifecycle.xml");
+
+ // a filter is required to invalidate root objects after commit
+ UuidRelationshipFilter filter = new UuidRelationshipFilter();
+ runtime.getDataDomain().addFilter(filter);
+ runtime.getDataDomain().getEntityResolver().getCallbackRegistry().addListener(
+ filter);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ runtime.shutdown();
+ }
+
+ public void testSortDbEntities() {
+
+ EntityResolver resolver = runtime.getDataDomain().getEntityResolver();
+
+ // since it is impossible to ensure non-coincidental sort order of unrelated
+ // DbEntities (without overriding DbEntity.hashCode()), we'll test on 2 entities
+ // with a relationship, and reverse the topological order with SortWeight
+ // annotation.
+
+ List<DbEntity> eSorted = Arrays.asList(resolver.getDbEntity("SORT_DEP"), resolver
+ .getDbEntity("SORT_ROOT"));
+
+ List<DbEntity> e1 = Arrays.asList(resolver.getDbEntity("SORT_ROOT"), resolver
+ .getDbEntity("SORT_DEP"));
+
+ List<DbEntity> e2 = Arrays.asList(resolver.getDbEntity("SORT_DEP"), resolver
+ .getDbEntity("SORT_ROOT"));
+
+ WeightedAshwoodEntitySorter sorter = new WeightedAshwoodEntitySorter();
+ sorter.setEntityResolver(resolver);
+
+ sorter.sortDbEntities(e1, false);
+ assertEquals(eSorted, e1);
+
+ sorter.sortDbEntities(e2, false);
+ assertEquals(eSorted, e2);
+ }
+}
Modified: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml?rev=1085359&r1=1085358&r2=1085359&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml (original)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/resources/lifecycle-map.map.xml Fri Mar 25 13:42:56 2011
@@ -10,6 +10,13 @@
<db-entity name="E2">
<db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
</db-entity>
+ <db-entity name="SORT_DEP">
+ <db-attribute name="ID" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
+ <db-attribute name="ROOT_ID" type="BIGINT" isMandatory="true"/>
+ </db-entity>
+ <db-entity name="SORT_ROOT">
+ <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ </db-entity>
<db-entity name="UUID_ROOT1">
<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
<db-attribute name="UUID" type="VARCHAR" length="200"/>
@@ -18,7 +25,19 @@
</obj-entity>
<obj-entity name="E2" className="org.apache.cayenne.lifecycle.db.E2" dbEntityName="E2">
</obj-entity>
+ <obj-entity name="SortDep" className="org.apache.cayenne.lifecycle.db.SortDep" dbEntityName="SORT_DEP">
+ </obj-entity>
+ <obj-entity name="SortRoot" className="org.apache.cayenne.lifecycle.db.SortRoot" dbEntityName="SORT_ROOT">
+ </obj-entity>
<obj-entity name="UuidRoot1" className="org.apache.cayenne.lifecycle.db.UuidRoot1" dbEntityName="UUID_ROOT1">
<obj-attribute name="uuid" type="java.lang.String" db-attribute-path="UUID"/>
</obj-entity>
+ <db-relationship name="root" source="SORT_DEP" target="SORT_ROOT" toMany="false">
+ <db-attribute-pair source="ROOT_ID" target="ID"/>
+ </db-relationship>
+ <db-relationship name="deps" source="SORT_ROOT" target="SORT_DEP" toMany="true">
+ <db-attribute-pair source="ID" target="ROOT_ID"/>
+ </db-relationship>
+ <obj-relationship name="root" source="SortDep" target="SortRoot" deleteRule="Nullify" db-relationship-path="root"/>
+ <obj-relationship name="deps" source="SortRoot" target="SortDep" deleteRule="Deny" db-relationship-path="deps"/>
</data-map>