From 2b62d6aa0d1a084866fb39a458a2411caecd4496 Mon Sep 17 00:00:00 2001 From: cnathe Date: Thu, 7 Aug 2025 10:21:54 -0500 Subject: [PATCH 01/17] Issue 53586: DomainUtil.createUniquePropertyURI to replace non AlphaNumeric chars --- api/src/org/labkey/api/exp/property/DomainUtil.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/api/src/org/labkey/api/exp/property/DomainUtil.java b/api/src/org/labkey/api/exp/property/DomainUtil.java index b3c4ba65145..6402f538240 100644 --- a/api/src/org/labkey/api/exp/property/DomainUtil.java +++ b/api/src/org/labkey/api/exp/property/DomainUtil.java @@ -1083,7 +1083,7 @@ public static DomainProperty addProperty(Domain domain, GWTPropertyDescriptor pd LOG.debug("Adding property for " + pd.getName()); if (StringUtils.isEmpty(pd.getPropertyURI())) { - String newPropertyURI = createUniquePropertyURI(domain.getTypeURI() + "#" + Lsid.encodePart(pd.getName()), propertyUrisInUse); + String newPropertyURI = createUniquePropertyURI(domain.getTypeURI(), pd.getName(), propertyUrisInUse); assert !propertyUrisInUse.contains(newPropertyURI) : "Attempting to assign an existing PropertyURI to a new property"; pd.setPropertyURI(newPropertyURI); propertyUrisInUse.add(newPropertyURI); @@ -1100,8 +1100,13 @@ public static DomainProperty addProperty(Domain domain, GWTPropertyDescriptor pd return p; } - private static String createUniquePropertyURI(String base, Set propertyUrisInUse) + private static String createUniquePropertyURI(String typeURI, String propName, Set propertyUrisInUse) { + // replace all non-alphanumeric characters in the propName with underscores as they can lead to generated + // URIs that are longer than the DB column length (Issue 53586) + String name = propName.replaceAll("[^a-zA-Z0-9]", "_"); + + String base = typeURI + "#" + Lsid.encodePart(name); String candidateURI = base; int i = 0; From 69c5875fc80980fd187a81dc7a0dc2edc638ef93 Mon Sep 17 00:00:00 2001 From: cnathe Date: Thu, 7 Aug 2025 16:26:25 -0500 Subject: [PATCH 02/17] Try using LsidManager.getLsidPrefixDbSeq() instead of including the property name in PropertyURI --- api/src/org/labkey/api/exp/property/DomainUtil.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/api/src/org/labkey/api/exp/property/DomainUtil.java b/api/src/org/labkey/api/exp/property/DomainUtil.java index 6402f538240..06f1dac81f0 100644 --- a/api/src/org/labkey/api/exp/property/DomainUtil.java +++ b/api/src/org/labkey/api/exp/property/DomainUtil.java @@ -45,6 +45,7 @@ import org.labkey.api.exp.DomainDescriptor; import org.labkey.api.exp.ExperimentException; import org.labkey.api.exp.Lsid; +import org.labkey.api.exp.LsidManager; import org.labkey.api.exp.OntologyManager; import org.labkey.api.exp.PropertyDescriptor; import org.labkey.api.exp.PropertyType; @@ -1083,7 +1084,7 @@ public static DomainProperty addProperty(Domain domain, GWTPropertyDescriptor pd LOG.debug("Adding property for " + pd.getName()); if (StringUtils.isEmpty(pd.getPropertyURI())) { - String newPropertyURI = createUniquePropertyURI(domain.getTypeURI(), pd.getName(), propertyUrisInUse); + String newPropertyURI = createUniquePropertyURI(domain.getTypeURI(), propertyUrisInUse); assert !propertyUrisInUse.contains(newPropertyURI) : "Attempting to assign an existing PropertyURI to a new property"; pd.setPropertyURI(newPropertyURI); propertyUrisInUse.add(newPropertyURI); @@ -1100,13 +1101,12 @@ public static DomainProperty addProperty(Domain domain, GWTPropertyDescriptor pd return p; } - private static String createUniquePropertyURI(String typeURI, String propName, Set propertyUrisInUse) + private static String createUniquePropertyURI(String typeURI, Set propertyUrisInUse) { - // replace all non-alphanumeric characters in the propName with underscores as they can lead to generated - // URIs that are longer than the DB column length (Issue 53586) - String name = propName.replaceAll("[^a-zA-Z0-9]", "_"); + // Don't use property name in URIs as it can create strings that are longer than the DB column length when encoded (Issue 53586) + String dbSeqStr = String.valueOf(LsidManager.getLsidPrefixDbSeq("Property", 1).next()); - String base = typeURI + "#" + Lsid.encodePart(name); + String base = typeURI + "#" + dbSeqStr; String candidateURI = base; int i = 0; From d254d2ee656e436b24d4bfab005145f6b7f76bc1 Mon Sep 17 00:00:00 2001 From: cnathe Date: Fri, 8 Aug 2025 10:41:35 -0500 Subject: [PATCH 03/17] DomainImpl.addProperty to use DomainUtil.createUniquePropertyURI() --- api/src/org/labkey/api/exp/property/DomainUtil.java | 2 +- .../src/org/labkey/experiment/api/property/DomainImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/org/labkey/api/exp/property/DomainUtil.java b/api/src/org/labkey/api/exp/property/DomainUtil.java index 06f1dac81f0..c04d4c955ce 100644 --- a/api/src/org/labkey/api/exp/property/DomainUtil.java +++ b/api/src/org/labkey/api/exp/property/DomainUtil.java @@ -1101,7 +1101,7 @@ public static DomainProperty addProperty(Domain domain, GWTPropertyDescriptor pd return p; } - private static String createUniquePropertyURI(String typeURI, Set propertyUrisInUse) + public static String createUniquePropertyURI(String typeURI, Set propertyUrisInUse) { // Don't use property name in URIs as it can create strings that are longer than the DB column length when encoded (Issue 53586) String dbSeqStr = String.valueOf(LsidManager.getLsidPrefixDbSeq("Property", 1).next()); diff --git a/experiment/src/org/labkey/experiment/api/property/DomainImpl.java b/experiment/src/org/labkey/experiment/api/property/DomainImpl.java index 990ccc5de1f..7de82f4c794 100644 --- a/experiment/src/org/labkey/experiment/api/property/DomainImpl.java +++ b/experiment/src/org/labkey/experiment/api/property/DomainImpl.java @@ -1290,7 +1290,7 @@ public DomainProperty addProperty(PropertyStorageSpec spec) pd.setNullable(spec.isNullable()); // pd.setAutoIncrement(spec.isAutoIncrement()); // always false in PropertyDescriptor pd.setMvEnabled(spec.isMvEnabled()); - pd.setPropertyURI(getTypeURI() + ":field-" + spec.getName()); + pd.setPropertyURI(DomainUtil.createUniquePropertyURI(getTypeURI(), new HashSet<>())); // Issue 53586 pd.setDescription(spec.getDescription()); pd.setImportAliases(spec.getImportAliases()); pd.setScale(spec.getSize()); From 326cb82737fcb2531065eb894200c6eacf80268a Mon Sep 17 00:00:00 2001 From: cnathe Date: Fri, 8 Aug 2025 11:17:06 -0500 Subject: [PATCH 04/17] use DomainUtil.createUniquePropertyURI() --- .../api/reports/model/ReportPropsManager.java | 14 +++----------- .../assay/plate/PlateMetadataDomainKind.java | 16 ++-------------- .../src/org/labkey/issue/model/IssueListDef.java | 4 +++- .../labkey/list/model/ListDefinitionImpl.java | 4 +++- 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/api/src/org/labkey/api/reports/model/ReportPropsManager.java b/api/src/org/labkey/api/reports/model/ReportPropsManager.java index d5db42c7537..dc320e866e5 100644 --- a/api/src/org/labkey/api/reports/model/ReportPropsManager.java +++ b/api/src/org/labkey/api/reports/model/ReportPropsManager.java @@ -34,6 +34,7 @@ import org.labkey.api.exp.PropertyType; import org.labkey.api.exp.property.Domain; import org.labkey.api.exp.property.DomainProperty; +import org.labkey.api.exp.property.DomainUtil; import org.labkey.api.exp.property.PropertyService; import org.labkey.api.query.ValidationException; import org.labkey.api.security.User; @@ -46,6 +47,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; @@ -84,11 +86,6 @@ public List getProperties(Container container) return properties; } - public void createProperty(Container container, User user, String name, String label, PropertyType type) throws Exception - { - ensureProperty(container, user, name, label, type); - } - private Map getPropertyMap(Container container) { Domain domain = getDomain(container, false); @@ -120,7 +117,7 @@ public synchronized DomainProperty ensureProperty(Container container, User user prop.setName(name); prop.setLabel(label); prop.setType(PropertyService.get().getType(domain.getContainer(), type.getXmlName())); - prop.setPropertyURI(getPropertyURI(name, container)); + prop.setPropertyURI(DomainUtil.createUniquePropertyURI(getDomainURI(container), new HashSet<>())); dp = prop; } @@ -209,11 +206,6 @@ private String getDomainURI(@NotNull Container container) return new Lsid("urn:lsid:labkey.com:" + NAMESPACE_PREFIX + ".Folder-" + container.getRowId() + ':' + TYPE_PROPERTIES).toString(); } - private String getPropertyURI(String propertyName, Container container) - { - return getDomainURI(container) + '#' + propertyName; - } - @Override public void containerDeleted(Container container, User user) { diff --git a/assay/src/org/labkey/assay/plate/PlateMetadataDomainKind.java b/assay/src/org/labkey/assay/plate/PlateMetadataDomainKind.java index 956491f2882..1ba6ca84db4 100644 --- a/assay/src/org/labkey/assay/plate/PlateMetadataDomainKind.java +++ b/assay/src/org/labkey/assay/plate/PlateMetadataDomainKind.java @@ -17,6 +17,7 @@ import org.labkey.api.exp.property.BaseAbstractDomainKind; import org.labkey.api.exp.property.Domain; import org.labkey.api.exp.property.DomainProperty; +import org.labkey.api.exp.property.DomainUtil; import org.labkey.api.exp.property.Lookup; import org.labkey.api.exp.property.PropertyService; import org.labkey.api.gwt.client.model.GWTDomain; @@ -153,7 +154,7 @@ public void ensureDomainProperties(Domain domain, Container container) DomainProperty prop = domain.addProperty(); prop.setName(spec.getName()); - prop.setPropertyURI(getUniqueURI(typeUri + "#" + spec.getName(), propertyURIs)); + prop.setPropertyURI(DomainUtil.createUniquePropertyURI(typeUri, propertyURIs)); prop.setRangeURI(spec.getTypeURI()); prop.setScale(spec.getSize()); prop.setRequired(!spec.isNullable()); @@ -168,19 +169,6 @@ public void ensureDomainProperties(Domain domain, Container container) } } - private String getUniqueURI(String uri, Set propertyURIs) - { - String result = uri; - int ordinal = 1; - - while (propertyURIs.contains(result)) - { - result = String.format("%s-%d", uri, ordinal++); - } - propertyURIs.add(result); - return result; - } - @Override public String getStorageSchemaName() { diff --git a/issues/src/org/labkey/issue/model/IssueListDef.java b/issues/src/org/labkey/issue/model/IssueListDef.java index 1daec0f046a..87df88580da 100644 --- a/issues/src/org/labkey/issue/model/IssueListDef.java +++ b/issues/src/org/labkey/issue/model/IssueListDef.java @@ -31,6 +31,7 @@ import org.labkey.api.exp.property.Domain; import org.labkey.api.exp.property.DomainKind; import org.labkey.api.exp.property.DomainProperty; +import org.labkey.api.exp.property.DomainUtil; import org.labkey.api.exp.property.Lookup; import org.labkey.api.exp.property.PropertyService; import org.labkey.api.issues.AbstractIssuesListDefDomainKind; @@ -45,6 +46,7 @@ import org.labkey.issue.query.IssueDefDomainKind; import java.util.Collection; +import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -286,7 +288,7 @@ private void ensureDomainProperties(Domain domain, AbstractIssuesListDefDomainKi DomainProperty prop = domain.addProperty(); prop.setName(spec.getName()); - prop.setPropertyURI(typeUri + "#" + spec.getName()); + prop.setPropertyURI(DomainUtil.createUniquePropertyURI(typeUri, new HashSet<>())); prop.setRangeURI(spec.getTypeURI()); prop.setScale(spec.getSize()); prop.setRequired(!spec.isNullable()); diff --git a/list/src/org/labkey/list/model/ListDefinitionImpl.java b/list/src/org/labkey/list/model/ListDefinitionImpl.java index ad0514f0e02..2095eb5c0a5 100644 --- a/list/src/org/labkey/list/model/ListDefinitionImpl.java +++ b/list/src/org/labkey/list/model/ListDefinitionImpl.java @@ -40,6 +40,7 @@ import org.labkey.api.exp.list.ListItem; import org.labkey.api.exp.property.Domain; import org.labkey.api.exp.property.DomainProperty; +import org.labkey.api.exp.property.DomainUtil; import org.labkey.api.exp.property.PropertyService; import org.labkey.api.gwt.client.model.GWTPropertyDescriptor; import org.labkey.api.query.BatchValidationException; @@ -64,6 +65,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; @@ -446,7 +448,7 @@ private void ensureKey() } DomainProperty prop = domain.addProperty(); - prop.setPropertyURI(domain.getTypeURI() + "#" + getKeyName()); + prop.setPropertyURI(DomainUtil.createUniquePropertyURI(domain.getTypeURI(), new HashSet<>())); prop.setName(getKeyName()); prop.setType(PropertyService.get().getType(domain.getContainer(), getKeyType().getPropertyType().getXmlName())); From 80ea02bff5dcb1152226a62bf7811db02da7bb6b Mon Sep 17 00:00:00 2001 From: cnathe Date: Fri, 8 Aug 2025 11:35:31 -0500 Subject: [PATCH 05/17] use DomainUtil.createUniquePropertyURI() --- .../query/snapshot/AbstractSnapshotProvider.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/api/src/org/labkey/api/query/snapshot/AbstractSnapshotProvider.java b/api/src/org/labkey/api/query/snapshot/AbstractSnapshotProvider.java index a08de1e6ec3..b56e917318e 100644 --- a/api/src/org/labkey/api/query/snapshot/AbstractSnapshotProvider.java +++ b/api/src/org/labkey/api/query/snapshot/AbstractSnapshotProvider.java @@ -24,6 +24,7 @@ import org.labkey.api.exp.PropertyType; import org.labkey.api.exp.property.Domain; import org.labkey.api.exp.property.DomainProperty; +import org.labkey.api.exp.property.DomainUtil; import org.labkey.api.exp.property.PropertyService; import org.labkey.api.query.CustomView; import org.labkey.api.query.QueryDefinition; @@ -35,6 +36,7 @@ import org.springframework.validation.BindException; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; /* @@ -131,13 +133,15 @@ public static DomainProperty addAsDomainProperty(Domain domain, ColumnInfo colum if (name.contains("/")) name = name.replace('/', '.'); + String propertyURI = DomainUtil.createUniquePropertyURI(domain.getTypeURI(), new HashSet<>()); + if (pd != null) { PropertyDescriptor newProp = pd.clone(); // initialize so the domain doesn't get upset newProp.setContainer(domain.getContainer()); - newProp.setPropertyURI(getPropertyURI(domain, column)); + newProp.setPropertyURI(propertyURI); newProp.setPropertyId(0); newProp.setName(name); newProp.setLabel(column.getLabel()); @@ -161,16 +165,11 @@ public static DomainProperty addAsDomainProperty(Domain domain, ColumnInfo colum prop.setType(PropertyService.get().getType(domain.getContainer(), type.getXmlName())); prop.setDescription(column.getDescription()); prop.setFormat(column.getFormat()); - prop.setPropertyURI(getPropertyURI(domain, column)); + prop.setPropertyURI(propertyURI); } return prop; } - public static String getPropertyURI(Domain domain, ColumnInfo column) - { - return domain.getTypeURI() + "." + column.getName(); - } - @Override public TableInfo getTableInfoQuerySnapshotDef() { From d5cacd9820c3308fc8f99d06b8851b689b0edc8b Mon Sep 17 00:00:00 2001 From: cnathe Date: Fri, 8 Aug 2025 11:35:55 -0500 Subject: [PATCH 06/17] remove unused method --- .../dataset/DatasetSnapshotProvider.java | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/study/src/org/labkey/study/dataset/DatasetSnapshotProvider.java b/study/src/org/labkey/study/dataset/DatasetSnapshotProvider.java index 5447e687b45..8f665e2e163 100644 --- a/study/src/org/labkey/study/dataset/DatasetSnapshotProvider.java +++ b/study/src/org/labkey/study/dataset/DatasetSnapshotProvider.java @@ -396,42 +396,6 @@ public ActionURL createSnapshot(QuerySnapshotForm form, BindException errors) th return null; } - /** - * Create a column map for parsing the generated tsv from the query view. We only want to map - * non-default columns, and need to build a map that goes from TSV header to PropertyURI - */ - private Map getColumnMap(Domain d, QueryView view, List fieldKeys, Map fieldMap) - { - Map columnMap = new CaseInsensitiveHashMap<>(); - Study study = StudyManager.getInstance().getStudy(view.getContainer()); - - if (fieldMap != null) - { - if (fieldKeys.isEmpty()) - { - fieldKeys = new ArrayList<>(); - for (DisplayColumn dc : view.getDisplayColumns()) - { - ColumnInfo colInfo = dc.getColumnInfo(); - if (colInfo != null) - fieldKeys.add(colInfo.getFieldKey()); - } - } - - for (FieldKey fieldKey : fieldKeys) - { - ColumnInfo col = fieldMap.get(fieldKey); - if (col != null && !DatasetDefinition.isDefaultFieldName(col.getName(), study)) - { - // The key of the entry is the same code that generates the TSV header lines for - // TSVGridWriter.ColumnHeaderType.queryColumnName. It would be nice to use the code directly. - columnMap.put(FieldKey.fromString(col.getName()).toDisplayString(), getPropertyURI(d, col)); - } - } - } - return columnMap; - } - @Override public synchronized ActionURL updateSnapshot(QuerySnapshotForm form, BindException errors, boolean suppressVisitManagerRecalc) throws Exception { From 5494d5fd8f3d53ee8178c61a8bc949de6d4865de Mon Sep 17 00:00:00 2001 From: cnathe Date: Wed, 13 Aug 2025 11:01:08 -0500 Subject: [PATCH 07/17] use DomainUtil.createUniquePropertyURI() --- api/src/org/labkey/api/exp/ImportTypesHelper.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/src/org/labkey/api/exp/ImportTypesHelper.java b/api/src/org/labkey/api/exp/ImportTypesHelper.java index 811dd90b495..0919d8cfec3 100644 --- a/api/src/org/labkey/api/exp/ImportTypesHelper.java +++ b/api/src/org/labkey/api/exp/ImportTypesHelper.java @@ -29,6 +29,7 @@ import org.labkey.api.data.PHI; import org.labkey.api.data.PropertyStorageSpec; import org.labkey.api.exp.OntologyManager.ImportPropertyDescriptorsList; +import org.labkey.api.exp.property.DomainUtil; import org.labkey.api.exp.property.IPropertyValidator; import org.labkey.api.exp.property.ValidatorKind; import org.labkey.api.gwt.client.DefaultScaleType; @@ -49,6 +50,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Date; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -244,7 +246,7 @@ public static ImportPropertyDescriptorsList getImportPropertyDescriptors(Collect String propertyURI = StringUtils.trimToEmpty(pd.getPropertyURI()); if (propertyURI.isEmpty()) { - pd.setPropertyURI(domainURI + "." + Lsid.encodePart(columnName)); + pd.setPropertyURI(DomainUtil.createUniquePropertyURI(domainURI, new HashSet<>())); } // try use existing SystemProperty PropertyDescriptor from Shared container. From eccbdd314cab89c0909c922710ffbe31a2fde11c Mon Sep 17 00:00:00 2001 From: cnathe Date: Mon, 18 Aug 2025 15:46:46 -0500 Subject: [PATCH 08/17] DomainUtil.createUniquePropertyURI to use CaseInsensitiveHashSet --- api/src/org/labkey/api/exp/ImportTypesHelper.java | 2 +- api/src/org/labkey/api/exp/property/DomainUtil.java | 5 +++++ .../labkey/api/query/snapshot/AbstractSnapshotProvider.java | 2 +- api/src/org/labkey/api/reports/model/ReportPropsManager.java | 2 +- .../src/org/labkey/experiment/api/property/DomainImpl.java | 2 +- issues/src/org/labkey/issue/model/IssueListDef.java | 2 +- list/src/org/labkey/list/model/ListDefinitionImpl.java | 2 +- 7 files changed, 11 insertions(+), 6 deletions(-) diff --git a/api/src/org/labkey/api/exp/ImportTypesHelper.java b/api/src/org/labkey/api/exp/ImportTypesHelper.java index 0919d8cfec3..450598e7095 100644 --- a/api/src/org/labkey/api/exp/ImportTypesHelper.java +++ b/api/src/org/labkey/api/exp/ImportTypesHelper.java @@ -246,7 +246,7 @@ public static ImportPropertyDescriptorsList getImportPropertyDescriptors(Collect String propertyURI = StringUtils.trimToEmpty(pd.getPropertyURI()); if (propertyURI.isEmpty()) { - pd.setPropertyURI(DomainUtil.createUniquePropertyURI(domainURI, new HashSet<>())); + pd.setPropertyURI(DomainUtil.createUniquePropertyURI(domainURI)); } // try use existing SystemProperty PropertyDescriptor from Shared container. diff --git a/api/src/org/labkey/api/exp/property/DomainUtil.java b/api/src/org/labkey/api/exp/property/DomainUtil.java index ca85f8e6456..b68e0ee64a0 100644 --- a/api/src/org/labkey/api/exp/property/DomainUtil.java +++ b/api/src/org/labkey/api/exp/property/DomainUtil.java @@ -1108,6 +1108,11 @@ public static DomainProperty addProperty(Domain domain, GWTPropertyDescriptor pd return p; } + public static String createUniquePropertyURI(String typeURI) + { + return createUniquePropertyURI(typeURI, new CaseInsensitiveHashSet()); + } + public static String createUniquePropertyURI(String typeURI, Set propertyUrisInUse) { // Don't use property name in URIs as it can create strings that are longer than the DB column length when encoded (Issue 53586) diff --git a/api/src/org/labkey/api/query/snapshot/AbstractSnapshotProvider.java b/api/src/org/labkey/api/query/snapshot/AbstractSnapshotProvider.java index b56e917318e..61e9efdc79e 100644 --- a/api/src/org/labkey/api/query/snapshot/AbstractSnapshotProvider.java +++ b/api/src/org/labkey/api/query/snapshot/AbstractSnapshotProvider.java @@ -133,7 +133,7 @@ public static DomainProperty addAsDomainProperty(Domain domain, ColumnInfo colum if (name.contains("/")) name = name.replace('/', '.'); - String propertyURI = DomainUtil.createUniquePropertyURI(domain.getTypeURI(), new HashSet<>()); + String propertyURI = DomainUtil.createUniquePropertyURI(domain.getTypeURI()); if (pd != null) { diff --git a/api/src/org/labkey/api/reports/model/ReportPropsManager.java b/api/src/org/labkey/api/reports/model/ReportPropsManager.java index dc320e866e5..04708973083 100644 --- a/api/src/org/labkey/api/reports/model/ReportPropsManager.java +++ b/api/src/org/labkey/api/reports/model/ReportPropsManager.java @@ -117,7 +117,7 @@ public synchronized DomainProperty ensureProperty(Container container, User user prop.setName(name); prop.setLabel(label); prop.setType(PropertyService.get().getType(domain.getContainer(), type.getXmlName())); - prop.setPropertyURI(DomainUtil.createUniquePropertyURI(getDomainURI(container), new HashSet<>())); + prop.setPropertyURI(DomainUtil.createUniquePropertyURI(getDomainURI(container))); dp = prop; } diff --git a/experiment/src/org/labkey/experiment/api/property/DomainImpl.java b/experiment/src/org/labkey/experiment/api/property/DomainImpl.java index 7de82f4c794..579db692c4d 100644 --- a/experiment/src/org/labkey/experiment/api/property/DomainImpl.java +++ b/experiment/src/org/labkey/experiment/api/property/DomainImpl.java @@ -1290,7 +1290,7 @@ public DomainProperty addProperty(PropertyStorageSpec spec) pd.setNullable(spec.isNullable()); // pd.setAutoIncrement(spec.isAutoIncrement()); // always false in PropertyDescriptor pd.setMvEnabled(spec.isMvEnabled()); - pd.setPropertyURI(DomainUtil.createUniquePropertyURI(getTypeURI(), new HashSet<>())); // Issue 53586 + pd.setPropertyURI(DomainUtil.createUniquePropertyURI(getTypeURI())); // Issue 53586 pd.setDescription(spec.getDescription()); pd.setImportAliases(spec.getImportAliases()); pd.setScale(spec.getSize()); diff --git a/issues/src/org/labkey/issue/model/IssueListDef.java b/issues/src/org/labkey/issue/model/IssueListDef.java index 87df88580da..6e14ca0cc51 100644 --- a/issues/src/org/labkey/issue/model/IssueListDef.java +++ b/issues/src/org/labkey/issue/model/IssueListDef.java @@ -288,7 +288,7 @@ private void ensureDomainProperties(Domain domain, AbstractIssuesListDefDomainKi DomainProperty prop = domain.addProperty(); prop.setName(spec.getName()); - prop.setPropertyURI(DomainUtil.createUniquePropertyURI(typeUri, new HashSet<>())); + prop.setPropertyURI(DomainUtil.createUniquePropertyURI(typeUri)); prop.setRangeURI(spec.getTypeURI()); prop.setScale(spec.getSize()); prop.setRequired(!spec.isNullable()); diff --git a/list/src/org/labkey/list/model/ListDefinitionImpl.java b/list/src/org/labkey/list/model/ListDefinitionImpl.java index 2095eb5c0a5..07c3b39a477 100644 --- a/list/src/org/labkey/list/model/ListDefinitionImpl.java +++ b/list/src/org/labkey/list/model/ListDefinitionImpl.java @@ -448,7 +448,7 @@ private void ensureKey() } DomainProperty prop = domain.addProperty(); - prop.setPropertyURI(DomainUtil.createUniquePropertyURI(domain.getTypeURI(), new HashSet<>())); + prop.setPropertyURI(DomainUtil.createUniquePropertyURI(domain.getTypeURI())); prop.setName(getKeyName()); prop.setType(PropertyService.get().getType(domain.getContainer(), getKeyType().getPropertyType().getXmlName())); From 54e6b43a4dca88f303995b0b8e4c40be4f7c09fc Mon Sep 17 00:00:00 2001 From: cnathe Date: Mon, 18 Aug 2025 16:42:54 -0500 Subject: [PATCH 09/17] DomainUtil.addProperty() usages to use CaseInsensitiveHashSet for propertyUris param --- .../org/labkey/api/issues/AbstractIssuesListDefDomainKind.java | 3 ++- api/src/org/labkey/api/query/ExtendedTableDomainKind.java | 3 ++- assay/src/org/labkey/assay/plate/PlateManager.java | 2 +- .../src/org/labkey/experiment/api/ExperimentServiceImpl.java | 2 +- .../src/org/labkey/experiment/api/SampleTypeServiceImpl.java | 3 ++- .../src/org/labkey/experiment/api/VocabularyDomainKind.java | 3 ++- .../experiment/controllers/property/PropertyController.java | 3 ++- list/src/org/labkey/list/model/ListDomainKind.java | 2 +- study/src/org/labkey/study/model/DatasetDomainKind.java | 3 ++- 9 files changed, 15 insertions(+), 9 deletions(-) diff --git a/api/src/org/labkey/api/issues/AbstractIssuesListDefDomainKind.java b/api/src/org/labkey/api/issues/AbstractIssuesListDefDomainKind.java index a145e5b3b7e..50bed3bd758 100644 --- a/api/src/org/labkey/api/issues/AbstractIssuesListDefDomainKind.java +++ b/api/src/org/labkey/api/issues/AbstractIssuesListDefDomainKind.java @@ -19,6 +19,7 @@ import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.labkey.api.collections.CaseInsensitiveHashSet; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerFilter; import org.labkey.api.data.DbSchema; @@ -325,7 +326,7 @@ public Domain createDomain(GWTDomain domain, IssuesDomain Set lowerReservedNames = reservedNames.stream().map(String::toLowerCase).collect(Collectors.toSet()); Set existingProperties = newDomain.getProperties().stream().map(o -> o.getName().toLowerCase()).collect(Collectors.toSet()); Map defaultValues = new HashMap<>(); - Set propertyUris = new HashSet<>(); + Set propertyUris = new CaseInsensitiveHashSet(); for (GWTPropertyDescriptor pd : properties) { diff --git a/api/src/org/labkey/api/query/ExtendedTableDomainKind.java b/api/src/org/labkey/api/query/ExtendedTableDomainKind.java index 902d22a06c7..d0dfec1cfab 100644 --- a/api/src/org/labkey/api/query/ExtendedTableDomainKind.java +++ b/api/src/org/labkey/api/query/ExtendedTableDomainKind.java @@ -17,6 +17,7 @@ import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; +import org.labkey.api.collections.CaseInsensitiveHashSet; import org.labkey.api.data.Container; import org.labkey.api.exp.ChangePropertyDescriptorException; import org.labkey.api.exp.Handler; @@ -98,7 +99,7 @@ public Domain createDomain(GWTDomain gwtDomain, JSONObjec List properties = gwtDomain.getFields(); Domain newDomain = PropertyService.get().createDomain(container, domainURI, gwtDomain.getName(), templateInfo); - Set propertyUris = new HashSet<>(); + Set propertyUris = new CaseInsensitiveHashSet(); Map defaultValues = new HashMap<>(); try { diff --git a/assay/src/org/labkey/assay/plate/PlateManager.java b/assay/src/org/labkey/assay/plate/PlateManager.java index 065e9a4e457..21ed9c81ee9 100644 --- a/assay/src/org/labkey/assay/plate/PlateManager.java +++ b/assay/src/org/labkey/assay/plate/PlateManager.java @@ -2349,7 +2349,7 @@ public Container getPlateMetadataDomainContainer(Container container) if (existingProperties.contains(pd.getName())) throw new IllegalStateException(String.format("Unable to create field: %s on domain: %s. The field already exists.", pd.getName(), metadataDomain.getTypeURI())); - DomainUtil.addProperty(metadataDomain, pd, new HashMap<>(), new HashSet<>(), null); + DomainUtil.addProperty(metadataDomain, pd, new HashMap<>(), new CaseInsensitiveHashSet(), null); } metadataDomain.save(user); tx.commit(); diff --git a/experiment/src/org/labkey/experiment/api/ExperimentServiceImpl.java b/experiment/src/org/labkey/experiment/api/ExperimentServiceImpl.java index 3b3abe6d34f..814c7124559 100644 --- a/experiment/src/org/labkey/experiment/api/ExperimentServiceImpl.java +++ b/experiment/src/org/labkey/experiment/api/ExperimentServiceImpl.java @@ -7886,7 +7886,7 @@ public ExpDataClassImpl createDataClass( lowerReservedNames = emptySet(); Map defaultValues = new HashMap<>(); - Set propertyUris = new HashSet<>(); + Set propertyUris = new CaseInsensitiveHashSet(); List calculatedFields = new ArrayList<>(); for (GWTPropertyDescriptor pd : properties) { diff --git a/experiment/src/org/labkey/experiment/api/SampleTypeServiceImpl.java b/experiment/src/org/labkey/experiment/api/SampleTypeServiceImpl.java index 7dc15f24429..5b23b5fd785 100644 --- a/experiment/src/org/labkey/experiment/api/SampleTypeServiceImpl.java +++ b/experiment/src/org/labkey/experiment/api/SampleTypeServiceImpl.java @@ -33,6 +33,7 @@ import org.labkey.api.audit.provider.FileSystemAuditProvider; import org.labkey.api.cache.Cache; import org.labkey.api.cache.CacheManager; +import org.labkey.api.collections.CaseInsensitiveHashSet; import org.labkey.api.collections.LongArrayList; import org.labkey.api.collections.LongHashMap; import org.labkey.api.collections.LongHashSet; @@ -787,7 +788,7 @@ public ExpSampleTypeImpl createSampleType(Container c, User u, String name, Stri boolean hasNameProperty = false; String idUri1 = null, idUri2 = null, idUri3 = null, parentUri = null; Map defaultValues = new HashMap<>(); - Set propertyUris = new HashSet<>(); + Set propertyUris = new CaseInsensitiveHashSet(); List calculatedFields = new ArrayList<>(); for (int i = 0; i < properties.size(); i++) { diff --git a/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java b/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java index ed94f605992..1473550b5e9 100644 --- a/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java +++ b/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java @@ -3,6 +3,7 @@ import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.Nullable; import org.json.JSONObject; +import org.labkey.api.collections.CaseInsensitiveHashSet; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerType; import org.labkey.api.data.SQLFragment; @@ -159,7 +160,7 @@ public Domain createDomain(GWTDomain domain, JSONObject arguments, Container con List properties = domain.getFields(); Domain vocabularyDomain = PropertyService.get().createDomain(container, domainURI, domain.getName(), templateInfo); - Set propertyUris = new HashSet<>(); + Set propertyUris = new CaseInsensitiveHashSet(); Map defaultValues = new HashMap<>(); try { diff --git a/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java b/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java index 5a7d624f4c2..a70d3a33524 100644 --- a/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java +++ b/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java @@ -42,6 +42,7 @@ import org.labkey.api.action.ReadOnlyApiAction; import org.labkey.api.action.SimpleViewAction; import org.labkey.api.action.SpringActionController; +import org.labkey.api.collections.CaseInsensitiveHashSet; import org.labkey.api.collections.IntHashMap; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerService; @@ -548,7 +549,7 @@ public Object execute(DomainApiForm form, BindException errors) { try { - DomainProperty dp = DomainUtil.addProperty(domain, field, new HashMap<>(), new HashSet<>(), results); + DomainProperty dp = DomainUtil.addProperty(domain, field, new HashMap<>(), new CaseInsensitiveHashSet(), results); OntologyManager.validatePropertyDescriptor(dp.getPropertyDescriptor()); } catch (ChangePropertyDescriptorException e) diff --git a/list/src/org/labkey/list/model/ListDomainKind.java b/list/src/org/labkey/list/model/ListDomainKind.java index c04fb2c1640..01ff5caa5b8 100644 --- a/list/src/org/labkey/list/model/ListDomainKind.java +++ b/list/src/org/labkey/list/model/ListDomainKind.java @@ -421,7 +421,7 @@ public Domain createDomain(GWTDomain domain, ListDomainKindProperties listProper Set lowerReservedNames = reservedNames.stream().map(String::toLowerCase).collect(Collectors.toSet()); Map defaultValues = new HashMap<>(); - Set propertyUris = new HashSet<>(); + Set propertyUris = new CaseInsensitiveHashSet(); for (GWTPropertyDescriptor pd : properties) { String propertyName = pd.getName().toLowerCase(); diff --git a/study/src/org/labkey/study/model/DatasetDomainKind.java b/study/src/org/labkey/study/model/DatasetDomainKind.java index 59c99386bfc..473f8f70ba6 100644 --- a/study/src/org/labkey/study/model/DatasetDomainKind.java +++ b/study/src/org/labkey/study/model/DatasetDomainKind.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.labkey.api.action.ApiUsageException; +import org.labkey.api.collections.CaseInsensitiveHashSet; import org.labkey.api.compliance.ComplianceService; import org.labkey.api.data.BaseColumnInfo; import org.labkey.api.data.ColumnInfo; @@ -502,7 +503,7 @@ else if (!timepointType.isVisitBased() && getKindName().equals(VisitDatasetDomai Set lowerReservedNames = reservedNames.stream().map(String::toLowerCase).collect(Collectors.toSet()); Set existingProperties = newDomain.getProperties().stream().map(o -> o.getName().toLowerCase()).collect(Collectors.toSet()); Map defaultValues = new HashMap<>(); - Set propertyUris = new HashSet<>(); + Set propertyUris = new CaseInsensitiveHashSet(); for (GWTPropertyDescriptor pd : properties) { From cfdee71a747bbc6c610afc2d836d951aa3989e9c Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 19 Aug 2025 10:26:35 -0500 Subject: [PATCH 10/17] PropertyController TestCase fix for setup and cleanup of Domain --- .../property/PropertyController.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java b/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java index a70d3a33524..35eb30a598f 100644 --- a/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java +++ b/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java @@ -27,7 +27,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.json.JSONObject; +import org.junit.AfterClass; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; import org.labkey.api.action.AbstractFileUploadAction; import org.labkey.api.action.Action; @@ -53,6 +55,7 @@ import org.labkey.api.data.SimpleFilter; import org.labkey.api.defaults.DefaultValueService; import org.labkey.api.exp.ChangePropertyDescriptorException; +import org.labkey.api.exp.DomainNotFoundException; import org.labkey.api.exp.Identifiable; import org.labkey.api.exp.Lsid; import org.labkey.api.exp.LsidManager; @@ -2197,7 +2200,10 @@ public void setPropertyURIs(List propertyURIs) public static class TestCase extends Assert { - Domain createVocabDomain() throws ValidationException + private static Domain domain; + + @BeforeClass + public static void initialSetUp() throws ValidationException { Container c = JunitUtil.getTestContainer(); User user = TestContext.get().getUser(); @@ -2223,7 +2229,14 @@ Domain createVocabDomain() throws ValidationException gwtDomain.setFields(gwtProps); - return DomainUtil.createDomain(VocabularyDomainKind.KIND_NAME, gwtDomain, null, c, user, domainName, null, false); + domain = DomainUtil.createDomain(VocabularyDomainKind.KIND_NAME, gwtDomain, null, c, user, domainName, null, false); + } + + @AfterClass + public static void tearDown() throws DomainNotFoundException + { + User user = TestContext.get().getUser(); + domain.delete(user); } @Test @@ -2232,14 +2245,12 @@ public void testGetDomains() throws ValidationException Container c = JunitUtil.getTestContainer(); User user = TestContext.get().getUser(); - Domain createdDomain = createVocabDomain(); - Set domainKinds = new HashSet<>(); domainKinds.add(VocabularyDomainKind.KIND_NAME); List vocabDomains = PropertyService.get().getDomains(c, user, domainKinds, null, false); - boolean found = vocabDomains.stream().anyMatch(d -> d.getTypeId() == createdDomain.getTypeId()); + boolean found = vocabDomains.stream().anyMatch(d -> d.getTypeId() == domain.getTypeId()); assertTrue("Vocabulary Domain Not found.", found); } @@ -2249,7 +2260,6 @@ public void testGetProperties() throws ValidationException Container c = JunitUtil.getTestContainer(); User user = TestContext.get().getUser(); - Domain domain = createVocabDomain(); var props = domain.getProperties().stream().map(DomainProperty::getPropertyDescriptor).collect(Collectors.toSet()); // find by domainIds @@ -2298,7 +2308,6 @@ public void testPropertyUsages() throws Exception Container c = JunitUtil.getTestContainer(); User user = TestContext.get().getUser(); - Domain domain = createVocabDomain(); var intProp = domain.getPropertyByName("testIntField"); var stringProp = domain.getPropertyByName("testStringField"); From ba466afecc7073247c374420c4718e5a26eb5811 Mon Sep 17 00:00:00 2001 From: cnathe Date: Wed, 20 Aug 2025 09:25:40 -0500 Subject: [PATCH 11/17] Nab test fix for SQL selects that were looking for run properties by propertyURI instead of name --- assay/api-src/org/labkey/api/assay/nab/RenderAssayBean.java | 1 - .../org/labkey/api/assay/nab/query/CutoffValueTable.java | 4 +++- .../org/labkey/api/assay/nab/query/NAbSpecimenTable.java | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/assay/api-src/org/labkey/api/assay/nab/RenderAssayBean.java b/assay/api-src/org/labkey/api/assay/nab/RenderAssayBean.java index e85c763c80d..2da6f00d071 100644 --- a/assay/api-src/org/labkey/api/assay/nab/RenderAssayBean.java +++ b/assay/api-src/org/labkey/api/assay/nab/RenderAssayBean.java @@ -328,7 +328,6 @@ public Pair getFitError(DilutionAssayRun.SampleResul { try { - Lsid fitErrorURI = new Lsid(DilutionDataHandler.NAB_PROPERTY_LSID_PREFIX, getAssay().getProtocol().getName(), DilutionDataHandler.FIT_ERROR_PROPERTY); PropertyDescriptor fitErrorPd = _assay.getDataHandler().getPropertyDescriptor(container, getAssay().getProtocol(), DilutionDataHandler.FIT_ERROR_PROPERTY, new HashMap<>()); if (null != fitErrorPd) diff --git a/assay/api-src/org/labkey/api/assay/nab/query/CutoffValueTable.java b/assay/api-src/org/labkey/api/assay/nab/query/CutoffValueTable.java index ae5db5c1946..5b39f7235af 100644 --- a/assay/api-src/org/labkey/api/assay/nab/query/CutoffValueTable.java +++ b/assay/api-src/org/labkey/api/assay/nab/query/CutoffValueTable.java @@ -81,7 +81,9 @@ private SQLFragment getSelectedCurveFitIC(boolean oorIndicator) defaultICSQL.append(DilutionManager.getTableInfoNAbSpecimen(), "ns"); defaultICSQL.append(", "); defaultICSQL.append(ExperimentService.get().getTinfoExperimentRun(), "er"); - defaultICSQL.append(" WHERE op.PropertyId = pd.PropertyId AND pd.PropertyURI LIKE '%#" + DilutionAssayProvider.CURVE_FIT_METHOD_PROPERTY_NAME + "' AND ns.RowId = "); + defaultICSQL.append(" WHERE op.PropertyId = pd.PropertyId AND pd.Name = ? "); + defaultICSQL.add(DilutionAssayProvider.CURVE_FIT_METHOD_PROPERTY_NAME); + defaultICSQL.append("AND ns.RowId = "); defaultICSQL.append(ExprColumn.STR_TABLE_ALIAS); defaultICSQL.append(".NAbSpecimenID AND er.LSID = o.ObjectURI AND o.ObjectId = op.ObjectId AND er.RowId = ns.RunId)"); defaultICSQL.append("\nWHEN 'Polynomial' THEN "); diff --git a/assay/api-src/org/labkey/api/assay/nab/query/NAbSpecimenTable.java b/assay/api-src/org/labkey/api/assay/nab/query/NAbSpecimenTable.java index 90be158b111..2b6267c8a0f 100644 --- a/assay/api-src/org/labkey/api/assay/nab/query/NAbSpecimenTable.java +++ b/assay/api-src/org/labkey/api/assay/nab/query/NAbSpecimenTable.java @@ -104,7 +104,8 @@ private SQLFragment getSelectedCurveFitAUC(boolean positive) sql.append(OntologyManager.getTinfoPropertyDescriptor(), "pd"); sql.append(", "); sql.append(ExperimentService.get().getTinfoExperimentRun(), "er"); - sql.append(" WHERE op.PropertyId = pd.PropertyId AND pd.PropertyURI LIKE '%#" + DilutionAssayProvider.CURVE_FIT_METHOD_PROPERTY_NAME + "'"); + sql.append(" WHERE op.PropertyId = pd.PropertyId AND pd.Name = ?"); + sql.add(DilutionAssayProvider.CURVE_FIT_METHOD_PROPERTY_NAME); sql.append(" AND er.LSID = o.ObjectURI AND o.ObjectId = op.ObjectId AND er.RowId = " + ExprColumn.STR_TABLE_ALIAS + ".RunId)"); sql.append("\nWHEN 'Polynomial' THEN "); sql.append(ExprColumn.STR_TABLE_ALIAS + "."); From 8af1af735d20372c2bbb3bb8032b57c5e8c89478 Mon Sep 17 00:00:00 2001 From: cnathe Date: Thu, 21 Aug 2025 13:55:28 -0500 Subject: [PATCH 12/17] Domain.addProperty method with option to provide your own propURISuffix --- api/src/org/labkey/api/exp/property/Domain.java | 1 + api/src/org/labkey/api/exp/property/DomainUtil.java | 13 +++++++------ .../labkey/assay/plate/PlateMetadataDomainKind.java | 2 +- .../labkey/experiment/api/property/DomainImpl.java | 9 ++++++++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/api/src/org/labkey/api/exp/property/Domain.java b/api/src/org/labkey/api/exp/property/Domain.java index 2fa60f59830..966bb67cf04 100644 --- a/api/src/org/labkey/api/exp/property/Domain.java +++ b/api/src/org/labkey/api/exp/property/Domain.java @@ -74,6 +74,7 @@ public interface Domain extends IPropertyType DomainProperty addPropertyOfPropertyDescriptor(PropertyDescriptor pd); DomainProperty addProperty(); DomainProperty addProperty(PropertyStorageSpec spec); + DomainProperty addProperty(PropertyStorageSpec spec, @Nullable String propURISuffix); List getColumns(TableInfo sourceTable, ColumnInfo lsidColumn, Container container, User user); diff --git a/api/src/org/labkey/api/exp/property/DomainUtil.java b/api/src/org/labkey/api/exp/property/DomainUtil.java index b68e0ee64a0..613841ca8a3 100644 --- a/api/src/org/labkey/api/exp/property/DomainUtil.java +++ b/api/src/org/labkey/api/exp/property/DomainUtil.java @@ -1091,7 +1091,7 @@ public static DomainProperty addProperty(Domain domain, GWTPropertyDescriptor pd LOG.debug("Adding property for " + pd.getName()); if (StringUtils.isEmpty(pd.getPropertyURI())) { - String newPropertyURI = createUniquePropertyURI(domain.getTypeURI(), propertyUrisInUse); + String newPropertyURI = createUniquePropertyURI(domain.getTypeURI(), null, propertyUrisInUse); assert !propertyUrisInUse.contains(newPropertyURI) : "Attempting to assign an existing PropertyURI to a new property"; pd.setPropertyURI(newPropertyURI); propertyUrisInUse.add(newPropertyURI); @@ -1110,15 +1110,16 @@ public static DomainProperty addProperty(Domain domain, GWTPropertyDescriptor pd public static String createUniquePropertyURI(String typeURI) { - return createUniquePropertyURI(typeURI, new CaseInsensitiveHashSet()); + return createUniquePropertyURI(typeURI, null, new CaseInsensitiveHashSet()); } - public static String createUniquePropertyURI(String typeURI, Set propertyUrisInUse) + public static String createUniquePropertyURI(String typeURI, @Nullable String propURISuffix, Set propertyUrisInUse) { - // Don't use property name in URIs as it can create strings that are longer than the DB column length when encoded (Issue 53586) - String dbSeqStr = String.valueOf(LsidManager.getLsidPrefixDbSeq("Property", 1).next()); + // Don't use long property names in URIs as it can create strings that are longer than the DB column length when encoded (Issue 53586) + if (propURISuffix == null) + propURISuffix = String.valueOf(LsidManager.getLsidPrefixDbSeq("Property", 1).next()); - String base = typeURI + "#" + dbSeqStr; + String base = typeURI + "#" + propURISuffix; String candidateURI = base; int i = 0; diff --git a/assay/src/org/labkey/assay/plate/PlateMetadataDomainKind.java b/assay/src/org/labkey/assay/plate/PlateMetadataDomainKind.java index 1ba6ca84db4..b5a3d7f1684 100644 --- a/assay/src/org/labkey/assay/plate/PlateMetadataDomainKind.java +++ b/assay/src/org/labkey/assay/plate/PlateMetadataDomainKind.java @@ -154,7 +154,7 @@ public void ensureDomainProperties(Domain domain, Container container) DomainProperty prop = domain.addProperty(); prop.setName(spec.getName()); - prop.setPropertyURI(DomainUtil.createUniquePropertyURI(typeUri, propertyURIs)); + prop.setPropertyURI(DomainUtil.createUniquePropertyURI(typeUri, null, propertyURIs)); prop.setRangeURI(spec.getTypeURI()); prop.setScale(spec.getSize()); prop.setRequired(!spec.isNullable()); diff --git a/experiment/src/org/labkey/experiment/api/property/DomainImpl.java b/experiment/src/org/labkey/experiment/api/property/DomainImpl.java index 579db692c4d..f53526dc4a1 100644 --- a/experiment/src/org/labkey/experiment/api/property/DomainImpl.java +++ b/experiment/src/org/labkey/experiment/api/property/DomainImpl.java @@ -30,6 +30,7 @@ import org.labkey.api.audit.AuditLogService; import org.labkey.api.audit.AuditTypeEvent; import org.labkey.api.collections.CaseInsensitiveHashMap; +import org.labkey.api.collections.CaseInsensitiveHashSet; import org.labkey.api.collections.Sets; import org.labkey.api.data.*; import org.labkey.api.data.dialect.SqlDialect; @@ -1281,6 +1282,12 @@ public DomainProperty addProperty() @Override public DomainProperty addProperty(PropertyStorageSpec spec) + { + return addProperty(spec, null); + } + + @Override + public DomainProperty addProperty(PropertyStorageSpec spec, @Nullable String propURISuffix) { PropertyDescriptor pd = new PropertyDescriptor(); pd.setContainer(getContainer()); @@ -1290,7 +1297,7 @@ public DomainProperty addProperty(PropertyStorageSpec spec) pd.setNullable(spec.isNullable()); // pd.setAutoIncrement(spec.isAutoIncrement()); // always false in PropertyDescriptor pd.setMvEnabled(spec.isMvEnabled()); - pd.setPropertyURI(DomainUtil.createUniquePropertyURI(getTypeURI())); // Issue 53586 + pd.setPropertyURI(DomainUtil.createUniquePropertyURI(getTypeURI(), propURISuffix, new CaseInsensitiveHashSet())); // Issue 53586 pd.setDescription(spec.getDescription()); pd.setImportAliases(spec.getImportAliases()); pd.setScale(spec.getSize()); From b29e72f580a34ea9340357374caaa97775823ad2 Mon Sep 17 00:00:00 2001 From: cnathe Date: Thu, 21 Aug 2025 13:56:14 -0500 Subject: [PATCH 13/17] DataIteratorUtil._createTableMap to not include PropertyURI suffix as tableAliasMap option --- api/src/org/labkey/api/dataiterator/DataIteratorUtil.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/api/src/org/labkey/api/dataiterator/DataIteratorUtil.java b/api/src/org/labkey/api/dataiterator/DataIteratorUtil.java index fd1c359788b..813c77e8668 100644 --- a/api/src/org/labkey/api/dataiterator/DataIteratorUtil.java +++ b/api/src/org/labkey/api/dataiterator/DataIteratorUtil.java @@ -247,11 +247,7 @@ protected static Map> _createTableMap(TableInf { String uri = col.getPropertyURI(); if (null != uri) - { targetAliasesMap.put(uri, new Pair<>(col, MatchType.propertyuri)); - String propName = uri.substring(uri.lastIndexOf('#')+1); - targetAliasesMap.put(propName, new Pair<>(col, MatchType.alias)); - } } for (ColumnInfo col : cols) From 9404ebe13daeb05d9de9c48d005c75d3847fcba0 Mon Sep 17 00:00:00 2001 From: cnathe Date: Thu, 21 Aug 2025 15:10:44 -0500 Subject: [PATCH 14/17] add issue number for XarExporter.getPropertyName --- experiment/src/org/labkey/experiment/XarExporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experiment/src/org/labkey/experiment/XarExporter.java b/experiment/src/org/labkey/experiment/XarExporter.java index 74094984a4e..3c6eab7bc80 100644 --- a/experiment/src/org/labkey/experiment/XarExporter.java +++ b/experiment/src/org/labkey/experiment/XarExporter.java @@ -793,7 +793,7 @@ public void addDataClass(ExpDataClass dataClass) throws ExperimentException queueDomain(dataClass.getDomain()); } - // Return the "name" portion of the propertyURI after the hash + // Return the "name" portion of the propertyURI after the hash (Issue 30718) private String getPropertyName(DomainProperty dp) { String name = dp.getName(); From f28eae218671b8f02c39eb5705d613f32ac01f16 Mon Sep 17 00:00:00 2001 From: cnathe Date: Thu, 21 Aug 2025 15:50:25 -0500 Subject: [PATCH 15/17] VocabularyDomainKind propertyURI to continue using field name as suffix --- .../src/org/labkey/experiment/api/VocabularyDomainKind.java | 1 + 1 file changed, 1 insertion(+) diff --git a/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java b/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java index 1473550b5e9..fc7c762e972 100644 --- a/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java +++ b/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java @@ -166,6 +166,7 @@ public Domain createDomain(GWTDomain domain, JSONObject arguments, Container con { for (GWTPropertyDescriptor pd : properties) { + pd.setPropertyURI(DomainUtil.createUniquePropertyURI(vocabularyDomain.getTypeURI(), Lsid.encodePart(pd.getName()), propertyUris)); DomainUtil.addProperty(vocabularyDomain, pd, defaultValues, propertyUris, null); } vocabularyDomain.save(user); From f303565cb58d27e1252a40c79ccd0dbad32da851 Mon Sep 17 00:00:00 2001 From: cnathe Date: Thu, 21 Aug 2025 16:37:16 -0500 Subject: [PATCH 16/17] VocabularyDomainKind propertyURI test case to check for "ends with field name" --- .../src/org/labkey/experiment/XarExporter.java | 1 + .../experiment/VocabularyViewSupportTest.java | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/experiment/src/org/labkey/experiment/XarExporter.java b/experiment/src/org/labkey/experiment/XarExporter.java index 3c6eab7bc80..ce98dfa36fe 100644 --- a/experiment/src/org/labkey/experiment/XarExporter.java +++ b/experiment/src/org/labkey/experiment/XarExporter.java @@ -794,6 +794,7 @@ public void addDataClass(ExpDataClass dataClass) throws ExperimentException } // Return the "name" portion of the propertyURI after the hash (Issue 30718) + @Deprecated private String getPropertyName(DomainProperty dp) { String name = dp.getName(); diff --git a/experiment/test/src/org/labkey/test/tests/experiment/VocabularyViewSupportTest.java b/experiment/test/src/org/labkey/test/tests/experiment/VocabularyViewSupportTest.java index 5978ecd687f..df09bbadf80 100644 --- a/experiment/test/src/org/labkey/test/tests/experiment/VocabularyViewSupportTest.java +++ b/experiment/test/src/org/labkey/test/tests/experiment/VocabularyViewSupportTest.java @@ -5,6 +5,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; +import org.labkey.api.exp.Lsid; import org.labkey.remoteapi.CommandException; import org.labkey.remoteapi.assay.Run; import org.labkey.remoteapi.assay.SaveAssayBatchCommand; @@ -117,6 +118,12 @@ public void testSampleSetViewSupport() throws IOException, CommandException DomainDetailsResponse domainResponse = createDomain(domainKind, domainName, description, fields); int domainId = domainResponse.getDomain().getDomainId().intValue(); + log("Verify vocab domain propertyURIs use field name in suffix (see changes for Issue 53586)"); + List domainFields = domainResponse.getDomain().getFields(); + assertTrue("Domain field propertyURI suffix is incorrect: " + domainFields.get(0).getPropertyURI(), domainFields.get(0).getPropertyURI().endsWith("#" + prop1Name)); + assertTrue("Domain field propertyURI suffix is incorrect: " + domainFields.get(1).getPropertyURI(), domainFields.get(1).getPropertyURI().endsWith("#" + prop2Name)); + assertTrue("Domain field propertyURI suffix is incorrect: " + domainFields.get(2).getPropertyURI(), domainFields.get(2).getPropertyURI().endsWith("#" + prop3Name)); + log("Create a sampleset"); String sampleSchemaName = "samples"; String sampleSetName = "Cars"; @@ -132,11 +139,11 @@ public void testSampleSetViewSupport() throws IOException, CommandException Map row = new HashMap<>(); row.put("Name", "Tesla"); // value for color vocabulary property - row.put(domainResponse.getDomain().getFields().get(0).getPropertyURI(), prop1Value); + row.put(domainFields.get(0).getPropertyURI(), prop1Value); // value for year vocabulary property - row.put(domainResponse.getDomain().getFields().get(1).getPropertyURI(), prop2Value); + row.put(domainFields.get(1).getPropertyURI(), prop2Value); // value for list lookup property - row.put(domainResponse.getDomain().getFields().get(2).getPropertyURI(), listRow1RowId); + row.put(domainFields.get(2).getPropertyURI(), listRow1RowId); insertRowsCommand.addRow(row); insertRowsCommand.execute(createDefaultConnection(), getProjectName()); @@ -224,6 +231,10 @@ public void testAssayViewSupport() throws IOException, CommandException String vocabDomainPropURI1 = domainResponse.getDomain().getFields().get(0).getPropertyURI(); String vocabDomainPropURI2 = domainResponse.getDomain().getFields().get(1).getPropertyURI(); + log("Verify vocab domain propertyURIs use field name in suffix (see changes for Issue 53586)"); + assertTrue("Vocabulary domain propertyURI suffix is incorrect: " + vocabDomainPropURI1, vocabDomainPropURI1.endsWith("#" + Lsid.encodePart(propNameLab))); + assertTrue("Vocabulary domain propertyURI suffix is incorrect: " + vocabDomainPropURI2, vocabDomainPropURI2.endsWith("#" + propNameLocation)); + Run run = new Run(); run.setName("ViewSupportRun"); run.setProperties(Map.of(vocabDomainPropURI1, propValueLab, vocabDomainPropURI2, listRow1RowId)); From 4b2bac49610f03e34270a54d30f95c1103a2d71f Mon Sep 17 00:00:00 2001 From: cnathe Date: Fri, 22 Aug 2025 16:06:22 -0500 Subject: [PATCH 17/17] Move Lsid.encodePart() within addProperty() --- api/src/org/labkey/api/exp/property/Domain.java | 4 +++- api/src/org/labkey/api/exp/property/DomainUtil.java | 10 ++++++---- .../labkey/experiment/api/VocabularyDomainKind.java | 2 +- .../org/labkey/experiment/api/property/DomainImpl.java | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/api/src/org/labkey/api/exp/property/Domain.java b/api/src/org/labkey/api/exp/property/Domain.java index 966bb67cf04..3c0d7b1c1c6 100644 --- a/api/src/org/labkey/api/exp/property/Domain.java +++ b/api/src/org/labkey/api/exp/property/Domain.java @@ -74,7 +74,9 @@ public interface Domain extends IPropertyType DomainProperty addPropertyOfPropertyDescriptor(PropertyDescriptor pd); DomainProperty addProperty(); DomainProperty addProperty(PropertyStorageSpec spec); - DomainProperty addProperty(PropertyStorageSpec spec, @Nullable String propURISuffix); + + @Deprecated // Use addProperty(PropertyStorageSpec) + DomainProperty addProperty(PropertyStorageSpec spec, @Nullable String propSuffix); List getColumns(TableInfo sourceTable, ColumnInfo lsidColumn, Container container, User user); diff --git a/api/src/org/labkey/api/exp/property/DomainUtil.java b/api/src/org/labkey/api/exp/property/DomainUtil.java index 613841ca8a3..6b83d805e70 100644 --- a/api/src/org/labkey/api/exp/property/DomainUtil.java +++ b/api/src/org/labkey/api/exp/property/DomainUtil.java @@ -1113,13 +1113,15 @@ public static String createUniquePropertyURI(String typeURI) return createUniquePropertyURI(typeURI, null, new CaseInsensitiveHashSet()); } - public static String createUniquePropertyURI(String typeURI, @Nullable String propURISuffix, Set propertyUrisInUse) + public static String createUniquePropertyURI(String typeURI, @Nullable String propSuffix, Set propertyUrisInUse) { // Don't use long property names in URIs as it can create strings that are longer than the DB column length when encoded (Issue 53586) - if (propURISuffix == null) - propURISuffix = String.valueOf(LsidManager.getLsidPrefixDbSeq("Property", 1).next()); + if (propSuffix == null) + propSuffix = String.valueOf(LsidManager.getLsidPrefixDbSeq("Property", 1).next()); + else + propSuffix = Lsid.encodePart(propSuffix); - String base = typeURI + "#" + propURISuffix; + String base = typeURI + "#" + propSuffix; String candidateURI = base; int i = 0; diff --git a/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java b/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java index fc7c762e972..daddfde1180 100644 --- a/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java +++ b/experiment/src/org/labkey/experiment/api/VocabularyDomainKind.java @@ -166,7 +166,7 @@ public Domain createDomain(GWTDomain domain, JSONObject arguments, Container con { for (GWTPropertyDescriptor pd : properties) { - pd.setPropertyURI(DomainUtil.createUniquePropertyURI(vocabularyDomain.getTypeURI(), Lsid.encodePart(pd.getName()), propertyUris)); + pd.setPropertyURI(DomainUtil.createUniquePropertyURI(vocabularyDomain.getTypeURI(), pd.getName(), propertyUris)); DomainUtil.addProperty(vocabularyDomain, pd, defaultValues, propertyUris, null); } vocabularyDomain.save(user); diff --git a/experiment/src/org/labkey/experiment/api/property/DomainImpl.java b/experiment/src/org/labkey/experiment/api/property/DomainImpl.java index f53526dc4a1..e275ca559a2 100644 --- a/experiment/src/org/labkey/experiment/api/property/DomainImpl.java +++ b/experiment/src/org/labkey/experiment/api/property/DomainImpl.java @@ -1287,7 +1287,7 @@ public DomainProperty addProperty(PropertyStorageSpec spec) } @Override - public DomainProperty addProperty(PropertyStorageSpec spec, @Nullable String propURISuffix) + public DomainProperty addProperty(PropertyStorageSpec spec, @Nullable String propSuffix) { PropertyDescriptor pd = new PropertyDescriptor(); pd.setContainer(getContainer()); @@ -1297,7 +1297,7 @@ public DomainProperty addProperty(PropertyStorageSpec spec, @Nullable String pro pd.setNullable(spec.isNullable()); // pd.setAutoIncrement(spec.isAutoIncrement()); // always false in PropertyDescriptor pd.setMvEnabled(spec.isMvEnabled()); - pd.setPropertyURI(DomainUtil.createUniquePropertyURI(getTypeURI(), propURISuffix, new CaseInsensitiveHashSet())); // Issue 53586 + pd.setPropertyURI(DomainUtil.createUniquePropertyURI(getTypeURI(), propSuffix, new CaseInsensitiveHashSet())); // Issue 53586 pd.setDescription(spec.getDescription()); pd.setImportAliases(spec.getImportAliases()); pd.setScale(spec.getSize());