X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.db.procore%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fprocore%2Fcluster%2FPredicateTable.java;h=cfd7bcc55bfb41b44361e1ecfe28f981579aed6c;hp=ed63d7fd44631a3fd0916472f28739eff2269392;hb=e19c37f84fd1ce2d946578f7c05f3e45444ba67a;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/PredicateTable.java b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/PredicateTable.java index ed63d7fd4..cfd7bcc55 100644 --- a/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/PredicateTable.java +++ b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/PredicateTable.java @@ -1,359 +1,359 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.db.procore.cluster; - -import gnu.trove.map.hash.TIntIntHashMap; -import gnu.trove.procedure.TIntIntProcedure; -import gnu.trove.set.hash.TIntHashSet; - -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.exception.ValidationException; -import org.simantics.db.impl.ClusterBase; -import org.simantics.db.impl.ClusterI; -import org.simantics.db.impl.ClusterI.ObjectProcedure; -import org.simantics.db.impl.ClusterI.PredicateProcedure; -import org.simantics.db.impl.ClusterI.Procedure; -import org.simantics.db.impl.ClusterSupport; -import org.simantics.db.impl.Modifier; -import org.simantics.db.impl.Table; -import org.simantics.db.impl.TableFactory; -import org.simantics.db.impl.TableIntAllocatorAdapter; -import org.simantics.db.impl.TableSizeListener; -import org.simantics.db.procore.cluster.TableIntArraySet2.Tables; - -public final class PredicateTable extends Table { - - final TableIntAllocatorAdapter allocator; - - public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase) { - super(TableFactory.getIntFactory(), sizeListener, header, headerBase); - allocator = new TableIntAllocatorAdapter(this); - } - public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) { - super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints); - allocator = new TableIntAllocatorAdapter(this); - } - int createPredicateSet(int[] ps, int[] os) - throws DatabaseException { - int hashBase = TableIntArraySet2.create(ps, os, allocator); - return convertRealIndexToTableIndex(hashBase); - } - void deletePredicateSet(int predicateIndex) { - int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); - if (TableIntArraySet2.isArraySet(getTable(), hashBase)) { - int capacity = TableIntArraySet2.getAllocatedSize(getTable(), hashBase); - int elementIndex = predicateIndex - TableIntArraySet2.HeaderSize; - deleteOldElement(elementIndex, capacity); - } else { - int capacity = TableIntSet2.getAllocatedSize(getTable(), hashBase); - int elementIndex = predicateIndex - TableIntSet2.HeaderSize; - deleteOldElement(elementIndex, capacity); - } - } - public int getPredicateSetSize(int predicateIndex) { - int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); - if (TableIntArraySet2.isArraySet(getTable(), hashBase)) - return TableIntArraySet2.getSize(getTable(), hashBase); - else - return TableIntSet2.getSize(getTable(), hashBase); - } - public int getObjectIndex(int predicateIndex, int pRef) { - int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); - if (TableIntArraySet2.isArraySet(table, hashBase)) - return TableIntArraySet2.get(table, hashBase, pRef); - else { - return TableIntSet2.get(table, hashBase, pRef); - } - } - private int addPredicateArray(int predicateIndex, int hashBase, int pReference, int oReference, ObjectTable ot) - throws DatabaseException { - int newHashBase; - int objectIndex = TableIntArraySet2.get(getTable(), hashBase, pReference); - if (0 == objectIndex) { - newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, oReference, allocator); - } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) { - int oRef = objectIndex; - if (oRef == oReference) { - return 0; // old direct object - } - objectIndex = ot.createObjectSet(oRef, oReference); - assert(0 != objectIndex); - int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex); - newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator); - } else { - int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference); - if (0 == newObjectIndex) - return 0; // old indirect object - newObjectIndex = ClusterTraits.statementIndexMake(newObjectIndex); - newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator); - if (newHashBase == 0) - return hashBase; - } - int TABLE_SIZE = TableIntArraySet2.getSize(getTable(), newHashBase); - if (TABLE_SIZE > 5) - return convertToPredicateSet(predicateIndex, newHashBase); - return newHashBase; - } - private int convertToPredicateSet(int predicateIndex, int hashBase) { - Tables tables = TableIntArraySet2.getInts(getTable(), hashBase); - this.deletePredicateSet(predicateIndex); - int newHashBase = TableIntSet2.create(tables.keys, tables.vals, allocator); - assert(0 != newHashBase); - return newHashBase; - } - private int addPredicateSet(int hashBase, int pReference, int oReference, ObjectTable ot) - throws DatabaseException { - int objectIndex = TableIntSet2.get(getTable(), hashBase, pReference); - int newHashBase; - if (0 == objectIndex) { - newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, oReference, allocator); - } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) { - int oRef = objectIndex; - if (oRef == oReference) { - return 0; // old direct object - } - objectIndex = ot.createObjectSet(oRef, oReference); - assert(0 != objectIndex); - int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex); - newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator); - assert(0 != newHashBase); - } else { - int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference); - if (0 == newObjectIndex) - return 0; // old indirect object - int stmIndex = ClusterTraits.statementIndexMake(newObjectIndex); - newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, stmIndex, allocator); - if (newHashBase == 0) - return hashBase; // new object added to old predicate (set) - } - return newHashBase; - } - /** - * @param predicateIndex - * @param pReference - * @return zero if element was not added or predicate index. - * Predicate index will change if new space is allocated. - */ - public int addPredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot) - throws DatabaseException { - int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); - int newHashBase; - if (TableIntArraySet2.isArraySet(getTable(), hashBase)) - newHashBase = addPredicateArray(predicateIndex, hashBase, pReference, oReference, ot); - else - newHashBase = addPredicateSet(hashBase, pReference, oReference, ot); - if (0 == newHashBase) - return 0; // not modified - return convertRealIndexToTableIndex(newHashBase); - } - public enum Status { - NothingRemoved, - ObjectRemoved, - PredicateRemoved; - } - /** - * @param predicateIndex - * @param oResourceIndex - * @return null if nothing was removed. Status if either object or both - * object and predicate were removed. - */ - public Status removePredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot) - throws DatabaseException { - int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); - int[] table = getTable(); - if (TableIntArraySet2.isArraySet(table, hashBase)) { - int objectIndex = TableIntArraySet2.get(table, hashBase, pReference); - if (0 == objectIndex) { - return Status.NothingRemoved; - } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) { - int oRef = objectIndex; - if (oRef != oReference) - return Status.NothingRemoved; - if (TableIntArraySet2.removeInt(table, hashBase, pReference)) - return Status.PredicateRemoved; - else - throw new DatabaseException("Internal error during remove."); - } else { - int oIndex = ClusterTraits.statementIndexGet(objectIndex); - int nO = ot.getObjectSetSize(oIndex); - if (nO < 1) - throw new DatabaseException("Illegal object set size="+nO); - int nObject = ot.removeObject(objectIndex, oReference); - if (nObject == 0) { - ot.deleteObjectSet(oIndex); - if (TableIntArraySet2.removeInt(table, hashBase, pReference)) - return Status.PredicateRemoved; - else - throw new DatabaseException("Internal error during remove (2)."); - } else if (nO == nObject) - return Status.NothingRemoved; - else - return Status.ObjectRemoved; - } - } else { - int objectIndex = TableIntSet2.get(table, hashBase, pReference); - if (0 == objectIndex) { - return Status.NothingRemoved; - } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) { - int oRef = objectIndex; - if (oRef != oReference) - return Status.NothingRemoved; - if (TableIntSet2.removeInt(table, hashBase, pReference)) - return Status.PredicateRemoved; - else - throw new DatabaseException("Internal error during remove (3)."); - } else { - int oIndex = ClusterTraits.statementIndexGet(objectIndex); - int nO = ot.getObjectSetSize(oIndex); - if (nO < 1) - throw new DatabaseException("Illegal object set size="+nO); - int nObject = ot.removeObject(objectIndex, oReference); - if (nObject == 0) { - ot.deleteObjectSet(oIndex); - if (TableIntSet2.removeInt(table, hashBase, pReference)) - return Status.PredicateRemoved; - else - throw new DatabaseException("Internal error during remove (4)."); - } else if (nO == nObject) - return Status.NothingRemoved; - else - return Status.ObjectRemoved; - } - } - } - public boolean foreachPredicate(int predicateIndex - , ClusterI.PredicateProcedure procedure - , Context context, ClusterSupport support, Modifier modifier) - throws DatabaseException { - final int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); - boolean ret; - if (TableIntArraySet2.isArraySet(getTable(), hashBase)) - ret = TableIntArraySet2.foreachInt(getTable(), hashBase, procedure, context, modifier); - else - ret = TableIntSet2.foreachInt(getTable(), hashBase, procedure, context, modifier); - return ret; - } - private void checkEntry(ClusterBase cluster, int[] table, int index) - throws DatabaseException { - assert(ClusterTraits.statementIndexIsDirect(table[index])); - int dr = table[index]; - cluster.checkDirectReference(dr); - assert(table[index+1] != 0); - if (ClusterTraits.statementIndexIsDirect(table[index+1])) { - cluster.checkDirectReference(table[index+1]); - } else { - cluster.checkObjectSetReference(table[index+1]); - } - } - private TIntHashSet checkIndexSet = null; - public void check(ClusterBase cluster) - throws DatabaseException { - if (null == checkIndexSet) - checkIndexSet = new TIntHashSet(); - else - checkIndexSet.clear(); - int count = 0; - int[] table = getTable(); - int ps = getHeader().getOffset() + ZERO_SHIFT; - int pe = ps + getTableSize(); - for (int p=ps; p= 0) { - int use = p++; - int fre = p++; - int max = p++; - assert(table[cap] >= table[use] + table[fre]); - assert(table[max] == table[cap] >> 1); - assert(table[max]+1 >= table[use]); - checkIndexSet.add(p - ps); - for (int e = p + table[cap]*2; p 0); - boolean free = false; - checkIndexSet.add(p - ps); - for (int e = p + size*2; p boolean foreach(int setIndex, Procedure procedure, Context context, - ClusterSupport support, Modifier modifier) throws DatabaseException { - return foreachPredicate(setIndex, (PredicateProcedure)procedure, context, support, modifier); - } -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.db.procore.cluster; + +import gnu.trove.map.hash.TIntIntHashMap; +import gnu.trove.procedure.TIntIntProcedure; +import gnu.trove.set.hash.TIntHashSet; + +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.ValidationException; +import org.simantics.db.impl.ClusterBase; +import org.simantics.db.impl.ClusterI; +import org.simantics.db.impl.ClusterI.ObjectProcedure; +import org.simantics.db.impl.ClusterI.PredicateProcedure; +import org.simantics.db.impl.ClusterI.Procedure; +import org.simantics.db.impl.ClusterSupport; +import org.simantics.db.impl.Modifier; +import org.simantics.db.impl.Table; +import org.simantics.db.impl.TableFactory; +import org.simantics.db.impl.TableIntAllocatorAdapter; +import org.simantics.db.impl.TableSizeListener; +import org.simantics.db.procore.cluster.TableIntArraySet2.Tables; + +public final class PredicateTable extends Table { + + final TableIntAllocatorAdapter allocator; + + public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase) { + super(TableFactory.getIntFactory(), sizeListener, header, headerBase); + allocator = new TableIntAllocatorAdapter(this); + } + public PredicateTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) { + super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints); + allocator = new TableIntAllocatorAdapter(this); + } + int createPredicateSet(int[] ps, int[] os) + throws DatabaseException { + int hashBase = TableIntArraySet2.create(ps, os, allocator); + return convertRealIndexToTableIndex(hashBase); + } + void deletePredicateSet(int predicateIndex) { + int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); + if (TableIntArraySet2.isArraySet(getTable(), hashBase)) { + int capacity = TableIntArraySet2.getAllocatedSize(getTable(), hashBase); + int elementIndex = predicateIndex - TableIntArraySet2.HeaderSize; + deleteOldElement(elementIndex, capacity); + } else { + int capacity = TableIntSet2.getAllocatedSize(getTable(), hashBase); + int elementIndex = predicateIndex - TableIntSet2.HeaderSize; + deleteOldElement(elementIndex, capacity); + } + } + public int getPredicateSetSize(int predicateIndex) { + int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); + if (TableIntArraySet2.isArraySet(getTable(), hashBase)) + return TableIntArraySet2.getSize(getTable(), hashBase); + else + return TableIntSet2.getSize(getTable(), hashBase); + } + public int getObjectIndex(int predicateIndex, int pRef) { + int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); + if (TableIntArraySet2.isArraySet(table, hashBase)) + return TableIntArraySet2.get(table, hashBase, pRef); + else { + return TableIntSet2.get(table, hashBase, pRef); + } + } + private int addPredicateArray(int predicateIndex, int hashBase, int pReference, int oReference, ObjectTable ot) + throws DatabaseException { + int newHashBase; + int objectIndex = TableIntArraySet2.get(getTable(), hashBase, pReference); + if (0 == objectIndex) { + newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, oReference, allocator); + } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) { + int oRef = objectIndex; + if (oRef == oReference) { + return 0; // old direct object + } + objectIndex = ot.createObjectSet(oRef, oReference); + assert(0 != objectIndex); + int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex); + newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator); + } else { + int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference); + if (0 == newObjectIndex) + return 0; // old indirect object + newObjectIndex = ClusterTraits.statementIndexMake(newObjectIndex); + newHashBase = TableIntArraySet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator); + if (newHashBase == 0) + return hashBase; + } + int TABLE_SIZE = TableIntArraySet2.getSize(getTable(), newHashBase); + if (TABLE_SIZE > 5) + return convertToPredicateSet(predicateIndex, newHashBase); + return newHashBase; + } + private int convertToPredicateSet(int predicateIndex, int hashBase) { + Tables tables = TableIntArraySet2.getInts(getTable(), hashBase); + this.deletePredicateSet(predicateIndex); + int newHashBase = TableIntSet2.create(tables.keys, tables.vals, allocator); + assert(0 != newHashBase); + return newHashBase; + } + private int addPredicateSet(int hashBase, int pReference, int oReference, ObjectTable ot) + throws DatabaseException { + int objectIndex = TableIntSet2.get(getTable(), hashBase, pReference); + int newHashBase; + if (0 == objectIndex) { + newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, oReference, allocator); + } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) { + int oRef = objectIndex; + if (oRef == oReference) { + return 0; // old direct object + } + objectIndex = ot.createObjectSet(oRef, oReference); + assert(0 != objectIndex); + int newObjectIndex = ClusterTraits.statementIndexMake(objectIndex); + newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, newObjectIndex, allocator); + assert(0 != newHashBase); + } else { + int newObjectIndex = ot.addObject(ClusterTraits.statementIndexGet(objectIndex), oReference); + if (0 == newObjectIndex) + return 0; // old indirect object + int stmIndex = ClusterTraits.statementIndexMake(newObjectIndex); + newHashBase = TableIntSet2.addInt(getTable(), hashBase, pReference, stmIndex, allocator); + if (newHashBase == 0) + return hashBase; // new object added to old predicate (set) + } + return newHashBase; + } + /** + * @param predicateIndex + * @param pReference + * @return zero if element was not added or predicate index. + * Predicate index will change if new space is allocated. + */ + public int addPredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot) + throws DatabaseException { + int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); + int newHashBase; + if (TableIntArraySet2.isArraySet(getTable(), hashBase)) + newHashBase = addPredicateArray(predicateIndex, hashBase, pReference, oReference, ot); + else + newHashBase = addPredicateSet(hashBase, pReference, oReference, ot); + if (0 == newHashBase) + return 0; // not modified + return convertRealIndexToTableIndex(newHashBase); + } + public enum Status { + NothingRemoved, + ObjectRemoved, + PredicateRemoved; + } + /** + * @param predicateIndex + * @param oResourceIndex + * @return null if nothing was removed. Status if either object or both + * object and predicate were removed. + */ + public Status removePredicate(int predicateIndex, int pReference, int oReference, ObjectTable ot) + throws DatabaseException { + int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); + int[] table = getTable(); + if (TableIntArraySet2.isArraySet(table, hashBase)) { + int objectIndex = TableIntArraySet2.get(table, hashBase, pReference); + if (0 == objectIndex) { + return Status.NothingRemoved; + } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) { + int oRef = objectIndex; + if (oRef != oReference) + return Status.NothingRemoved; + if (TableIntArraySet2.removeInt(table, hashBase, pReference)) + return Status.PredicateRemoved; + else + throw new DatabaseException("Internal error during remove."); + } else { + int oIndex = ClusterTraits.statementIndexGet(objectIndex); + int nO = ot.getObjectSetSize(oIndex); + if (nO < 1) + throw new DatabaseException("Illegal object set size="+nO); + int nObject = ot.removeObject(objectIndex, oReference); + if (nObject == 0) { + ot.deleteObjectSet(oIndex); + if (TableIntArraySet2.removeInt(table, hashBase, pReference)) + return Status.PredicateRemoved; + else + throw new DatabaseException("Internal error during remove (2)."); + } else if (nO == nObject) + return Status.NothingRemoved; + else + return Status.ObjectRemoved; + } + } else { + int objectIndex = TableIntSet2.get(table, hashBase, pReference); + if (0 == objectIndex) { + return Status.NothingRemoved; + } else if (ClusterTraits.statementIndexIsDirect(objectIndex)) { + int oRef = objectIndex; + if (oRef != oReference) + return Status.NothingRemoved; + if (TableIntSet2.removeInt(table, hashBase, pReference)) + return Status.PredicateRemoved; + else + throw new DatabaseException("Internal error during remove (3)."); + } else { + int oIndex = ClusterTraits.statementIndexGet(objectIndex); + int nO = ot.getObjectSetSize(oIndex); + if (nO < 1) + throw new DatabaseException("Illegal object set size="+nO); + int nObject = ot.removeObject(objectIndex, oReference); + if (nObject == 0) { + ot.deleteObjectSet(oIndex); + if (TableIntSet2.removeInt(table, hashBase, pReference)) + return Status.PredicateRemoved; + else + throw new DatabaseException("Internal error during remove (4)."); + } else if (nO == nObject) + return Status.NothingRemoved; + else + return Status.ObjectRemoved; + } + } + } + public boolean foreachPredicate(int predicateIndex + , ClusterI.PredicateProcedure procedure + , Context context, ClusterSupport support, Modifier modifier) + throws DatabaseException { + final int hashBase = checkIndexAndGetRealIndex(predicateIndex, 0); + boolean ret; + if (TableIntArraySet2.isArraySet(getTable(), hashBase)) + ret = TableIntArraySet2.foreachInt(getTable(), hashBase, procedure, context, modifier); + else + ret = TableIntSet2.foreachInt(getTable(), hashBase, procedure, context, modifier); + return ret; + } + private void checkEntry(ClusterBase cluster, int[] table, int index) + throws DatabaseException { + assert(ClusterTraits.statementIndexIsDirect(table[index])); + int dr = table[index]; + cluster.checkDirectReference(dr); + assert(table[index+1] != 0); + if (ClusterTraits.statementIndexIsDirect(table[index+1])) { + cluster.checkDirectReference(table[index+1]); + } else { + cluster.checkObjectSetReference(table[index+1]); + } + } + private TIntHashSet checkIndexSet = null; + public void check(ClusterBase cluster) + throws DatabaseException { + if (null == checkIndexSet) + checkIndexSet = new TIntHashSet(); + else + checkIndexSet.clear(); + int count = 0; + int[] table = getTable(); + int ps = getHeader().getOffset() + ZERO_SHIFT; + int pe = ps + getTableSize(); + for (int p=ps; p= 0) { + int use = p++; + int fre = p++; + int max = p++; + assert(table[cap] >= table[use] + table[fre]); + assert(table[max] == table[cap] >> 1); + assert(table[max]+1 >= table[use]); + checkIndexSet.add(p - ps); + for (int e = p + table[cap]*2; p 0); + boolean free = false; + checkIndexSet.add(p - ps); + for (int e = p + size*2; p boolean foreach(int setIndex, Procedure procedure, Context context, + ClusterSupport support, Modifier modifier) throws DatabaseException { + return foreachPredicate(setIndex, (PredicateProcedure)procedure, context, support, modifier); + } +}