blob: ce3338f5475f2b79bf5e61bca819be314ffa15ed [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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.
//
////////////////////////////////////////////////////////////////////////////////
package UnitTest.Validation
{
import flash.utils.ByteArray;
import flashx.textLayout.conversion.ConversionType;
import flashx.textLayout.conversion.ITextExporter;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.elements.TextFlow;
public class XMLSnapshot
{
private var baselineXMLStack:Array = new Array();
private var currentXMLStack:Array = new Array();
/**
* return line data from the TextFlow in XML
*/
public function takeSnapshot(aFlow:TextFlow, aFormat:String):XML
{
var xmlSnapshot:XML = <{aFormat + "Snapshot"}/>;
// for compatibility with existing snapshots, use the old root tag
// if we ever get to rebase everything, we could remove this line.
//if (aFormat == TextConverter.TEXT_LAYOUT_FORMAT) xmlSnapshot = <XFLSnapshot/>;
var filter:ITextExporter = TextConverter.getExporter(aFormat);
xmlSnapshot = filter.export(aFlow, ConversionType.XML_TYPE) as XML;
var xmlDataBytes:ByteArray = new ByteArray();
xmlSnapshot.normalize();
xmlDataBytes.writeObject (xmlSnapshot);
xmlDataBytes.compress();
xmlDataBytes.uncompress();
xmlSnapshot = new XML(xmlDataBytes.readObject());
xmlSnapshot.normalize();
return xmlSnapshot;
}
/**
* compare the two snapshots
* a list of differences in XML are returned
* null is returned if the snapshots are identical
*/
private function removeExtraSpace(tmpString:String):String
{
var iCount:Number = tmpString.length;
var newString:String = "";
for (var i:Number = iCount; i > 0; i--)
{
var tmpChar:Number = tmpString.charCodeAt(i);
if (!((tmpChar == 32) || (tmpChar == 10)))
newString += tmpString.charAt(i);
}
return newString;
}
public function compare (baseline:XML, current:XML):Boolean
{
var Result:Boolean = true;
baseline.normalize();
current.normalize();
var strBaseline:String = baseline.toXMLString();
var strCurrent:String = current.toXMLString();
if (strBaseline != strCurrent)
Result = false;
return Result;
}
public function compareAdvanced (baseline:XML, current:XML):Boolean
{
baseline.normalize();
current.normalize();
if (!compareElements(baseline, current))
return false;
return compareAdvancedChildren(baseline, current);
}
private function compareAdvancedChildren (baseline:XML, current:XML):Boolean
{
var result:Boolean = true;
var baselineStack:Array = new Array();
var currentStack:Array = new Array();
var baselineChild:XML;
var currentChild:XML;
var baselineChildren:XMLList = baseline.children();
var currentChildren:XMLList = current.children();
for each (baselineChild in baselineChildren)
{
baselineStack.push(baselineChild);
//trace(baselineChild.toString());
}
for each (currentChild in currentChildren)
{
currentStack.push(currentChild);
//trace(currentChild.toString());
}
baselineChild = baselineStack.shift();
currentChild = currentStack.shift();
while ((baselineChild != null) && (currentChild != null) && result)
{
if (!compareElements(baselineChild, currentChild))
return false;
result = compareAdvancedChildren(baselineChild, currentChild);
if (result)
{
baselineChild = baselineStack.shift();
currentChild = currentStack.shift();
}
}
return result;
}
private function compareElements(baselineChild:XML, currentChild:XML):Boolean
{
if (baselineChild.nodeKind() != currentChild.nodeKind())
return false;
else if (baselineChild.name() != currentChild.name())
return false;
else if (baselineChild.text() != currentChild.text())
return false;
else if (baselineChild.children().length() != currentChild.children().length())
return false;
else if (!(compareAttributes (baselineChild, currentChild)))
return false;
return true;
}
public function createDiff (baseline:XML, current:XML):Boolean
{
var Result:Boolean = true;
var baselineStack:Array = new Array();
var currentStack:Array = new Array();
var baselineChild:XML;
var currentChild:XML;
var strProblem:String;
baseline.normalize();
current.normalize();
var baselineChildren:XMLList = baseline.children();
var currentChildren:XMLList = current.children();
for each (baselineChild in baselineChildren)
{
baselineStack.push(baselineChild);
}
for each (currentChild in currentChildren)
{
currentStack.push(currentChild);
}
baselineChild = baselineStack.shift();
currentChild = currentStack.shift();
while ((baselineChild != null) && (currentChild != null))
{
strProblem = "";
if (baselineChild.nodeKind() != currentChild.nodeKind())
{
strProblem = "Type";
//trace("Not the same kind of node.");
// Mark node with problem attribute.
currentChild.@compError = "type";
}
else if (baselineChild.name() != currentChild.name())
{
strProblem = "Name";
//trace("Names not the same.");
currentChild.@compError = "name";
}
else if (baselineChild.text() != currentChild.text())
{
strProblem = "Text";
//trace("Text is not the same");
// Mark node with problem attribute.
currentChild.@compError = "text";
}
else if (baselineChild.children().length() != currentChild.children().length())
{
strProblem = "Count";
//trace("Not the same number of kids.");
}
else if (!(compareAttributes (baselineChild, currentChild)))
{
strProblem = "Attributes";
//trace("Attributes not the same.");
currentChild.@compError = "attribute";
}
baselineXMLStack.push(baselineChild.toString());
createDiff(baselineChild, currentChild);
baselineChild = baselineStack.shift();
currentChild = currentStack.shift();
}
while (baselineChild != null)
{
//trace("A -" + baselineChild.nodeKind() + " - " + baselineChild.name() + " - " + baselineChild.text());
baselineChild.@compError = "extra";
baselineChild = baselineStack.shift();
}
while (currentChild != null)
{
//trace("B -" + currentChild.nodeKind() + " - " + currentChild.name() + " - " + currentChild.text() );
currentChild.@compError = "extra";
currentChild = currentStack.shift();
}
return Result;
}
private function compareAttributes(baseline:XML, current:XML):Boolean
{
var Result:Boolean = true;
var baselineAttributes:XMLList = baseline.attributes();
var baselineAttribute:XML;
var arBaseAttributes:Array = new Array();
var arCurrentAttributes:Array = new Array();
for each (baselineAttribute in baselineAttributes)
{
arBaseAttributes.push({Name:baselineAttribute.name(), Value:baselineAttribute.toString()});
}
var currentAttributes:XMLList = current.attributes();
var currentAttribute:XML;
for each (currentAttribute in currentAttributes)
{
arCurrentAttributes.push({Name:currentAttribute.name(), Value:currentAttribute.toString()});
}
if (arBaseAttributes.length != arCurrentAttributes.length)
Result = false;
else
{
arCurrentAttributes.sortOn("Name");
arBaseAttributes.sortOn("Name");
var tmpBaseAttribute:Object = arCurrentAttributes.shift();
var tmpCurrentAttribute:Object = arBaseAttributes.shift();
while (tmpBaseAttribute != null)
{
if (!((tmpBaseAttribute.Name == tmpCurrentAttribute.Name) && (tmpBaseAttribute.Value == tmpCurrentAttribute.Value)))
{
Result = false;
break;
}
tmpBaseAttribute = arCurrentAttributes.shift();
tmpCurrentAttribute = arBaseAttributes.shift();
}
}
return Result;
}
}
}