public override void beforeWriteNode(bool IsCopy, bool OverrideUniqueValidation) { List <CswNbtNodePropWrapper> CompoundUniqueProps = new List <CswNbtNodePropWrapper>(); foreach (CswNbtNodePropWrapper CurrentProp in _CswNbtNode.Properties) { if (CurrentProp.WasModified) { // When a property changes, we need to: // 1. recalculate composite property values which include changed properties on this node foreach (CswNbtNodePropWrapper CompositeProp in _CswNbtNode.Properties[(CswEnumNbtFieldType)CswEnumNbtFieldType.Composite]) { if ( CompositeProp.AsComposite.TemplateValue.Contains( CswNbtMetaData.MakeTemplateEntry(CurrentProp.NodeTypePropId.ToString()))) { CompositeProp.AsComposite.RecalculateCompositeValue(); } } // 2. recalculate property references attached to relationships whose values changed if (CurrentProp.getFieldTypeValue() == CswEnumNbtFieldType.Relationship) { foreach (CswNbtNodePropWrapper PropRefPropWrapper in _CswNbtNode.Properties[(CswEnumNbtFieldType)CswEnumNbtFieldType.PropertyReference]) { CswNbtNodePropPropertyReference PropRefProp = PropRefPropWrapper.AsPropertyReference; if ((PropRefProp.RelationshipType == CswEnumNbtViewPropIdType.NodeTypePropId && PropRefProp.RelationshipId == CurrentProp.NodeTypePropId) || (PropRefProp.RelationshipType == CswEnumNbtViewPropIdType.ObjectClassPropId && PropRefProp.RelationshipId == CurrentProp.ObjectClassPropId)) { PropRefProp.RecalculateReferenceValue(); } } } // 3. mark any property references to this property on other nodes as pending update if (CswTools.IsPrimaryKey(CurrentProp.NodeId)) { //BZ 10239 - Fetch the cached value field name. CswNbtFieldTypeRulePropertyReference PropRefFTR = (CswNbtFieldTypeRulePropertyReference)_CswNbtResources.MetaData.getFieldTypeRule(CswEnumNbtFieldType.PropertyReference); CswEnumNbtPropColumn PropRefColumn = PropRefFTR.CachedValueSubField.Column; string SQL = @"update jct_nodes_props set pendingupdate = '" + CswConvert.ToDbVal(true) + @"', " + PropRefColumn.ToString() + @" = '' where jctnodepropid in (select j.jctnodepropid from jct_nodes_props j join nodes n on n.nodeid = j.nodeid join nodetype_props p on p.nodetypepropid = j.nodetypepropid join field_types f on p.fieldtypeid = f.fieldtypeid left outer join jct_nodes_props jntp on (jntp.nodetypepropid = p.fkvalue and jntp.nodeid = n.nodeid and jntp.field1_fk = " + CurrentProp.NodeId.PrimaryKey.ToString() + @") left outer join (select jx.jctnodepropid, ox.objectclasspropid, jx.nodeid from jct_nodes_props jx join nodetype_props px on jx.nodetypepropid = px.nodetypepropid join object_class_props ox on px.objectclasspropid = ox.objectclasspropid where jx.field1_fk = " + CurrentProp.NodeId.PrimaryKey.ToString() + @") jocp on (jocp.objectclasspropid = p.fkvalue and jocp.nodeid = n.nodeid) where f.fieldtype = 'PropertyReference' and ((lower(p.fktype) = 'nodetypepropid' and jntp.jctnodepropid is not null) or (lower(p.fktype) = 'objectclasspropid' and jocp.jctnodepropid is not null)) and ((lower(p.valueproptype) = 'nodetypepropid' and p.valuepropid = " + CurrentProp.NodeTypePropId.ToString() + @") or (lower(p.valueproptype) = 'objectclasspropid' and p.valuepropid = " + CurrentProp.ObjectClassPropId + @")))"; // We're not doing this in a CswTableUpdate because it might be a large operation, // and we don't care about auditing for this change. _CswNbtResources.execArbitraryPlatformNeutralSql(SQL); } // 4. For locations, if this node's location changed, we need to update the pathname on the children if (CurrentProp.getFieldTypeValue() == CswEnumNbtFieldType.Location && CswTools.IsPrimaryKey(_CswNbtNode.NodeId)) { _CswNbtResources.CswNbtNodeFactory.CswNbtNodeWriter.updateRelationsToThisNode(_CswNbtNode); } // 5. Prepare for compound unique validation if (CswConvert.ToBoolean(CurrentProp[CswEnumNbtPropertyAttributeName.CompoundUnique])) { CompoundUniqueProps.Add(CurrentProp); } } // if(CurrentProp.WasModified) } // foreach (CswNbtNodePropWrapper CurrentProp in _CswNbtNode.Properties) if (CompoundUniqueProps.Count > 0 && NodeId != null) { if (false == IsCopy && false == OverrideUniqueValidation) { //check for other compound unique props that were _not_ modified foreach (CswNbtNodePropWrapper CurrentProp in _CswNbtNode.Properties) { if (CswConvert.ToBoolean(CurrentProp[CswEnumNbtPropertyAttributeName.CompoundUnique]) && (false == CompoundUniqueProps.Contains(CurrentProp))) { CompoundUniqueProps.Add(CurrentProp); } } CswNbtView CswNbtView = this.NodeType.CreateDefaultView(); CswNbtView.ViewName = "For compound unique"; CswNbtViewRelationship ViewRelationship = CswNbtView.Root.ChildRelationships[0]; if (CswTools.IsPrimaryKey(NodeId)) { ViewRelationship.NodeIdsToFilterOut.Add(NodeId); } foreach (CswNbtNodePropWrapper CurrentCompoundUniqueProp in CompoundUniqueProps) { //case 27670 - in order to reserve the right for compound unique props to be empty, it has to be explicitly stated when creating the ForCompundUnique view CswNbtViewProperty CswNbtViewProperty = CswNbtView.AddViewProperty(ViewRelationship, CurrentCompoundUniqueProp.NodeTypeProp); ICswNbtFieldTypeRule ftRule = CurrentCompoundUniqueProp.NodeTypeProp.getFieldTypeRule(); ftRule.AddUniqueFilterToView(CswNbtView, CswNbtViewProperty, CurrentCompoundUniqueProp, true); } ICswNbtTree NodeTree = _CswNbtResources.Trees.getTreeFromView(_CswNbtResources.CurrentNbtUser, CswNbtView, true, false, false); if (NodeTree.getChildNodeCount() > 0) { NodeTree.goToNthChild(0); CswNbtNode DuplicateValueNode = NodeTree.getNodeForCurrentPosition(); CswCommaDelimitedString CompoundUniquePropNames = new CswCommaDelimitedString(); CswCommaDelimitedString CompoundUniquePropValues = new CswCommaDelimitedString(); foreach (CswNbtNodePropWrapper CurrentUniqueProp in CompoundUniqueProps) { CompoundUniquePropNames.Add(CurrentUniqueProp.PropName); CompoundUniquePropValues.Add(CurrentUniqueProp.Gestalt); } string ExotericMessage = "The following properties must have unique values: " + CompoundUniquePropNames.ToString(); string EsotericMessage = "The " + CompoundUniquePropNames.ToString() + " of node " + NodeId.ToString() + " are the same as for node " + DuplicateValueNode.NodeId.ToString() + ": " + CompoundUniquePropValues.ToString(); if (false == _CswNbtNode.IsTemp && false == DuplicateValueNode.IsTemp) //only throw an error if we're comparing two REAL nodes { throw (new CswDniException(CswEnumErrorType.Warning, ExotericMessage, EsotericMessage)); } }//we have a duplicate value situation } else { foreach (CswNbtNodePropWrapper CurrentPropWrapper in CompoundUniqueProps) { CurrentPropWrapper.ClearValue(); CurrentPropWrapper.clearModifiedFlag(); } } //if-else we're not a copy and not overridding } //if we have at leaste one modified compound unique prop //_synchNodeName(); // can't do this here, because we miss some of the onBeforeUpdateNodePropRow events // we do it in writer now instead } // beforeWriteNode()
private void _validateCompoundUniqueProps(bool IsCopy) { List <CswNbtNodePropWrapper> CompoundUniqueProps = new List <CswNbtNodePropWrapper>(); if (false == IsCopy) { //check for other compound unique props that were _not_ modififed foreach (CswNbtNodePropWrapper CurrentProp in _CswNbtNode.Properties) { if (CurrentProp.NodeTypeProp.IsCompoundUnique()) { CompoundUniqueProps.Add(CurrentProp); } } if (CompoundUniqueProps.Count > 0 && NodeId != null) { CswNbtView CswNbtView = this.NodeType.CreateDefaultView(); CswNbtView.ViewName = "For compound unique"; CswNbtViewRelationship ViewRelationship = CswNbtView.Root.ChildRelationships[0]; if (CswTools.IsPrimaryKey(NodeId)) { ViewRelationship.NodeIdsToFilterOut.Add(NodeId); } foreach (CswNbtNodePropWrapper CurrentCompoundUniqueProp in CompoundUniqueProps) { //case 27670 - in order to reserve the right for compound unique props to be empty, it has to be explicitly stated when creating the ForCompundUnique view CswNbtViewProperty CswNbtViewProperty = CswNbtView.AddViewProperty(ViewRelationship, CurrentCompoundUniqueProp.NodeTypeProp); ICswNbtFieldTypeRule ftRule = CurrentCompoundUniqueProp.NodeTypeProp.getFieldTypeRule(); ftRule.AddUniqueFilterToView(CswNbtView, CswNbtViewProperty, CurrentCompoundUniqueProp, true); } ICswNbtTree NodeTree = _CswNbtResources.Trees.getTreeFromView(_CswNbtResources.CurrentNbtUser, CswNbtView, true, false, false); if (NodeTree.getChildNodeCount() > 0) { NodeTree.goToNthChild(0); CswNbtNode DuplicateValueNode = NodeTree.getNodeForCurrentPosition(); CswCommaDelimitedString CompoundUniquePropNames = new CswCommaDelimitedString(); CswCommaDelimitedString CompoundUniquePropValues = new CswCommaDelimitedString(); foreach (CswNbtNodePropWrapper CurrentUniqueProp in CompoundUniqueProps) { CompoundUniquePropNames.Add(CurrentUniqueProp.PropName); CompoundUniquePropValues.Add(CurrentUniqueProp.Gestalt); } string ExotericMessage = "The following properties must have unique values: " + CompoundUniquePropNames.ToString(); string EsotericMessage = "The " + CompoundUniquePropNames.ToString() + " of node " + NodeId.ToString() + " are the same as for node " + DuplicateValueNode.NodeId.ToString() + ": " + CompoundUniquePropValues.ToString(); if (false == _CswNbtNode.IsTemp && false == DuplicateValueNode.IsTemp) //only throw an error if we're comparing two REAL nodes { throw (new CswDniException(CswEnumErrorType.Warning, ExotericMessage, EsotericMessage)); } }//we have a duplicate value situation } } else//[9:55:20 AM 11/21/2013] Steven Salter: I can't think of any other situation [that unique props should be blanked] { foreach (CswNbtNodePropWrapper CurrentPropWrapper in CompoundUniqueProps) { CurrentPropWrapper.ClearValue(); CurrentPropWrapper.clearSubFieldModifiedFlags(); } } //if-else we're not a copy and not overridding }