Commit d2630ea7 authored by Sergey Konovalov's avatar Sergey Konovalov

toXml - writer instead string; refreshedDate

parent a4a58c47
......@@ -75,23 +75,23 @@ namespace codegen
}
public void merge(GenMemberPivot val)
{
if (!string.IsNullOrEmpty(val.sName))
if (string.IsNullOrEmpty(this.sName))
sName = val.sName;
if (!string.IsNullOrEmpty(val.sNamespace))
if (string.IsNullOrEmpty(this.sNamespace))
sNamespace = val.sNamespace;
if (!string.IsNullOrEmpty(val.sType))
if (string.IsNullOrEmpty(this.sType))
sType = val.sType;
if (null != val.oSystemType)
if (null == this.oSystemType)
oSystemType = val.oSystemType;
if (val.bIsAttribute.HasValue)
if (!this.bIsAttribute.HasValue)
bIsAttribute = val.bIsAttribute;
if (!string.IsNullOrEmpty(val.sDefAttribute))
if (string.IsNullOrEmpty(this.sDefAttribute))
sDefAttribute = val.sDefAttribute;
if (val.bQualified.HasValue)
if (!this.bQualified.HasValue)
bQualified = val.bQualified;
if (val.nArrayRank.HasValue)
if (!this.nArrayRank.HasValue)
nArrayRank = val.nArrayRank;
if (val.bIsArrayTypesHidden.HasValue)
if (!this.bIsArrayTypesHidden.HasValue)
bIsArrayTypesHidden = val.bIsArrayTypesHidden;
}
public void completeDefaults()
......@@ -105,7 +105,7 @@ namespace codegen
//[System.Xml.Serialization.XmlElementAttribute("c")]
//public CT_CalcCell[] c {
//bIsArray=true;aArrayTypes=[CT_CalcCell]
//nArrayRank=0;aArrayTypes=[CT_CalcCell];bIsArrayTypesHidden=true
//[System.Xml.Serialization.XmlElementAttribute("b", typeof(CT_Boolean))]
//[System.Xml.Serialization.XmlElementAttribute("d", typeof(CT_DateTime))]
......@@ -114,9 +114,18 @@ namespace codegen
//[System.Xml.Serialization.XmlElementAttribute("n", typeof(CT_Number))]
//[System.Xml.Serialization.XmlElementAttribute("s", typeof(CT_String))]
//public object[] Items {
//nArrayRank=0;aArrayTypes=[CT_Boolean, CT_DateTime, CT_Error, CT_Missing, CT_Number, CT_String];bIsArrayTypesHidden=true
//[System.Xml.Serialization.XmlElementAttribute("consolidation", typeof(CT_Consolidation))]
//[System.Xml.Serialization.XmlElementAttribute("extLst", typeof(CT_ExtensionList))]
//[System.Xml.Serialization.XmlElementAttribute("worksheetSource", typeof(CT_WorksheetSource))]
//public object Item
//{
//nArrayRank=null;aArrayTypes=[CT_Consolidation, CT_ExtensionList, CT_WorksheetSource];bIsArrayTypesHidden=true
//[System.Xml.Serialization.XmlArrayItemAttribute("author", IsNullable=false)]
//public string[] authors {
//nArrayRank=0;aArrayTypes=[string];bIsArrayTypesHidden=false
//[System.Xml.Serialization.XmlArrayItemAttribute("b", typeof(CT_Boolean), IsNullable=false)]
//[System.Xml.Serialization.XmlArrayItemAttribute("d", typeof(CT_DateTime), IsNullable=false)]
......@@ -126,12 +135,7 @@ namespace codegen
//[System.Xml.Serialization.XmlArrayItemAttribute("s", typeof(CT_String), IsNullable=false)]
//[System.Xml.Serialization.XmlArrayItemAttribute("x", typeof(CT_Index), IsNullable=false)]
//public object[][] r {
//[System.Xml.Serialization.XmlElementAttribute("consolidation", typeof(CT_Consolidation))]
//[System.Xml.Serialization.XmlElementAttribute("extLst", typeof(CT_ExtensionList))]
//[System.Xml.Serialization.XmlElementAttribute("worksheetSource", typeof(CT_WorksheetSource))]
//public object Item
//{
//nArrayRank=1;aArrayTypes=[CT_Boolean, CT_DateTime, CT_Error, CT_Missing, CT_Number, CT_String, CT_Index];bIsArrayTypesHidden=false
public class GenClassPivot
{
......@@ -222,6 +226,9 @@ namespace codegen
Queue<GenClassPivot> aTemp = new Queue<GenClassPivot>();
List<GenClassPivot> aRes = new List<GenClassPivot>();
string[] aTargetTypes = new string[] { "CT_PivotCacheDefinition", "CT_PivotCacheRecords", "CT_pivotTableDefinition" };
//string[] aTargetTypes = new string[] { "CT_Workbook" };
//string[] aTargetTypes = new string[] { "CT_Comments" };
Dictionary<string, bool> mapTargetSubTypes = new Dictionary<string, bool>();
Dictionary<string, bool> namspaces = new Dictionary<string, bool>();
......@@ -419,16 +426,19 @@ namespace codegen
{
if (1 == aTempMemebers.Count)
{
oGenMember.merge(aTempMemebers[0]);
GenMemberPivot TempMember = aTempMemebers[0];
TempMember.merge(oGenMember);
TempMember.nArrayRank = null;
}
else
{
oGenMember.aArrayTypes = aTempMemebers;
if (bXmlElementAttribute)
oGenMember.bIsArrayTypesHidden = true;
else
oGenMember.bIsArrayTypesHidden = false;
}
else
{
oGenMember.nArrayRank = null;
}
oGenMember.completeDefaults();
return oGenMember;
......
......@@ -59,10 +59,10 @@ namespace codegen
m_mapProcessedClasses[oGenClass.sName] = oGenClass;
}
string sFileJs = "PivotTables.js";
//string sFileJs = "Workbook.js";
oJsSer.AppendFormat("\"use strict\";\r\n");
oJsSer.AppendFormat(Utils.gc_sFilePrefix);
oJsSer.AppendFormat("function getBoolFromXml(val){{return \"0\"!==val && \"false\"!==val && \"off\"!==val;}}\r\n");
oJsSer.AppendFormat("function getXmlFromBool(val){{return val ? \"1\" : \"0\";}}\r\n");
//enums
ProcessEnums(oJsSer, aEnums);
......@@ -163,11 +163,11 @@ namespace codegen
{
if (oGenClass.isRoot())
{
sb.AppendFormat("{0}.prototype.toXml = function() {{\r\n", oGenClass.sName);
sb.AppendFormat("{0}.prototype.toXml = function(writer) {{\r\n", oGenClass.sName);
}
else
{
sb.AppendFormat("{0}.prototype.toXml = function(name) {{\r\n", oGenClass.sName);
sb.AppendFormat("{0}.prototype.toXml = function(writer, name) {{\r\n", oGenClass.sName);
}
sb.AppendFormat("var res = \"\";\r\n");
ProcessToXml(sb, oGenClass);
......@@ -190,7 +190,23 @@ namespace codegen
{
bNeedDoubleArray = true;
}
if (null == oGenMember.aArrayTypes)
if (null != oGenMember.aArrayTypes)
{
for (int j = 0; j < oGenMember.aArrayTypes.Count; ++j)
{
InfoFromMemberElem(oGenMember.aArrayTypes[j], ref bNeedTextNode);
}
}
else
{
InfoFromMemberElem(oGenMember, ref bNeedTextNode);
}
aMembers.Add(oGenMember);
}
}
}
public void InfoFromMemberElem(GenMemberPivot oGenMember, ref bool bNeedTextNode)
{
if (null != oGenMember.oSystemType)
{
......@@ -208,10 +224,6 @@ namespace codegen
}
}
}
aMembers.Add(oGenMember);
}
}
}
void ProcessProperty(StringBuilder sb, List<GenMemberPivot> aAttributes, List<GenMemberPivot> aMembers, bool bNeedTextNode, bool bNeedDoubleArray)
{
if (aAttributes.Count > 0)
......@@ -237,7 +249,12 @@ namespace codegen
{
GenMemberPivot oGenMember = aMembers[i];
if (oGenMember.nArrayRank.HasValue)
{
if (false != oGenMember.bIsArrayTypesHidden)
sb.AppendFormat("this.{0} = [];\r\n", oGenMember.sName);
else
sb.AppendFormat("this.{0} = null;\r\n", oGenMember.sName);
}
else
{
if (null != oGenMember.aArrayTypes)
......@@ -310,8 +327,9 @@ namespace codegen
}
else
{
sb.AppendFormat("//todo check\r\n", getNameWithPrefix(oGenClass, oGenMember), sCodeName);
sb.AppendFormat("//todo check name duplication\r\n", getNameWithPrefix(oGenClass, oGenMember), sCodeName);
}
sb.AppendFormat("this.{0} = [];\r\n", oGenMember.sName);
sb.AppendFormat("}}\r\n", getNameWithPrefix(oGenClass, oGenMember), sCodeName);
nCounter++;
}
......@@ -383,30 +401,26 @@ namespace codegen
for (int i = 0; i < aMembers.Count; ++i)
{
GenMemberPivot oGenMember = aMembers[i];
nCounter = ProcessOnTextNodeFromXmlMember(sb, oGenClass, oGenMember, null, nCounter);
}
}
int ProcessOnTextNodeFromXmlMember(StringBuilder sb, GenClassPivot oGenClass, GenMemberPivot oGenMember, GenMemberPivot oGenMemberContainer, int nCounter)
{
if (0 != nCounter)
sb.AppendFormat("else ");
sb.AppendFormat("if(\"{0}\" === this._curElem){{\r\n", getNameWithPrefix(oGenClass, oGenMember));
if (null != oGenMember.oSystemType)
{
if (oGenMember.nArrayRank.HasValue)
if (null != oGenMember.aArrayTypes)
{
if (oGenMember.nArrayRank > 0)
for (int j = 0; j < oGenMember.aArrayTypes.Count; ++j)
{
sb.AppendFormat("this._curArray.push({0});\r\n", ProcessJsTypeFromXml(oGenMember.oSystemType, "text"));
nCounter = ProcessOnTextNodeFromXmlMember(sb, oGenClass, oGenMember.aArrayTypes[j], nCounter);
}
}
else
{
sb.AppendFormat("this.{0}.push({1});\r\n", oGenMember.sName, ProcessJsTypeFromXml(oGenMember.oSystemType, "text"));
nCounter = ProcessOnTextNodeFromXmlMember(sb, oGenClass, oGenMember, nCounter);
}
}
else
sb.AppendFormat("this.{0} = {1};\r\n", oGenMember.sName, ProcessJsTypeFromXml(oGenMember.oSystemType, "text"));
}
int ProcessOnTextNodeFromXmlMember(StringBuilder sb, GenClassPivot oGenClass, GenMemberPivot oGenMember, int nCounter)
{
if (null != oGenMember.oSystemType)
{
ProcessOnTextNodeFromXmlMemberPrefix(sb, oGenClass, oGenMember, nCounter);
ProcessOnTextNodeFromXmlMemberElem(sb, oGenMember, ProcessJsTypeFromXml(oGenMember.oSystemType, "text"));
nCounter = ProcessOnTextNodeFromXmlMemberPostfix(sb, nCounter);
}
else if (null != oGenMember.sType)
{
......@@ -415,28 +429,45 @@ namespace codegen
{
if (oTemp.bIsEnum)
{
ProcessOnTextNodeFromXmlMemberPrefix(sb, oGenClass, oGenMember, nCounter);
sb.AppendFormat("var val = {0}(text);\r\n", gc_sEnumFromXmlPrefix + oTemp.sName);
sb.AppendFormat("if(-1 !== val){{\r\n");
ProcessOnTextNodeFromXmlMemberElem(sb, oGenMember, "val");
sb.AppendFormat("}}\r\n");
nCounter = ProcessOnTextNodeFromXmlMemberPostfix(sb, nCounter);
}
}
}
return nCounter;
}
void ProcessOnTextNodeFromXmlMemberPrefix(StringBuilder sb, GenClassPivot oGenClass, GenMemberPivot oGenMember, int nCounter)
{
if (0 != nCounter)
sb.AppendFormat("else ");
sb.AppendFormat("if(\"{0}\" === this._curElem){{\r\n", getNameWithPrefix(oGenClass, oGenMember));
}
int ProcessOnTextNodeFromXmlMemberPostfix(StringBuilder sb, int nCounter)
{
sb.AppendFormat("}}\r\n");
nCounter++;
return nCounter;
}
void ProcessOnTextNodeFromXmlMemberElem(StringBuilder sb, GenMemberPivot oGenMember, string sCodeName)
{
if (oGenMember.nArrayRank.HasValue)
{
if (oGenMember.nArrayRank > 0)
{
sb.AppendFormat("this._curArray.push(val);\r\n");
sb.AppendFormat("this._curArray.push({0});\r\n", sCodeName);
}
else
{
sb.AppendFormat("this.{0}.push(val);\r\n", oGenMember.sName);
sb.AppendFormat("this.{0}.push({1});\r\n", oGenMember.sName, sCodeName);
}
}
else
sb.AppendFormat("this.{0} = val;\r\n", oGenMember.sName);
sb.AppendFormat("}}\r\n");
}
}
}
sb.AppendFormat("}}\r\n");
nCounter++;
return nCounter;
sb.AppendFormat("this.{0} = {1};\r\n", oGenMember.sName, sCodeName);
}
void ProcessOnEndNodeFromXml(StringBuilder sb, GenClassPivot oGenClass, List<GenMemberPivot> aMembers)
{
......@@ -527,15 +558,19 @@ namespace codegen
bool bNeedDoubleArray = false;
InfoFromMember(oGenClass, ref aAttributes, ref aMembers, ref bNeedTextNode, ref bNeedDoubleArray);
string sCodeName;
if (oGenClass.isRoot())
{
sb.AppendFormat("res += \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?>\";\r\n");
sb.AppendFormat("res += \"<{0}{1}\";\r\n", oGenClass.sRootName, gc_sNamespaceToXml);
sCodeName = "\"" + oGenClass.sRootName + "\"";
sb.AppendFormat("writer.WriteXmlString(\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?>\");\r\n");
sb.AppendFormat("writer.WriteXmlNodeStart({0});\r\n", sCodeName);
sb.AppendFormat("writer.WriteXmlString(\"{0}\");\r\n", gc_sNamespaceToXml);
}
else
{
sb.AppendFormat("res += \"<\";\r\n");
sb.AppendFormat("res += name;\r\n");
sCodeName = "name";
sb.AppendFormat("writer.WriteXmlNodeStart({0});\r\n", sCodeName);
}
for (int i = 0; i < aAttributes.Count; ++i)
......@@ -546,16 +581,22 @@ namespace codegen
if (aMembers.Count > 0)
{
sb.AppendFormat("res += \">\";\r\n");
sb.AppendFormat("writer.WriteXmlNodeEnd({0}, true);\r\n", sCodeName);
for (int i = 0; i < aMembers.Count; ++i)
{
GenMemberPivot oGenMember = aMembers[i];
bool bNullCheck = true;
string sCodeElem;
if (oGenMember.nArrayRank > 0)
{
if (false == oGenMember.bIsArrayTypesHidden)
{
sb.AppendFormat("if(null !== {0}){{\r\n", oGenMember.sName);
}
sb.AppendFormat("for(var i = 0; i < this.{0}.length; ++i){{\r\n", oGenMember.sName);
sb.AppendFormat("var elem = this.{0}[i];\r\n", oGenMember.sName);
sCodeElem = "elem";
bNullCheck = false;
}
else
{
......@@ -565,21 +606,42 @@ namespace codegen
{
if (false == oGenMember.bIsArrayTypesHidden)
{
sb.AppendFormat("res += \"<{0}>\";\r\n", getNameWithPrefix(oGenClass, oGenMember));
if (bNullCheck)
sb.AppendFormat("if(null !== {0}){{\r\n", sCodeElem);
sb.AppendFormat("writer.WriteXmlNodeEnd(\"{0}\", true);\r\n", getNameWithPrefix(oGenClass, oGenMember));
}
if (oGenMember.nArrayRank.HasValue)
{
string sCodeSubElem;
if (oGenMember.nArrayRank > 0)
{
sb.AppendFormat("for(var j = 0; j < {0}.length; ++j){{\r\n", sCodeElem);
sb.AppendFormat("var subelem = {0}[j];\r\n", sCodeElem);
sCodeSubElem = "subelem";
}
else
{
sb.AppendFormat("for(var i = 0; i < {0}.length; ++i){{\r\n", sCodeElem);
sb.AppendFormat("var elem = {0}[i];\r\n", sCodeElem);
sCodeSubElem = "elem";
}
if (1 == oGenMember.aArrayTypes.Count)
{
GenMemberPivot oTempMember = oGenMember.aArrayTypes[0];
ProcessMemberToXml(sb, oGenClass, oTempMember, sCodeSubElem, false);
}
else
{
for (int j = 0; j < oGenMember.aArrayTypes.Count; ++j)
{
GenMemberPivot oTempMember = oGenMember.aArrayTypes[j];
if (0 != j)
sb.AppendFormat("else ");
sb.AppendFormat("if(subelem instanceof {0}){{\r\n", oTempMember.sType);
sb.AppendFormat("res += subelem.toXml(\"{0}\");\r\n", getNameWithPrefix(oGenClass, oTempMember));
sb.AppendFormat("if({0} instanceof {1}){{\r\n", sCodeSubElem, oTempMember.sType);
sb.AppendFormat("{0}.toXml(writer, \"{1}\");\r\n", sCodeSubElem, getNameWithPrefix(oGenClass, oTempMember));
sb.AppendFormat("}}\r\n");
}
}
sb.AppendFormat("}}\r\n");
}
else
......@@ -593,42 +655,29 @@ namespace codegen
}
if (false == oGenMember.bIsArrayTypesHidden)
{
sb.AppendFormat("res += \"</{0}>\";\r\n", getNameWithPrefix(oGenClass, oGenMember));
}
}
else
{
if (oGenMember.nArrayRank.HasValue)
{
sb.AppendFormat("for(var i = 0; i < {0}.length; ++i){{\r\n", sCodeElem);
sb.AppendFormat("var elem = {0}[i];\r\n", sCodeElem);
ProcessMemberToXml(sb, oGenClass, oGenMember, "elem", false);
sb.AppendFormat("writer.WriteXmlNodeEnd(\"{0}\");\r\n", getNameWithPrefix(oGenClass, oGenMember));
if (bNullCheck)
sb.AppendFormat("}}\r\n");
}
}
else
{
ProcessMemberToXml(sb, oGenClass, oGenMember, sCodeElem, true);
}
}
if (oGenMember.nArrayRank > 0)
{
sb.AppendFormat("}}\r\n");
}
}
if (oGenClass.isRoot())
if (false == oGenMember.bIsArrayTypesHidden)
{
sb.AppendFormat("res += \"</{0}>\";\r\n", oGenClass.sRootName);
sb.AppendFormat("}}\r\n", oGenMember.sName);
}
}
else
{
sb.AppendFormat("res += \"</\";\r\n");
sb.AppendFormat("res += name;\r\n");
sb.AppendFormat("res += \">\";\r\n");
}
sb.AppendFormat("writer.WriteXmlNodeEnd({0});\r\n", sCodeName);
}
else
sb.AppendFormat("res += \"/>\";\r\n");
sb.AppendFormat("writer.WriteXmlNodeEnd({0}, true, true);\r\n", sCodeName);
}
void ProcessMemberToXml(StringBuilder sb, GenClassPivot oGenClass, GenMemberPivot oGenMember, string sElemName, bool checkNull)
{
......@@ -642,15 +691,7 @@ namespace codegen
if (null != oGenMember.oSystemType)
{
if (bIsAttribute)
sb.AppendFormat("res += \" {0}=\\\"\";\r\n", sElemXmlName);
else
sb.AppendFormat("res += \"<{0}>\";\r\n", sElemXmlName);
sb.AppendFormat("res += {0};\r\n", ProcessJsTypeToXml(oGenMember.oSystemType, sElemName));
if (bIsAttribute)
sb.AppendFormat("res += \"\\\"\";\r\n");
else
sb.AppendFormat("res += \"</{0}>\";\r\n", sElemXmlName);
ProcessJsTypeToXml(sb, sElemXmlName, oGenMember.oSystemType, sElemName, bIsAttribute);
}
else if (null != oGenMember.sType)
{
......@@ -660,20 +701,13 @@ namespace codegen
{
if (oGenClassMember.bIsEnum)
{
if (bIsAttribute)
sb.AppendFormat("res += \" {0}=\\\"\";\r\n", sElemXmlName);
else
sb.AppendFormat("res += \"<{0}>\";\r\n", sElemXmlName);
sb.AppendFormat("res += {0}{1}({2});\r\n", gc_sEnumToXmlPrefix, oGenClassMember.sName, sElemName);
if (bIsAttribute)
sb.AppendFormat("res += \"\\\"\";\r\n");
else
sb.AppendFormat("res += \"</{0}>\";\r\n", sElemXmlName);
string sElemNameEnum = gc_sEnumToXmlPrefix + oGenClassMember.sName + "("+ sElemName + ")";
ProcessJsTypeToXml(sb, sElemXmlName, oGenMember.oSystemType, sElemNameEnum, bIsAttribute);
}
else
{
if (!bIsAttribute)
sb.AppendFormat("res += {0}.toXml(\"{1}\");\r\n", sElemName, sElemXmlName);
sb.AppendFormat("res += {0}.toXml(writer, \"{1}\");\r\n", sElemName, sElemXmlName);
}
}
}
......@@ -682,13 +716,21 @@ namespace codegen
sb.AppendFormat("}}\r\n");
}
}
string ProcessJsTypeToXml(Type oType, string sVal)
void ProcessJsTypeToXml(StringBuilder sb, string sName, Type oType, string sVal, bool bAttribute)
{
string sRes;
switch (Type.GetTypeCode(oType))
{
case TypeCode.Boolean:
sRes = "getXmlFromBool(" + sVal + ")";
if(bAttribute)
{
sb.AppendFormat("writer.WriteXmlAttributeBool(\"{0}\", {1});\r\n", sName, sVal);
}
else
{
sb.AppendFormat("writer.WriteXmlNodeStart(\"{0}\", true);\r\n", sName);
sb.AppendFormat("writer.WriteXmlBool({0});\r\n", sVal);
sb.AppendFormat("writer.WriteXmlNodeEnd(\"{0}\");\r\n", sName);
}
break;
case TypeCode.Byte:
case TypeCode.SByte:
......@@ -700,11 +742,30 @@ namespace codegen
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
sRes = sVal + ".toString()";
if (bAttribute)
{
sb.AppendFormat("writer.WriteXmlAttributeNumber(\"{0}\", {1});\r\n", sName, sVal);
}
else
{
sb.AppendFormat("writer.WriteXmlNodeStart(\"{0}\", true);\r\n", sName);
sb.AppendFormat("writer.WriteXmlNumber({0});\r\n", sVal);
sb.AppendFormat("writer.WriteXmlNodeEnd(\"{0}\");\r\n", sName);
}
break;
default:
if (bAttribute)
{
sb.AppendFormat("writer.WriteXmlAttributeString(\"{0}\", {1});\r\n", sName, sVal);
}
else
{
sb.AppendFormat("writer.WriteXmlNodeStart(\"{0}\", true);\r\n", sName);
sb.AppendFormat("writer.WriteXmlString({0});\r\n", sVal);
sb.AppendFormat("writer.WriteXmlNodeEnd(\"{0}\");\r\n", sName);
}
break;
default: sRes = sVal; break;
}
return sRes;
}
string getNameWithPrefix(GenClassPivot oGenClass, GenMemberPivot oGenMember)
......
......@@ -568,7 +568,7 @@
<xsd:attribute name="optimizeMemory" type="xsd:boolean" use="optional" default="false"/>
<xsd:attribute name="enableRefresh" type="xsd:boolean" use="optional" default="true"/>
<xsd:attribute name="refreshedBy" type="s:ST_Xstring" use="optional"/>
<xsd:attribute name="refreshedDateIso" type="xsd:dateTime" use="optional"/>
<xsd:attribute name="refreshedDate" type="xsd:double" use="optional"/>
<xsd:attribute name="backgroundQuery" type="xsd:boolean" default="false"/>
<xsd:attribute name="missingItemsLimit" type="xsd:unsignedInt" use="optional"/>
<xsd:attribute name="createdVersion" type="xsd:unsignedByte" use="optional" default="0"/>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment