Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / Validation / ValidationHelper.cs / 1305376 / ValidationHelper.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.Activities.Validation { using System; using System.Activities; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime; using System.Globalization; static class ValidationHelper { public static void ValidateArguments(Activity activity, OverloadGroupEquivalenceInfo equivalenceInfo, Dictionary> overloadGroups, List requiredArgumentsNotInOverloadGroups, IDictionary inputs, ref IList validationErrors) { if (!requiredArgumentsNotInOverloadGroups.IsNullOrEmpty()) { // 1. Check if there are any Required arguments (outside overload groups) that were not specified. foreach (RuntimeArgument argument in requiredArgumentsNotInOverloadGroups) { if (CheckIfArgumentIsNotBound(argument, inputs)) { ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.RequiredArgumentValueNotSupplied(argument.Name), false, argument.Name, activity)); } } } if (!overloadGroups.IsNullOrEmpty()) { //1. Check to see if any of the overload groups are configured. // An overload group is considered to be completely configured if all it's required arguments // are non-null. If an overload group does not have any required arguments then the group is // considered configured if any of the optional arguments are configured. Dictionary configurationResults = new Dictionary (); string configuredGroupName = string.Empty; int configuredCount = 0; int overloadGroupsWithNoRequiredArgs = 0; foreach (KeyValuePair > entry in overloadGroups) { string groupName = entry.Key; configurationResults.Add(groupName, false); IEnumerable requiredArguments = entry.Value.Where((a) => a.IsRequired); if (requiredArguments.Count() > 0) { if (requiredArguments.All(localArgument => CheckIfArgumentIsBound(localArgument, inputs))) { configurationResults[groupName] = true; configuredGroupName = groupName; configuredCount++; } } else { overloadGroupsWithNoRequiredArgs++; IEnumerable optionalArguments = entry.Value.Where((a) => !a.IsRequired); if (optionalArguments.Any(localArgument => CheckIfArgumentIsBound(localArgument, inputs))) { configurationResults[groupName] = true; configuredGroupName = groupName; configuredCount++; } } } //2. It's an error if none of the groups are configured unless there // is atleast one overload group with no required arguments in it. if (configuredCount == 0) { if (overloadGroupsWithNoRequiredArgs == 0) { ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.NoOverloadGroupsAreConfigured, false, activity)); } } //3. If only one overload group was configured, ensure none of the disjoint/overlapping groups have any // required or optional activity arguments set. else if (configuredCount == 1) { HashSet configuredOverloadSet = new HashSet (overloadGroups[configuredGroupName]); Predicate checkIfArgumentIsBound = new Predicate (localArgument => CheckIfArgumentIsBound(localArgument, inputs)); List disjointGroups = null; if (!equivalenceInfo.DisjointGroupsDictionary.IsNullOrEmpty()) { equivalenceInfo.DisjointGroupsDictionary.TryGetValue(configuredGroupName, out disjointGroups); } List overlappingGroups = null; if (!equivalenceInfo.OverlappingGroupsDictionary.IsNullOrEmpty()) { equivalenceInfo.OverlappingGroupsDictionary.TryGetValue(configuredGroupName, out overlappingGroups); } // Iterate over the groups that may not be completely configured. foreach (string groupName in configurationResults.Keys.Where((k) => configurationResults[k] == false)) { // Check if the partially configured group name is in the disjoint groups list. // If so, find all configured arguments. if (disjointGroups != null && disjointGroups.Contains(groupName)) { foreach (RuntimeArgument configuredArgument in overloadGroups[groupName].FindAll(checkIfArgumentIsBound)) { ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.ExtraOverloadGroupPropertiesConfigured(configuredGroupName, configuredArgument.Name, groupName), false, activity)); } } else if (overlappingGroups != null && overlappingGroups.Contains(groupName)) { // Find all arguments of the Overlapping group that are not in the configuredOverloadSet. HashSet overloadGroupSet = new HashSet (overloadGroups[groupName]); IEnumerable intersectSet = overloadGroupSet.Intersect(configuredOverloadSet); List exceptList = overloadGroupSet.Except(intersectSet).ToList(); foreach (RuntimeArgument configuredArgument in exceptList.FindAll(checkIfArgumentIsBound)) { ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.ExtraOverloadGroupPropertiesConfigured(configuredGroupName, configuredArgument.Name, groupName), false, activity)); } } } } //4. If more than one overload group is configured, generate an error. else { IEnumerable configuredGroups = configurationResults.Keys.Where((k) => configurationResults[k]).OrderBy((k) => k, StringComparer.Ordinal); ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.MultipleOverloadGroupsConfigured(configuredGroups.AsCommaSeparatedValues()), false, activity)); } } } public static bool GatherAndValidateOverloads(Activity activity, out Dictionary > overloadGroups, out List requiredArgumentsNotInOverloadGroups, out OverloadGroupEquivalenceInfo equivalenceInfo, ref IList validationErrors) { overloadGroups = null; requiredArgumentsNotInOverloadGroups = null; IEnumerable runtimeArguments = activity.RuntimeArguments; foreach (RuntimeArgument runtimeArgument in runtimeArguments) { if (!runtimeArgument.OverloadGroupNames.IsNullOrEmpty()) { foreach (string groupName in runtimeArgument.OverloadGroupNames) { if (overloadGroups == null) { overloadGroups = new Dictionary >(); } List arguments = null; if (!overloadGroups.TryGetValue(groupName, out arguments)) { arguments = new List (); overloadGroups.Add(groupName, arguments); } arguments.Add(runtimeArgument); } } else { if (runtimeArgument.IsRequired) { if (requiredArgumentsNotInOverloadGroups == null) { requiredArgumentsNotInOverloadGroups = new List (); } requiredArgumentsNotInOverloadGroups.Add(runtimeArgument); } } } equivalenceInfo = GetOverloadGroupEquivalence(overloadGroups); return ValidateOverloadGroupDefinitions(activity, equivalenceInfo, overloadGroups, ref validationErrors); } // This method checks if any of the overload groups are equivalent and/or are a subset/superset of another // overload group. Returns true if there are not any errors. static bool ValidateOverloadGroupDefinitions(Activity activity, OverloadGroupEquivalenceInfo equivalenceInfo, Dictionary > overloadGroups, ref IList validationErrors) { Fx.Assert(equivalenceInfo != null, "equivalenceInfo should have been setup before calling this method"); bool noErrors = true; if (!equivalenceInfo.EquivalentGroupsDictionary.IsNullOrEmpty()) { Hashtable keysVisited = new Hashtable(equivalenceInfo.EquivalentGroupsDictionary.Count); foreach (KeyValuePair > entry in equivalenceInfo.EquivalentGroupsDictionary) { if (!keysVisited.Contains(entry.Key)) { string[] equivalentGroups = new string[entry.Value.Count + 1]; equivalentGroups[0] = entry.Key; entry.Value.CopyTo(equivalentGroups, 1); IEnumerable sortedList = equivalentGroups.OrderBy((s) => s, StringComparer.Ordinal); ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.OverloadGroupsAreEquivalent(sortedList.AsCommaSeparatedValues()), false, activity)); noErrors = false; for (int i = 0; i < equivalentGroups.Length; i++) { keysVisited.Add(equivalentGroups[i], null); } } } } else if (!equivalenceInfo.SupersetOfGroupsDictionary.IsNullOrEmpty()) { foreach (KeyValuePair > entry in equivalenceInfo.SupersetOfGroupsDictionary) { IList sortedList = entry.Value.OrderBy((s) => s, StringComparer.Ordinal).ToList(); string[] subsetGroups = new string[sortedList.Count]; int index = 0; // Select only subsets that have atleast one required argument in them. // We ignore the subsets that have no required arguments in them. foreach (string subsetGroup in sortedList) { if (overloadGroups[subsetGroup].Any ((a) => a.IsRequired)) { subsetGroups[index++] = subsetGroup; } } // If there were any subsets with required arguments generate an error. if (index > 0) { ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.OverloadGroupHasSubsets(entry.Key, subsetGroups.AsCommaSeparatedValues()), false, activity)); noErrors = false; } } } return noErrors; } static OverloadGroupEquivalenceInfo GetOverloadGroupEquivalence(Dictionary > groupDefinitions) { OverloadGroupEquivalenceInfo overloadGroupsInfo = new OverloadGroupEquivalenceInfo(); if (!groupDefinitions.IsNullOrEmpty()) { string[] groupNames = new string[groupDefinitions.Count]; groupDefinitions.Keys.CopyTo(groupNames, 0); for (int i = 0; i < groupNames.Length; i++) { string group1 = groupNames[i]; HashSet group1Args = new HashSet (groupDefinitions[group1]); for (int j = i + 1; j < groupNames.Length; j++) { string group2 = groupNames[j]; HashSet group2Args = new HashSet (groupDefinitions[group2]); if (group1Args.IsProperSupersetOf(group2Args)) { overloadGroupsInfo.SetAsSuperset(group1, group2); } else if (group1Args.IsProperSubsetOf(group2Args)) { overloadGroupsInfo.SetAsSuperset(group2, group1); } else if (group1Args.SetEquals(group2Args)) { overloadGroupsInfo.SetAsEquivalent(group1, group2); } else if (group1Args.Overlaps(group2Args)) { overloadGroupsInfo.SetAsOverlapping(group1, group2); } else // the groups are disjoint. { overloadGroupsInfo.SetAsDisjoint(group1, group2); } } } } return overloadGroupsInfo; } static bool CheckIfArgumentIsNotBound(RuntimeArgument argument, IDictionary inputs) { if (argument.Owner != null && argument.Owner.Parent == null && ArgumentDirectionHelper.IsOut(argument.Direction)) { // Skip the validation for root node's out argument // as it will be added to the output dictionary return false; } if (argument.BoundArgument != null && argument.BoundArgument.Expression != null) { return false; } if (inputs != null) { if(inputs.ContainsKey(argument.Name)) { return false; } } return true; } static bool CheckIfArgumentIsBound(RuntimeArgument argument, IDictionary inputs) { return !(CheckIfArgumentIsNotBound(argument, inputs)); } public class OverloadGroupEquivalenceInfo { Dictionary > equivalentGroupsDictionary; Dictionary > supersetOfGroupsDictionary; Dictionary > overlappingGroupsDictionary; Dictionary > disjointGroupsDictionary; public OverloadGroupEquivalenceInfo() { } public Dictionary > EquivalentGroupsDictionary { get { return this.equivalentGroupsDictionary; } } public Dictionary > SupersetOfGroupsDictionary { get { return this.supersetOfGroupsDictionary; } } public Dictionary > OverlappingGroupsDictionary { get { return this.overlappingGroupsDictionary; } } public Dictionary > DisjointGroupsDictionary { get { return this.disjointGroupsDictionary; } } public void SetAsEquivalent(string group1, string group2) { // Setup EquivalentGroups for group1 this.AddToDictionary(ref this.equivalentGroupsDictionary, group1, group2); // Setup EquivalentGroups for group2 this.AddToDictionary(ref this.equivalentGroupsDictionary, group2, group1); } public void SetAsSuperset(string group1, string group2) { this.AddToDictionary(ref this.supersetOfGroupsDictionary, group1, group2); } public void SetAsOverlapping(string group1, string group2) { // Setup OverlapGroups for group1 this.AddToDictionary(ref this.overlappingGroupsDictionary, group1, group2); // Setup OverlapGroups for group2 this.AddToDictionary(ref this.overlappingGroupsDictionary, group2, group1); } public void SetAsDisjoint(string group1, string group2) { // Setup DisjointGroups for group1 this.AddToDictionary(ref this.disjointGroupsDictionary, group1, group2); // Setup DisjointGroups for group2 this.AddToDictionary(ref this.disjointGroupsDictionary, group2, group1); } void AddToDictionary(ref Dictionary > dictionary, string dictionaryKey, string listEntry) { if (dictionary == null) { dictionary = new Dictionary >(); } List listValues = null; if (!dictionary.TryGetValue(dictionaryKey, out listValues)) { listValues = new List { listEntry }; dictionary.Add(dictionaryKey, listValues); } else { Fx.Assert(!listValues.Contains(listEntry), string.Format(CultureInfo.InvariantCulture, "Duplicate group entry '{0}' getting added.", listEntry)); listValues.Add(listEntry); } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SelectManyQueryOperator.cs
- NamespaceInfo.cs
- LazyTextWriterCreator.cs
- SmtpFailedRecipientException.cs
- ApplicationCommands.cs
- ManagementDateTime.cs
- NameSpaceEvent.cs
- Ops.cs
- nulltextcontainer.cs
- DataKeyCollection.cs
- securitymgrsite.cs
- SafeProcessHandle.cs
- ServerValidateEventArgs.cs
- Base64Stream.cs
- ObjectDataSourceDesigner.cs
- TdsRecordBufferSetter.cs
- LayoutDump.cs
- RenderTargetBitmap.cs
- ThumbAutomationPeer.cs
- TextRangeSerialization.cs
- SiteMapHierarchicalDataSourceView.cs
- PartialArray.cs
- OleDbEnumerator.cs
- AttachmentCollection.cs
- ConnectionManagementElement.cs
- PathGradientBrush.cs
- TileBrush.cs
- ControlValuePropertyAttribute.cs
- OleStrCAMarshaler.cs
- RSAPKCS1KeyExchangeFormatter.cs
- StoryFragments.cs
- InkPresenterAutomationPeer.cs
- GridViewRow.cs
- ExtensionQuery.cs
- ZipIOLocalFileBlock.cs
- SizeConverter.cs
- KeyPressEvent.cs
- ValidatorCollection.cs
- X500Name.cs
- Pen.cs
- WebPartConnection.cs
- SymmetricCryptoHandle.cs
- FunctionUpdateCommand.cs
- CacheChildrenQuery.cs
- ExtractorMetadata.cs
- FormattedTextSymbols.cs
- DiffuseMaterial.cs
- ReaderWriterLock.cs
- RoutedUICommand.cs
- SubMenuStyleCollection.cs
- NetMsmqSecurity.cs
- ToolboxItem.cs
- ProfileParameter.cs
- CardSpaceShim.cs
- DelegatingTypeDescriptionProvider.cs
- InitializerFacet.cs
- Duration.cs
- XmlQualifiedName.cs
- ScaleTransform3D.cs
- DataRowView.cs
- CodeTypeDelegate.cs
- FlowDocumentReader.cs
- RepeaterItemEventArgs.cs
- ButtonPopupAdapter.cs
- WindowsPen.cs
- BindingMAnagerBase.cs
- DateTimeOffset.cs
- TransactionFlowProperty.cs
- ProcessStartInfo.cs
- InlinedAggregationOperator.cs
- FreezableCollection.cs
- Matrix3DStack.cs
- ThreadInterruptedException.cs
- Instrumentation.cs
- EqualityArray.cs
- Region.cs
- HitTestDrawingContextWalker.cs
- MetadataArtifactLoaderFile.cs
- RequestContext.cs
- Mutex.cs
- DataServiceSaveChangesEventArgs.cs
- PageCodeDomTreeGenerator.cs
- Int32RectConverter.cs
- SafeRightsManagementHandle.cs
- ImportDesigner.xaml.cs
- XmlWriterSettings.cs
- DataGridViewToolTip.cs
- CorrelationManager.cs
- MachineSettingsSection.cs
- Timer.cs
- HyperLinkStyle.cs
- Type.cs
- ProviderConnectionPoint.cs
- ConfigurationProperty.cs
- DataRowChangeEvent.cs
- TypeDelegator.cs
- WebServiceTypeData.cs
- ProtectedConfigurationProviderCollection.cs
- Int32RectConverter.cs
- DateTimePicker.cs