// Brandon Haynes - http://brandonhaynes.org
// Copyright (c) 2008
// by Brandon Haynes
// Please refer to the project license, located at http://www.codeplex.com/DNNLocalization/license
// The above copyright notice and this permission notice shall be included in all copies or substantial portions
// of the Software.
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
//INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
//WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
//USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
namespace BrandonHaynes.DotNetNukeResXBuildProvider
{
public class ResourcePathMetadata
{
#region Public Constants
public static string PatternWithCulture
{
get
{
return @"
(^
(?<namespace>
(?:[^\.]*\.)*? (?# One or more sets of tokens followed by a period)
[^\.]* (?# Followed by a final token)
)
\. (?# ... and a final period, not included in capture)
)?? (?# Zero or one namespace captures, but as few as possible - non-greedy)
(?:(?<typeName>[^\.]*(?:\.(?:ascx|aspx))?)\.) (?# Typename token including ascx or aspx extension)
(?:(?<culture>[^\.]*)\.)? (?# Capture potential culture name)
(?:Portal-(?<portal>\d+)\.)?(?# Optionally capture portalId)
resx
$";
}
}
public static string PatternWithoutCulture
{
get
{
return @"
(^
(?<namespace>
(?:[^\.]*\.)*? (?# One or more sets of tokens followed by a period)
[^\.]* (?# Followed by a final token)
)
\. (?# ... and a final period, not included in capture)
)?? (?# Zero or one namespace captures, but as few as possible - non-greedy)
(?:(?<typeName>[^\.]*(?:\.(?:ascx|aspx))?)\.) (?# Typename token including ascx or aspx token)
(?:Portal-(?<portal>\d+)\.)?(?# Optionally capture portalId)
resx
$";
}
}
#endregion
#region Constructors
public ResourcePathMetadata(string virtualPath)
{
int portalId;
string fileName = Path.GetFileName(virtualPath);
var matches = Regex.Match(fileName, PatternWithCulture, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace);
if (!matches.Success)
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, @"VirtualPath ""{0}"" could not be parsed.", virtualPath), "virtualPath");
else if (!Extensions.TryGetCulture(matches.Groups["culture"].Value, out culture))
matches = Regex.Match(fileName, PatternWithoutCulture, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace);
VirtualPath = virtualPath;
PortalId = int.TryParse(matches.Groups["portal"].Value, out portalId) ? (int?)portalId : null;
Namespace = MakeValidName(FormatNamespace(matches.Groups["namespace"].Value));
TypeName = MakeValidName(matches.Groups["typeName"].Value);
}
#endregion
#region Public Properties
public string VirtualPath { get; private set; }
public string Namespace { get; private set; }
public string TypeName { get; private set; }
public int? PortalId { get; private set; }
private CultureInfo culture;
public CultureInfo Culture
{ get { return culture; } }
private string embeddedName;
public string EmbeddedName
{
get
{
if (embeddedName == null)
{
var tokens = new List<string>(4);
if (!string.IsNullOrEmpty(Namespace))
tokens.Add(Namespace);
tokens.Add(TypeName);
if (Culture != null && !Culture.Equals(CultureInfo.InvariantCulture))
tokens.Add(culture.Name);
tokens.Add("resources");
// Resource must be embedded in all-lowercase characters
embeddedName = string.Join(".", tokens.ToArray()).ToLowerInvariant();
}
return embeddedName;
}
}
private bool? isLocal;
public bool IsLocal
{
get
{
if (isLocal == null)
isLocal = Regex.IsMatch(VirtualPath, "ascx|aspx");
return isLocal.Value;
}
}
public string QualifiedTypeName
{
get
{
return string.IsNullOrEmpty(Namespace) ? TypeName : string.Format(CultureInfo.InvariantCulture, "{0}.{1}", Namespace, TypeName);
}
}
#endregion
#region Private Support Methods
private string FormatNamespace(string baseNamespace)
{
var tokens = new List<string>(4);
if (!IsLocal)
tokens.Add("Resources");
if (!string.IsNullOrEmpty(baseNamespace))
tokens.Add(baseNamespace);
if (PortalId != null)
tokens.Add("Portal" + PortalId.ToString());
return string.Join(".", tokens.ToArray());
}
public static string MakeValidName(string name)
{
return Regex.Replace(name.Trim(), @"(?:^[0-9]*)|[^a-zA-Z0-9.]", "_").TrimStart('_');
}
#endregion
}
}