diff --git a/PCAxis.Metadata.UnitTest/PCAxis.Metadata.UnitTest.csproj b/PCAxis.Metadata.UnitTest/PCAxis.Metadata.UnitTest.csproj
index ce0b8cc..819ae96 100644
--- a/PCAxis.Metadata.UnitTest/PCAxis.Metadata.UnitTest.csproj
+++ b/PCAxis.Metadata.UnitTest/PCAxis.Metadata.UnitTest.csproj
@@ -6,6 +6,16 @@
false
+
+
+
+
+
+
+ Always
+
+
+
@@ -16,4 +26,8 @@
+
+
+
+
diff --git a/PCAxis.Metadata.UnitTest/UnitTest1.cs b/PCAxis.Metadata.UnitTest/UnitTest1.cs
index 9e08618..e24a044 100644
--- a/PCAxis.Metadata.UnitTest/UnitTest1.cs
+++ b/PCAxis.Metadata.UnitTest/UnitTest1.cs
@@ -1,13 +1,50 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Linq;
namespace PCAxis.Metadata.UnitTest
{
- [TestClass]
- public class UnitTest1
- {
- [TestMethod]
- public void TestMethod1()
- {
- }
- }
+ [TestClass]
+ public class UnitTest1
+ {
+ [TestMethod]
+ public void TestMethod1()
+ {
+ string metaid_raw = "KORTNAVN:aku";
+ string expectedLink = "https://www.ssb.no/aku#om-statistikken";
+ string expectedLinkText = "Om statistikken";
+
+ var metaLinkCreator = new MetaLinkManager();
+ Assert.IsTrue(metaLinkCreator.LoadConfiguration("metadata.config"));
+
+
+ var links = metaLinkCreator.GetTableLinks(metaid_raw, "no");
+ Assert.AreEqual(expectedLink, links[0].Link);
+ Assert.AreEqual(expectedLinkText, links[0].LinkText);
+
+ }
+
+ [TestMethod]
+ public void TestMethod2()
+ {
+ string metaid_raw = "urn:ssb:classification:klass:123";
+ //string expectedLink = "https://www.ssb.no/aku#om-statistikken";
+ //string expectedLinkText = "Om statistikken";
+
+ var metaLinkCreator = new MetaLinkManager();
+ Assert.IsTrue(metaLinkCreator.LoadConfiguration("metadata.config"));
+
+
+ //var links = metaLinkCreator.GetTableLinks(metaid_raw, "no");
+ //Assert.AreEqual(expectedLink, links[0].Link);
+ //Assert.AreEqual(expectedLinkText, links[0].LinkText);
+
+ var varLinks = metaLinkCreator.GetVariableLinks(metaid_raw, "no");
+ // returns empty with orginal code. The problem is that "urn:ssb:classification:klass" id the system Id
+ // , but : is the parameter separator , so things get confusing :-)
+ Assert.IsTrue(varLinks.Count() > 0, "No link for variable");
+
+
+ }
+
+ }
}
diff --git a/PCAxis.Metadata.UnitTest/metadata.config b/PCAxis.Metadata.UnitTest/metadata.config
new file mode 100644
index 0000000..9477580
--- /dev/null
+++ b/PCAxis.Metadata.UnitTest/metadata.config
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PCAxis.Metadata/MetaLinkManagerNorway_cs.txt b/PCAxis.Metadata/MetaLinkManagerNorway_cs.txt
new file mode 100644
index 0000000..5a47941
--- /dev/null
+++ b/PCAxis.Metadata/MetaLinkManagerNorway_cs.txt
@@ -0,0 +1,503 @@
+using PCAxis.Metadata;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Xml;
+
+namespace Norway.PCAxis.Metadata
+{
+ ///
+ /// Class that encapsulates a metadata.config file containing link-definitions to metadata systems
+ ///
+ public class MetaLinkManager : IMetaIdProvider
+ {
+ ///
+ /// Class holding format information for a link
+ ///
+ private class MetaLinkFormat
+ {
+ ///
+ /// Format of the link text
+ ///
+ public string LinkTextFormat { get; set; }
+
+ ///
+ /// Format of the link (URL)
+ ///
+ public string LinkFormat { get; set; }
+
+ ///
+ /// Hyperlink target
+ /// Valid values:
+ /// _blank - Load in new window
+ /// _self - Load in the same frame as it was clicked
+ /// _parent - Load in the parent frameset
+ /// _top - Load in the full body of the window
+ /// framename - Load in named frame
+ ///
+ public string Target { get; set; }
+
+ ///
+ /// Get number of expected parameters to the text link
+ ///
+ ///
+ public int NumberOfTextParameters()
+ {
+ return GetNumberOfParameters(LinkTextFormat);
+ }
+
+ ///
+ /// Get number of expected parameters to the link
+ ///
+ ///
+ public int NumberOfLinkParameters()
+ {
+ return GetNumberOfParameters(LinkFormat);
+ }
+
+ ///
+ /// Internal method for finding the number of expected parameters
+ ///
+ ///
+ ///
+ private int GetNumberOfParameters(string txt)
+ {
+ int count = 0;
+ int paramIndex = 0;
+ int index = 0;
+ bool ok = true;
+
+ if (string.IsNullOrWhiteSpace(txt))
+ {
+ return 0;
+ }
+
+
+ while (ok)
+ {
+ index = txt.IndexOf("{" + paramIndex.ToString() + "}", index); // Find {0}, next time {1} and so on...
+ if (index != -1)
+ {
+ count += 1;
+ paramIndex += 1;
+ }
+ else
+ {
+ ok = false;
+ }
+ }
+
+ return count;
+ }
+ }
+
+
+
+
+
+ #region "Private fields"
+
+ ///
+ /// Configuration file
+ ///
+ XmlDocument _xdoc;
+
+ ///
+ /// List of available metadata systems
+ ///
+ private List _metadataSystems;
+
+ private HashSet _ignoreMetaidPrefixList = new HashSet();
+
+ ///
+ /// Dictionary of metadata systems containing table information.
+ /// Key = Metadata system id, Value = dictionary of linkformats per language (key = language, value = linkformat-object).
+ ///
+ private Dictionary> _tableLinkFormats;
+
+ ///
+ /// Dictionary of metadata systems containing variable information.
+ /// Key = Metadata system id, Value = dictionary of linkformats per language (key = language, value = linkformat-object).
+ ///
+ private Dictionary> _variableLinkFormats;
+
+ ///
+ /// Dictionary of metadata systems containing value information.
+ /// Key = Metadata system id, Value = dictionary of linkformats per language (key = language, value = linkformat-object).
+ ///
+ private Dictionary> _valueLinkFormats;
+
+ ///
+ /// Logging to Log4Net
+ ///
+ private static log4net.ILog _logger = log4net.LogManager.GetLogger(typeof(MetaLinkManager));
+
+ ///
+ /// Character that separates the systems within a META-ID
+ ///
+ private char[] _systemSeparator = { ',' };
+
+ ///
+ /// Character that separates the parameters within a system META-ID
+ ///
+ private char[] _paramSeparator = { ':' };
+
+ ///
+ /// Integer that defines how many parametes a metaIdsystem consist of
+ ///
+ private int _numberOfMetaIdParams;
+
+ #endregion
+
+
+
+
+
+ ///
+ /// Constructor
+ ///
+ public MetaLinkManager()
+ {
+ _metadataSystems = new List();
+ _tableLinkFormats = new Dictionary>();
+ _variableLinkFormats = new Dictionary>();
+ _valueLinkFormats = new Dictionary>();
+ }
+
+ ///
+ /// Returns the param separator
+ ///
+ ///
+ public char[] GetParamSeparator()
+ {
+ return _paramSeparator;
+ }
+
+ ///
+ /// Returns the system separator
+ ///
+ ///
+ public char[] GetSystemSeparator()
+ {
+ return _systemSeparator;
+ }
+
+ ///
+ /// Load metadata.config file
+ ///
+ /// Path to the configuration file
+ /// True if the configuration file was successfully loaded, else false
+ public bool LoadConfiguration(string configurationFile)
+ {
+ if (!System.IO.File.Exists(configurationFile))
+ {
+ _logger.ErrorFormat("Metadata configuration file '{0}' does not exist", configurationFile);
+ return false;
+ }
+
+ _xdoc = new XmlDocument();
+ _xdoc.Load(configurationFile);
+
+ // Table-level
+ LoadConfigurationSection("onTable", _tableLinkFormats);
+
+ // Variable-level
+ LoadConfigurationSection("onVariable", _variableLinkFormats);
+
+ // Value-level
+ LoadConfigurationSection("onValue", _valueLinkFormats);
+
+ return true;
+ }
+
+ ///
+ /// Load sub section of the configuration file
+ ///
+ /// Name of the section
+ /// Dictionary to store section data in
+ ///
+ private bool LoadConfigurationSection(string section, Dictionary> dictionary)
+ {
+ string xpath;
+ XmlNode node;
+ XmlNodeList xmlnodes;
+
+ xpath = "/metaId/" + section;
+ node = _xdoc.SelectSingleNode(xpath);
+
+ // Find all system nodes to ignore
+ xpath = ".//ignoreMetaSystem";
+ xmlnodes = node.SelectNodes(xpath);
+
+ foreach (XmlNode ignoreSysNode in xmlnodes)
+ {
+ string sysIdIgnore = ignoreSysNode.Attributes["id"].Value; // system id to ignore
+
+ if (!_ignoreMetaidPrefixList.Contains(sysIdIgnore))
+ {
+ _ignoreMetaidPrefixList.Add(sysIdIgnore);
+ }
+ }
+
+ // Find all system nodes
+ xpath = ".//metaSystem";
+ xmlnodes = node.SelectNodes(xpath);
+
+ foreach (XmlNode sysNode in xmlnodes)
+ {
+ string sysId = sysNode.Attributes["id"].Value; // system id
+
+ if (!string.IsNullOrWhiteSpace(sysId))
+ {
+ AddMetadataSystem(sysId);
+
+ if (!dictionary.ContainsKey(sysId))
+ {
+ dictionary.Add(sysId, new Dictionary()); // add system to dictionary
+
+ // Find all language nodes for the system
+ xpath = ".//link";
+ XmlNodeList langNodes = sysNode.SelectNodes(xpath);
+
+ foreach (XmlNode langNode in langNodes)
+ {
+ string language = langNode.Attributes["px-lang"].Value;
+ string textFormat = langNode.Attributes["labelStringFormat"].Value;
+ string linkFormat = langNode.Attributes["urlStringFormat"].Value;
+ string target;
+ if ((langNode.Attributes["target"] != null) && (!string.IsNullOrEmpty(langNode.Attributes["target"].Value)))
+ {
+ target = langNode.Attributes["target"].Value;
+ }
+ else
+ {
+ target = "_blank";
+ }
+
+ if (!string.IsNullOrWhiteSpace(language) && !string.IsNullOrWhiteSpace(textFormat) && !string.IsNullOrWhiteSpace(linkFormat))
+ {
+ if (!dictionary[sysId].ContainsKey(language))
+ {
+ MetaLinkFormat format = new MetaLinkFormat();
+ format.LinkTextFormat = textFormat;
+ format.LinkFormat = linkFormat;
+ format.Target = target;
+
+ dictionary[sysId].Add(language, format); // Add format for this language to dictionary
+ }
+ }
+ }
+
+ }
+ }
+
+ }
+
+ return true;
+ }
+
+
+ ///
+ /// Add metadatasystem to list of available systems
+ ///
+ /// Id of the metadatasystem
+ private void AddMetadataSystem(string system)
+ {
+ foreach (MetadataSystem sys in _metadataSystems)
+ {
+ if (sys.ID.Equals(system))
+ {
+ return;
+ }
+ }
+
+ _metadataSystems.Add(new MetadataSystem(system, system));
+ }
+
+ private bool IsMetaIdInIgnoreList(string metaId)
+ {
+ return _ignoreMetaidPrefixList.Any(x => metaId.StartsWith(x + ":"));
+ }
+
+ ///
+ /// Create links
+ ///
+ /// META-ID
+ /// Language
+ /// Dictionary containing the link formats
+ ///
+ private MetaLink[] GetLinks(string metaIdList, string language, Dictionary> dictionary)
+ {
+ List lst = new List();
+
+ string[] metaIds = metaIdList.Split(_systemSeparator, StringSplitOptions.RemoveEmptyEntries);
+
+ foreach (string metaId in metaIds)
+ {
+ string theMetadataSystemId = "";
+
+ foreach (string aMetadataSystemId in dictionary.Keys)
+ {
+ if (metaId.StartsWith(aMetadataSystemId))
+ {
+ theMetadataSystemId = aMetadataSystemId;
+ break;
+ }
+ }
+
+ if (String.IsNullOrEmpty(theMetadataSystemId))
+ {
+ if (!IsMetaIdInIgnoreList(metaId))
+ {
+ _logger.ErrorFormat("Cant find MetadataSystem for {0}", metaId);
+ }
+
+ continue;
+ }
+
+ string rawParamsString = metaId.Replace(theMetadataSystemId, "");
+ string[] linkParams = rawParamsString.Split(_paramSeparator, StringSplitOptions.RemoveEmptyEntries);
+
+ //
+ if (dictionary[theMetadataSystemId].ContainsKey(language))
+ {
+
+ // Get format object from dictionary
+ MetaLinkFormat format = dictionary[theMetadataSystemId][language];
+
+ MetaLink lnk = new MetaLink();
+ lnk.System = theMetadataSystemId;
+
+
+ try
+ {
+ // Create link text
+ if (theMetadataSystemId == "urn:ssb:classification:klass")
+ {
+ lnk.LinkText = GetKlassHeaderFromAPI(linkParams[0], format.Target);
+ if (string.IsNullOrEmpty(lnk.LinkText))
+ {
+ //lnk.Link = string.Format(format.LinkFormat, linkParams);
+ lnk.LinkText = string.Format(format.LinkTextFormat, linkParams);
+ }
+ lnk.Link = string.Format(format.LinkFormat, linkParams);
+ }
+ else if (theMetadataSystemId == "urn:ssb:contextvariable:common")
+ {
+ lnk.Link = string.Format(format.LinkFormat, linkParams) + "&lang=" + language;
+ lnk.LinkText = string.Format(format.LinkTextFormat, linkParams);
+ }
+ else
+ {
+ lnk.Link = string.Format(format.LinkFormat, linkParams);
+ lnk.LinkText = string.Format(format.LinkTextFormat, linkParams);
+ }
+
+
+ // Create the link
+ //lnk.Link = string.Format(format.LinkFormat, linkParams);
+ lnk.Target = format.Target;
+
+ // Add link to the return-list
+ lst.Add(lnk);
+ }
+ catch (System.FormatException e)
+ {
+ _logger.ErrorFormat("Problem for metadataSystem {0}, rawParamsString {1}", theMetadataSystemId, rawParamsString);
+ _logger.Error("The problem: ", e);
+ }
+
+ }
+ }
+
+
+
+ return lst.ToArray();
+ }
+
+
+ private int GetNumberOfSystemParameters(string systemId)
+ {
+ try
+ {
+ return systemId.Split(_paramSeparator[0]).Length;
+ }
+ catch
+ {
+ return 1;
+ }
+ }
+ private String getSystemMetaId(object[] systemLinkParams, int _numberOfMetaIdParams)
+ {
+ string sysId = "";
+ if (_numberOfMetaIdParams < systemLinkParams.Length)
+ {
+ for (int i = 0; i < _numberOfMetaIdParams; i++)
+ {
+ sysId += (string)systemLinkParams[i] + ":";
+ }
+ sysId = sysId.Remove(sysId.LastIndexOf(":"));
+ }
+ return sysId;
+ }
+
+
+ #region "Implementation of IMetaIdProvider"
+
+ public bool Initialize(string configurationFile)
+ {
+ return LoadConfiguration(configurationFile);
+ }
+
+ public MetadataSystem[] MetadataSystems
+ {
+ get
+ {
+ return _metadataSystems.ToArray();
+ }
+ }
+
+ public MetaLink[] GetTableLinks(string metaId, string language)
+ {
+ return GetLinks(metaId, language, _tableLinkFormats);
+ }
+
+ public MetaLink[] GetVariableLinks(string metaId, string language)
+ {
+ return GetLinks(metaId, language, _variableLinkFormats);
+ }
+
+ public MetaLink[] GetValueLinks(string metaId, string language)
+ {
+ return GetLinks(metaId, language, _valueLinkFormats);
+ }
+
+ public String GetKlassHeaderFromAPI(string id, string target)
+ {
+ try
+ {
+ var klassUrl = string.Format(target, id);
+ WebRequest objRequest = HttpWebRequest.Create(klassUrl);
+ objRequest.Timeout = 3000; //No time for config now....
+
+ using (WebResponse objResponse = objRequest.GetResponse())
+ {
+ using (var sr = new System.IO.StreamReader(objResponse.GetResponseStream(), System.Text.Encoding.UTF8))
+ {
+ var rawString = sr.ReadToEnd();
+ var json = JObject.Parse(rawString);
+ return (string)json["name"];
+ }
+ }
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+
+ #endregion
+ }
+}