|
//------------------------------------------------------------------------------
// <copyright file="PersonalizationStateInfoCollection.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.UI.WebControls.WebParts {
using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.Util;
[Serializable]
public sealed class PersonalizationStateInfoCollection : ICollection {
private Dictionary<Key, int> _indices;
private bool _readOnly;
// Tried to use the generic type List<T> instead, but it's readonly
// implementation returns a different type that is not assignable to List<T>.
// That would require to maintain two different fields, one for the readonly
// collection when set and one for the modifiable collection version.
//
// So, the cleaner solution is to use ArrayList, though it might have a
// slightly slower perf because of explicit casting.
private ArrayList _values;
public PersonalizationStateInfoCollection() {
_indices = new Dictionary<Key, int>(KeyComparer.Default);
_values = new ArrayList();
}
public int Count {
get {
return _values.Count;
}
}
public PersonalizationStateInfo this[string path, string username] {
get {
if (path == null) {
throw new ArgumentNullException("path");
}
Key key = new Key(path, username);
int index;
if (!_indices.TryGetValue(key, out index)) {
return null;
}
return (PersonalizationStateInfo) _values[index];
}
}
public PersonalizationStateInfo this[int index] {
get {
return (PersonalizationStateInfo) _values[index];
}
}
public void Add(PersonalizationStateInfo data) {
if (data == null) {
throw new ArgumentNullException("data");
}
Key key;
UserPersonalizationStateInfo userData = data as UserPersonalizationStateInfo;
if (userData != null) {
key = new Key(userData.Path, userData.Username);
}
else {
key = new Key(data.Path, null);
}
// VSWhidbey 376063: avoid key duplicate, we check here first before we add.
if (_indices.ContainsKey(key)) {
if (userData != null) {
throw new ArgumentException(SR.GetString(SR.PersonalizationStateInfoCollection_CouldNotAddUserStateInfo,
key.Path, key.Username));
}
else {
throw new ArgumentException(SR.GetString(SR.PersonalizationStateInfoCollection_CouldNotAddSharedStateInfo,
key.Path));
}
}
int pos = _values.Add(data);
try {
_indices.Add(key, pos);
}
catch {
// Roll back the first addition to make the whole addition atomic
_values.RemoveAt(pos);
throw;
}
}
public void Clear() {
_values.Clear();
_indices.Clear();
}
public void CopyTo(PersonalizationStateInfo[] array, int index) {
_values.CopyTo(array, index);
}
public IEnumerator GetEnumerator() {
return _values.GetEnumerator();
}
public bool IsSynchronized {
get {
return false;
}
}
public void Remove(string path, string username) {
if (path == null) {
throw new ArgumentNullException("path");
}
Key key = new Key(path, username);
int ipos;
if (!_indices.TryGetValue(key, out ipos)) {
return;
}
Debug.Assert(ipos >= 0 && ipos < _values.Count);
_indices.Remove(key);
try {
_values.RemoveAt(ipos);
}
catch {
// Roll back the first addition to make the whole addition atomic
_indices.Add(key, ipos);
throw;
}
// Readjust the values' indices by -1 where the indices are greater than the removed index
ArrayList al = new ArrayList();
foreach(KeyValuePair<Key,int> de in _indices) {
if (de.Value > ipos) {
al.Add(de.Key);
}
}
foreach (Key k in al) {
_indices[k] = ((int) _indices[k]) - 1;
}
}
public void SetReadOnly() {
if (_readOnly) {
return;
}
_readOnly = true;
_values = ArrayList.ReadOnly(_values);
}
public object SyncRoot {
get {
return this;
}
}
void ICollection.CopyTo(Array array, int index) {
_values.CopyTo(array, index);
}
[Serializable]
private sealed class Key {
public string Path;
public string Username;
internal Key(string path, string username) {
Debug.Assert(path != null);
Path = path;
Username = username;
}
}
[Serializable]
private sealed class KeyComparer : IEqualityComparer<Key> {
internal static readonly IEqualityComparer<Key> Default = new KeyComparer();
bool IEqualityComparer<Key>.Equals(Key x, Key y) {
return (Compare(x, y) == 0);
}
int IEqualityComparer<Key>.GetHashCode(Key key) {
if (key == null) {
return 0;
}
Debug.Assert(key.Path != null);
int pathHashCode = key.Path.ToLowerInvariant().GetHashCode();
int usernameHashCode = 0;
if (key.Username != null) {
usernameHashCode = key.Username.ToLowerInvariant().GetHashCode();
}
return HashCodeCombiner.CombineHashCodes(pathHashCode, usernameHashCode);
}
private int Compare(Key x, Key y) {
if (x == null && y == null) {
return 0;
}
if (x == null) {
return -1;
}
if (y == null) {
return 1;
}
int pathDiff = String.Compare(x.Path, y.Path,
StringComparison.OrdinalIgnoreCase);
if (pathDiff != 0) {
return pathDiff;
}
else {
return String.Compare(x.Username, y.Username,
StringComparison.OrdinalIgnoreCase);
}
}
}
}
}
|