a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
207 lines
8.2 KiB
C#
207 lines
8.2 KiB
C#
//Copyright 2010 Microsoft Corporation
|
|
//
|
|
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
|
|
//You may obtain a copy of the License at
|
|
//
|
|
//http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
//Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
|
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
//See the License for the specific language governing permissions and limitations under the License.
|
|
|
|
|
|
namespace System.Data.Services.Common
|
|
{
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Data.Services.Client;
|
|
|
|
internal sealed class EpmTargetTree
|
|
{
|
|
private int countOfNonContentProperties;
|
|
|
|
internal EpmTargetTree()
|
|
{
|
|
this.SyndicationRoot = new EpmTargetPathSegment();
|
|
this.NonSyndicationRoot = new EpmTargetPathSegment();
|
|
}
|
|
|
|
internal EpmTargetPathSegment SyndicationRoot
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
internal EpmTargetPathSegment NonSyndicationRoot
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
internal bool IsV1Compatible
|
|
{
|
|
get
|
|
{
|
|
return this.countOfNonContentProperties == 0;
|
|
}
|
|
}
|
|
|
|
internal void Add(EntityPropertyMappingInfo epmInfo)
|
|
{
|
|
String targetName = epmInfo.Attribute.TargetPath;
|
|
bool isSyndication = epmInfo.Attribute.TargetSyndicationItem != SyndicationItemProperty.CustomProperty;
|
|
String namespaceUri = epmInfo.Attribute.TargetNamespaceUri;
|
|
String namespacePrefix = epmInfo.Attribute.TargetNamespacePrefix;
|
|
|
|
EpmTargetPathSegment currentSegment = isSyndication ? this.SyndicationRoot : this.NonSyndicationRoot;
|
|
IList<EpmTargetPathSegment> activeSubSegments = currentSegment.SubSegments;
|
|
|
|
Debug.Assert(!String.IsNullOrEmpty(targetName), "Must have been validated during EntityPropertyMappingAttribute construction");
|
|
String[] targetSegments = targetName.Split('/');
|
|
|
|
for (int i = 0; i < targetSegments.Length; i++)
|
|
{
|
|
String targetSegment = targetSegments[i];
|
|
|
|
if (targetSegment.Length == 0)
|
|
{
|
|
throw new InvalidOperationException(Strings.EpmTargetTree_InvalidTargetPath(targetName));
|
|
}
|
|
|
|
if (targetSegment[0] == '@' && i != targetSegments.Length - 1)
|
|
{
|
|
throw new InvalidOperationException(Strings.EpmTargetTree_AttributeInMiddle(targetSegment));
|
|
}
|
|
|
|
EpmTargetPathSegment foundSegment = activeSubSegments.SingleOrDefault(
|
|
segment => segment.SegmentName == targetSegment &&
|
|
(isSyndication || segment.SegmentNamespaceUri == namespaceUri));
|
|
if (foundSegment != null)
|
|
{
|
|
currentSegment = foundSegment;
|
|
}
|
|
else
|
|
{
|
|
currentSegment = new EpmTargetPathSegment(targetSegment, namespaceUri, namespacePrefix, currentSegment);
|
|
if (targetSegment[0] == '@')
|
|
{
|
|
activeSubSegments.Insert(0, currentSegment);
|
|
}
|
|
else
|
|
{
|
|
activeSubSegments.Add(currentSegment);
|
|
}
|
|
}
|
|
|
|
activeSubSegments = currentSegment.SubSegments;
|
|
}
|
|
|
|
if (currentSegment.HasContent)
|
|
{
|
|
throw new ArgumentException(Strings.EpmTargetTree_DuplicateEpmAttrsWithSameTargetName(EpmTargetTree.GetPropertyNameFromEpmInfo(currentSegment.EpmInfo), currentSegment.EpmInfo.DefiningType.Name, currentSegment.EpmInfo.Attribute.SourcePath, epmInfo.Attribute.SourcePath));
|
|
}
|
|
|
|
if (!epmInfo.Attribute.KeepInContent)
|
|
{
|
|
this.countOfNonContentProperties++;
|
|
}
|
|
|
|
currentSegment.EpmInfo = epmInfo;
|
|
|
|
if (EpmTargetTree.HasMixedContent(this.NonSyndicationRoot, false))
|
|
{
|
|
throw new InvalidOperationException(Strings.EpmTargetTree_InvalidTargetPath(targetName));
|
|
}
|
|
}
|
|
|
|
internal void Remove(EntityPropertyMappingInfo epmInfo)
|
|
{
|
|
String targetName = epmInfo.Attribute.TargetPath;
|
|
bool isSyndication = epmInfo.Attribute.TargetSyndicationItem != SyndicationItemProperty.CustomProperty;
|
|
String namespaceUri = epmInfo.Attribute.TargetNamespaceUri;
|
|
|
|
EpmTargetPathSegment currentSegment = isSyndication ? this.SyndicationRoot : this.NonSyndicationRoot;
|
|
List<EpmTargetPathSegment> activeSubSegments = currentSegment.SubSegments;
|
|
|
|
Debug.Assert(!String.IsNullOrEmpty(targetName), "Must have been validated during EntityPropertyMappingAttribute construction");
|
|
String[] targetSegments = targetName.Split('/');
|
|
for (int i = 0; i < targetSegments.Length; i++)
|
|
{
|
|
String targetSegment = targetSegments[i];
|
|
|
|
if (targetSegment.Length == 0)
|
|
{
|
|
throw new InvalidOperationException(Strings.EpmTargetTree_InvalidTargetPath(targetName));
|
|
}
|
|
|
|
if (targetSegment[0] == '@' && i != targetSegments.Length - 1)
|
|
{
|
|
throw new InvalidOperationException(Strings.EpmTargetTree_AttributeInMiddle(targetSegment));
|
|
}
|
|
|
|
EpmTargetPathSegment foundSegment = activeSubSegments.FirstOrDefault(
|
|
segment => segment.SegmentName == targetSegment &&
|
|
(isSyndication || segment.SegmentNamespaceUri == namespaceUri));
|
|
if (foundSegment != null)
|
|
{
|
|
currentSegment = foundSegment;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
activeSubSegments = currentSegment.SubSegments;
|
|
}
|
|
|
|
if (currentSegment.HasContent)
|
|
{
|
|
if (!currentSegment.EpmInfo.Attribute.KeepInContent)
|
|
{
|
|
this.countOfNonContentProperties--;
|
|
}
|
|
|
|
do
|
|
{
|
|
EpmTargetPathSegment parentSegment = currentSegment.ParentSegment;
|
|
parentSegment.SubSegments.Remove(currentSegment);
|
|
currentSegment = parentSegment;
|
|
}
|
|
while (currentSegment.ParentSegment != null && !currentSegment.HasContent && currentSegment.SubSegments.Count == 0);
|
|
}
|
|
}
|
|
|
|
private static bool HasMixedContent(EpmTargetPathSegment currentSegment, bool ancestorHasContent)
|
|
{
|
|
foreach (EpmTargetPathSegment childSegment in currentSegment.SubSegments.Where(s => !s.IsAttribute))
|
|
{
|
|
if (childSegment.HasContent && ancestorHasContent)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (HasMixedContent(childSegment, childSegment.HasContent || ancestorHasContent))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static String GetPropertyNameFromEpmInfo(EntityPropertyMappingInfo epmInfo)
|
|
{
|
|
{
|
|
if (epmInfo.Attribute.TargetSyndicationItem != SyndicationItemProperty.CustomProperty)
|
|
{
|
|
return epmInfo.Attribute.TargetSyndicationItem.ToString();
|
|
}
|
|
else
|
|
{
|
|
return epmInfo.Attribute.TargetPath;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |