/*
* Copyright IBM Corp. 2011
*
* Licensed 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 xsp.extlib.designer.test.visualizations;
import junit.framework.TestCase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import xsp.extlib.designer.junit.util.TestDesignerProject;
import com.ibm.commons.iloader.node.IAttribute;
import com.ibm.commons.iloader.node.IClassDef;
import com.ibm.commons.iloader.node.ICollection;
import com.ibm.commons.iloader.node.IMember;
import com.ibm.commons.iloader.node.IObjectCollection;
import com.ibm.commons.iloader.node.IValueCollection;
import com.ibm.commons.iloader.node.NodeException;
import com.ibm.commons.util.StringUtil;
import com.ibm.commons.xml.DOMUtil;
import com.ibm.commons.xml.XMLException;
import com.ibm.designer.domino.xsp.api.util.XPagesDOMUtil;
import com.ibm.designer.domino.xsp.editpart.ExtendedDesignTimeJSContext;
import com.ibm.designer.domino.xsp.internal.loaders.XFacesDOMLoader;
import com.ibm.designer.domino.xsp.internal.loaders.XFacesMultiObjDOMLoader;
import com.ibm.jscript.InterpretException;
import com.ibm.jscript.macro.MacroProcessor;
import com.ibm.jscript.types.FBSCustomObject;
import com.ibm.jscript.types.FBSNumber;
import com.ibm.jscript.types.FBSObject;
import com.ibm.jscript.types.FBSUtility;
import com.ibm.jscript.types.FBSValue;
import com.ibm.xsp.extlib.designer.tooling.visualizations.AbstractCommonControlVisualizer;
import com.ibm.xsp.library.StandardRegistryMaintainer;
import com.ibm.xsp.registry.FacesDefinition;
import com.ibm.xsp.registry.FacesSharableRegistry;
public abstract class AbstractVisualizationTest extends TestCase {
boolean debug = false;
public static String EXT_LIB_NAMESPACE_URI = "http://www.ibm.com/xsp/coreex";
public static String EXT_LIB_PREFIX = "xe";
public static String LINE_DELIMITER = "\r\n";
public static final String START_SCRIPLET_TAG = "<%";
public static final String START_SCRIPLET_VALUE_TAG = "<%=";
public static final String END_SCRIPLET_TAG = "%>";
public AbstractCommonControlVisualizer _visualizationFactory;
public Node _nodeToVisualize;
/**
* This method should return whether or not the markup of the visualization should be static
* @return boolean indicating if the markup of the control is static.
*/
public abstract boolean isRenderMarkupStatic();
/**
* This method should return the xsp-markup that is the expected result of calling
* getFullXSPMarkupForControl() of the visualization factory.
* @return String representing the full xsp-markup expected to be returned by the visualization factory.
*/
public abstract String getExpectedFullXSPMarkup();
/**
* This method should return the xsp-markup that is the expected result of calling
* getFullXSPMarkupForControl() of the visualization factory and then putting that markup through
* the javascript preprocessor. Basically this should return the source that is actually rendered
* by the XPage.
* @return String representing the processed full xsp-markup expected to be returned by the visualization factory.
*/
public abstract String getExpectedProcessedFullXSPMarkup();
/**
* This method should return the xsp-markup that is the expected result of calling
* getXSPMarkupForControl() of the visualization factory.
* @return String representing the xsp-markup expected to be returned by the visualization factory.
*/
public abstract String getExpectedXSPMarkup();
/**
* This method is used to determine what tag the factory is visualizing. This is used to create the
* node passed into the visualization factory when calling getFullXSPMarkup and getXSPMarkup.
* @return the tagName of the tag this factory is visualizing.
*/
public abstract String getTagName();
/**
* This method is used to determine what tag the factory is visualizing. This is used to create the
* node passed into the visualization factory when calling getFullXSPMarkup and getXSPMarkup.
* @return the namespaceURI of the tag this factory is visualizing.
*/
public abstract String getNamespaceURI();
//These are the objects we use to create the visualizations and run the macro processor.
public FacesSharableRegistry _facesRegistry;
public XFacesMultiObjDOMLoader _loader;
/*
* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
//set up the variables we need for the tests
_facesRegistry = StandardRegistryMaintainer.getStandardRegistry();
_loader = new XFacesMultiObjDOMLoader(new TestDesignerProject(_facesRegistry));
String namespaceURI = getNamespaceURI();
String tagName = getTagName();
String prefix = getPrefixForNamespaceURI(namespaceURI);
String docContents = getBlankXPageContents();
if(StringUtil.isNotEmpty(docContents)){
Document doc = createDocument(docContents);
if(null != doc){
if(StringUtil.isNotEmpty(namespaceURI) && StringUtil.isNotEmpty(prefix)){
_nodeToVisualize = doc.createElementNS(namespaceURI, XPagesDOMUtil.createQualifiedTagName(prefix, tagName));
}
}
}
}
/*
* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
@Override
protected void tearDown() throws Exception {
super.tearDown();
_visualizationFactory = null;
}
/**
* This method will test if the isStaticMarkup() method of the visualization factory returns the correct result.
* Child classes must implement isRenderMarkupStatic() which is used to determine if the markup generated by
* visualization factory should be static or dynamic.
*/
public void testIsStaticMarkup() {
boolean isStaticInVisualizer = _visualizationFactory.isStaticMarkup();
boolean shouldBeStatic = isRenderMarkupStatic();
if(!shouldBeStatic == isStaticInVisualizer){
StringBuilder message = new StringBuilder();
message.append("FAIL - Render markup for visualization is ");
if(!shouldBeStatic){
message.append("not ");
}
message.append("static but the visualizer returned that it is ");
if(!isStaticInVisualizer){
message.append("not ");
}
message.append("static");
fail(message.toString());
}
else{
StringBuilder message = new StringBuilder();
message.append("SUCCESS - Render markup for visualization is ");
if(!shouldBeStatic){
message.append("not ");
}
message.append("static and the visualizer returned that it is ");
if(!isStaticInVisualizer){
message.append("not ");
}
message.append("static");
System.out.println(message.toString());
}
}
/**
* This method will test if the control/tag that the visualization factory is providing a
* visualization for exists in the registry
*/
public void testDoesControlExist() {
FacesDefinition def = _facesRegistry.findDef(getNamespaceURI(),getTagName());
if(null == def){
fail("Fail - the tag that this factory is trying to visualize does not exist");
}
}
/**
* This method test that the markup returned by getXSPMarkupForControl in the control visualization factory matches
* the expected markup from getExpectedXSPMarkup
* @throws Exception
*/
public void testGetXSPMarkupForControl() throws Exception {
if(null == _nodeToVisualize){
fail("Fail - Failed to generate the DOM node for the visualization factory to provide render-markup for");
}
else{
if(null == _visualizationFactory){
fail("Fail - Failed to create visualization factory");
}
else{
String returnedMarkup = _visualizationFactory.getXSPMarkupForControl(_nodeToVisualize, null, _facesRegistry);
if(StringUtil.isNotEmpty(returnedMarkup)){
String expectedMarkup = getExpectedXSPMarkup();
if(StringUtil.isNotEmpty(expectedMarkup)){
boolean equal = compareMarkup(returnedMarkup, expectedMarkup);
if(!equal){
fail("FAIL - returned markup from getXSPMarkupForControl did not match expected markup from getExpectedXSPMarkup");
}
else{
System.out.println("SUCCESS - returned markup from getXSPMarkupForControl matched expected markup from getExpectedXSPMarkup");
return;
}
}
else{
fail("FAIL - markup returned by getExpectedXSPMarkup was empty or null");
}
}
else{
fail("FAIL - markup returned by getXSPMarkupForControl was empty or null");
}
}
}
fail("FAIL - unknown error occurred while executing testGetXSPMarkupForControl");
}
/**
* This method test that the markup returned by getFullXSPMarkupForControl in the control visualization factory matches
* the expected markup from getExpectedFullXSPMarkup
* @throws Exception
*/
public void testGetFullXSPMarkupForControl() throws Exception{
if(null == _nodeToVisualize){
fail("Fail - Failed to generate the DOM node for the visualization factory to provide render-markup for");
}
else{
if(null == _visualizationFactory){
fail("Fail - Failed to create visualization factory");
}
else{
String returnedMarkup = _visualizationFactory.getFullXSPMarkupForControl(_nodeToVisualize, _facesRegistry);
if(StringUtil.isNotEmpty(returnedMarkup)){
String expectedMarkup = getExpectedFullXSPMarkup();
if(StringUtil.isNotEmpty(expectedMarkup)){
boolean equal = compareMarkup(returnedMarkup, expectedMarkup);
if(!equal){
fail("FAIL - returned markup from getFullXSPMarkupForControl did not match expected markup from getExpectedFullXSPMarkup");
}
else{
System.out.println("SUCCESS - returned markup from getFullXSPMarkupForControl matched expected markup from getExpectedFullXSPMarkup");
return;
}
}
else{
fail("FAIL - markup returned by getExpectedFullXSPMarkup was empty or null");
}
}
else{
fail("FAIL - markup returned by getFullXSPMarkupForControl was empty or null");
}
}
}
fail("FAIL - unknown error occurred while executing testGetFullXSPMarkupForControl");
}
/**
* This method test that the processed markup returned by getFullXSPMarkupForControl in the control visualization factory matches
* the expected markup from getExpectedProcessedFullXSPMarkup
* @throws Exception
*/
public void testGetProcessedFullXSPMarkupForControl() throws Exception{
if(null == _nodeToVisualize){
fail("Fail - Failed to generate the DOM node for the visualization factory to provide render-markup for");
}
else{
if(null == _visualizationFactory){
fail("Fail - Failed to create visualization factory");
}
else{
String returnedMarkup = _visualizationFactory.getFullXSPMarkupForControl(_nodeToVisualize, _facesRegistry);
if(StringUtil.isNotEmpty(returnedMarkup)){
//run the markup through the preprocessor
returnedMarkup = processMarkup(returnedMarkup);
String expectedMarkup = getExpectedProcessedFullXSPMarkup();
if(StringUtil.isNotEmpty(expectedMarkup)){
boolean equal = compareProcessedMarkup(returnedMarkup, expectedMarkup);
if(!equal){
fail("FAIL - returned processed markup from getFullXSPMarkupForControl did not match expected markup from getExpectedProcessedFullXSPMarkup");
}
else{
System.out.println("SUCCESS - returned processed markup from getFullXSPMarkupForControl matched expected markup from getExpectedProcessedFullXSPMarkup");
return;
}
}
else{
fail("FAIL - markup returned by getExpectedProcessedFullXSPMarkup was empty or null");
}
}
else{
fail("FAIL - markup returned by getFullXSPMarkupForControl was empty or null");
}
}
}
fail("FAIL - unknown error occurred while executing testGetProcessedFullXSPMarkupForControl");
}
/**
* This method test that the processed markup returned by getFullXSPMarkupForControl in the control visualization is valid
* @throws Exception
*/
public void testIsFullXSPMarkupForControlValid() throws Exception{
if(null == _nodeToVisualize){
fail("Fail - Failed to generate the DOM node for the visualization factory to provide render-markup for");
}
else{
if(null == _visualizationFactory){
fail("Fail - Failed to create visualization factory");
}
else{
String returnedMarkup = _visualizationFactory.getFullXSPMarkupForControl(_nodeToVisualize, _facesRegistry);
if(StringUtil.isNotEmpty(returnedMarkup)){
boolean valid = isReturnedMarkupValid(returnedMarkup);
if(valid){
System.out.println("SUCCESS - Processed markup from getFullXSPMarkupForControl is valid");
return;
}
else{
fail("FAIL - Processed markup returned by getFullXSPMarkupForControl is not valid XSP Markup");
}
}
else{
fail("FAIL - markup returned by getFullXSPMarkupForControl was empty or null");
}
}
}
fail("FAIL - unknown error occurred while executing testGetFullXSPMarkupForControl");
}
/**
* Helper method to check if the given markup is valid. The markup is run through the macro processor
* and the results returned and checked for validity.
* @param markup
* @return true if the generated source is valid, false otherwise.
*/
public boolean isReturnedMarkupValid(String markup){
//process the markup
String processedMarkup = processMarkup(markup);
//Check to see if the markup brought back by the preprocessor is valid
boolean valid = false;
//if we have processed markup
if(StringUtil.isNotEmpty(processedMarkup)){
//check to see if it is valid
valid = isMarkupValid(processedMarkup);
}
return valid;
}
/**
* Private method to put the returned xsp markup through the javascript preprocessor.
* @param markup
* @return the processed markup
*/
public String processMarkup(String markup){
MacroProcessor macroProc = new MacroProcessor(ExtendedDesignTimeJSContext.getJSContext());
String processedMarkup = "";
try{
FBSObject _this = new XPagesObject(_loader,_nodeToVisualize);
macroProc.setThis(_this);
processedMarkup = macroProc.process(markup);
}
catch(Exception e){
//do nothing
}
return processedMarkup;
}
/**
* We try to create a doc with the source. If we can then its valid. If we can't then its not valid
* and return false. Return true otherwise.
* @param source
* @return whether or not we can successfully create a document with the given markup.
*/
public boolean isMarkupValid(String source){
if(StringUtil.isNotEmpty(source)){
//create a document from the source to pass into the xsp Validator
Document xspDoc = null;
try{
xspDoc = DOMUtil.createDocument(source);
if(null != xspDoc){
//if we managed to create the doc then the markup was valid.
return true;
}
}
catch (XMLException xmlEx){
return false;
}
}
return false;
}
/**
* This is a helper method that will return the standard opening xp:view tag that is used by most of the
* visualization factories
* @return an opening xp:view tag with standard configuration
*/
public String getDefaultXPageHeader(){
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
strBuilder.append(LINE_DELIMITER);
strBuilder.append("<xp:view xmlns:xp=\"http://www.ibm.com/xsp/core\">");
strBuilder.append(LINE_DELIMITER);
return strBuilder.toString();
}
/**
* This is a helper method that will return the standard closing xp:view tag that is used by all of the
* visualization factories to this point.
* @return a standard closing xp:view tag
*/
public String getDefaultXPageFooter(){
StringBuilder strBuilder = new StringBuilder();
strBuilder.append(LINE_DELIMITER);
strBuilder.append("</xp:view>");
strBuilder.append(LINE_DELIMITER);
return strBuilder.toString();
}
/**
* Simple helper method to return the default contents of an XPage.
* We use this to generate a document we then use to create a child node
* to pass into the visualizer. This method will give us a property configured
* view node with the namespaces already configured.
* @return
*/
public String getBlankXPageContents(){
return getDefaultXPageHeader() + getDefaultXPageFooter();
}
/**
* Private method to return a matching prefix for a given namespaceURI.
* @param namespaceURI
* @return the matching prefix for that given namespaceURI.
*/
public String getPrefixForNamespaceURI(String namespaceURI){
if(StringUtil.equals(namespaceURI, EXT_LIB_NAMESPACE_URI)){
return EXT_LIB_PREFIX;
}
return null;
}
/**
* This method will compare the markup returned by the visualization factory to the
* markup expected by the test case.
* @param returnedMarkup - the markup returned by the visualization factory
* @param expectedMarkup - the markup we expect to have been returned by the visualization factory
* @return true if the markup matches, false otherwise.
*/
public boolean compareMarkup(String returnedMarkup, String expectedMarkup){
if(StringUtil.isNotEmpty(returnedMarkup) && StringUtil.isNotEmpty(expectedMarkup)){
//handle the standard case first where the strings match out of the box.
boolean equal = StringUtil.equals(returnedMarkup, expectedMarkup);
if(equal){
pringDebug(returnedMarkup, expectedMarkup, "compareMarkup unchanged markup before stipping line delims etc..");
return true;
}
else{
//if the visualization is static and does contain any scriplet tags, then line delimiters have no
//effect on whether or not the markup will render. So stip out line delims and try the compare again.
//We use a case sensitive string compare on the off chance case is important in any labels used.
boolean returnedMarkupContainsScript = containsScript(returnedMarkup);
boolean expectedMarkupContainsScript = containsScript(expectedMarkup);
if((returnedMarkupContainsScript && ! expectedMarkupContainsScript) ||
(!returnedMarkupContainsScript && expectedMarkupContainsScript)){
pringDebug(returnedMarkup, expectedMarkup, "compareMarkup one with script one without");
//if one contains script and the other doesn't, then they are not the same.
return false;
}
else if(!returnedMarkupContainsScript && !expectedMarkupContainsScript){
//no script in either markup blobs. So strip out line delims. Leave spaces and tabs in case they are important.
returnedMarkup = stripMarkup(returnedMarkup);
expectedMarkup = stripMarkup(expectedMarkup);
pringDebug(returnedMarkup, expectedMarkup, "compareMarkup no script");
return StringUtil.equals(returnedMarkup, expectedMarkup);
}
else{
//both contain script, so we have to do a bit more work to figure out if they are equal.
//strip out line delims only where they are definitely not needed. (i.e. ouside of the script tags.)
returnedMarkup = stripMarkupContainingScript(returnedMarkup);
expectedMarkup = stripMarkupContainingScript(expectedMarkup);
pringDebug(returnedMarkup, expectedMarkup, "compareMarkup with script");
return StringUtil.equals(returnedMarkup, expectedMarkup);
}
}
}
return false;
}
/**
* This method will compare the markup returned by the visualization factory to the
* markup expected by the test case.
* @param returnedMarkup - the processed markup returned by the visualization factory
* @param expectedMarkup - the processed markup we expect to have been returned by the visualization factory
* @return true if the markup matches, false otherwise.
*/
public boolean compareProcessedMarkup(String returnedMarkup, String expectedMarkup){
if(StringUtil.isNotEmpty(returnedMarkup) && StringUtil.isNotEmpty(expectedMarkup)){
//handle the standard case first where the strings match out of the box.
boolean equal = StringUtil.equals(returnedMarkup, expectedMarkup);
if(equal){
return true;
}
else{
//there should be no script in either markup blobs. So strip out line delims.
//Leave spaces and tabs in case they are important.
returnedMarkup = stripMarkup(returnedMarkup);
expectedMarkup = stripMarkup(expectedMarkup);
pringDebug(returnedMarkup, expectedMarkup, "compareProcessedMarkup");
return StringUtil.equals(returnedMarkup, expectedMarkup);
}
}
return false;
}
/**
* Helper method to create a Document from the supplied contents
* @param documentContents - the contents of the document
* @return a new Document containing the provided contents
* @throws Exception
*/
public Document createDocument(String documentContents) throws Exception{
if(StringUtil.isNotEmpty(documentContents)){
return DOMUtil.createDocument(documentContents);
}
return null;
}
/**
* Helper method to check to see if the provided markup contains any scriplet tags.
* @param markup
* @return true if the markup contains any script tags, false otherwise.
*/
public boolean containsScript(String markup){
if(StringUtil.isNotEmpty(markup)){
if(markup.indexOf(START_SCRIPLET_VALUE_TAG)!=-1){
return true;
}
else if(markup.indexOf(START_SCRIPLET_TAG)!= -1){
return true;
}
else if(markup.indexOf(END_SCRIPLET_TAG)!= -1){
return true;
}
}
return false;
}
/**
* Helper method to remove all line delimiters from a string
* @param markup - the string to remove the line delimiters from
* @return a string containing the markup without any line delims
*/
public String stripMarkup(String markup){
StringBuilder strBuilder = new StringBuilder();
for(int i=0; i<markup.length(); i++){
char tmpChr = markup.charAt(i);
if(tmpChr!='\n' && tmpChr!='\r' ) {
strBuilder.append(tmpChr);
}
}
return strBuilder.toString();
}
/**
* Helper method to remove all line delimiters from a string
* @param markup - the string to remove the line delimiters from
* @return a string containing the markup without any line delims
*/
public String stripMarkupContainingScript(String markup){
int openScriptletPos = markup.indexOf(START_SCRIPLET_TAG);
int endScriptletPos = markup.indexOf(END_SCRIPLET_TAG);
if(openScriptletPos!=1 && endScriptletPos!=-1 && openScriptletPos<endScriptletPos){
endScriptletPos = endScriptletPos+END_SCRIPLET_TAG.length();
String start = markup.substring(0,openScriptletPos);
String script = markup.substring(openScriptletPos,endScriptletPos);
String end = markup.substring(endScriptletPos);
return stripMarkup(start) + script + stripMarkupContainingScript(end);
}
else{
return markup;
}
}
/**
*Copied from CCCustomRenderingElementEditPart. Needed for makup processing
*/
public static class XPagesObject extends FBSCustomObject {
XFacesDOMLoader loader;
IClassDef classDef;
Object object;
XPagesObject(XFacesDOMLoader loader, Object object) {
super(ExtendedDesignTimeJSContext.getJSContext());
this.loader = loader;
try {
this.classDef = object!=null ? loader.getClassOf(object) : null;
this.object = object;
} catch(NodeException ex) {
// Just ignore - classdef will be null
}
}
public boolean hasProperty(String name) {
if(classDef!=null) {
IMember m = classDef.getMember(name);
if(m instanceof IAttribute) {
return true;
}
if(m instanceof ICollection) {
return true;
}
}
return super.hasProperty(name);
}
public FBSValue get(String name) throws InterpretException {
try {
if(classDef!=null) {
IMember m = classDef.getMember(name);
if(m instanceof IAttribute) {
try {
if(object instanceof Element){
Element elem = (Element)object;
IAttribute attr = (IAttribute)m;
String attrVal = XPagesDOMUtil.getAttribute(elem, attr.getName());
return FBSUtility.wrap(ExtendedDesignTimeJSContext.getJSContext(),attrVal);
}
} catch(Exception ex) {
// Ignore, and let fall to a property access error
}
}
if(m instanceof ICollection) {
ICollection col = (ICollection)m;
if(col.getType()==ICollection.TYPE_OBJECT) {
IObjectCollection c = loader.getObjectCollection(object, col);
return new XPagesObjectCollection(loader,object,c);
} else {
IValueCollection c = loader.getValueCollection(object, col);
return new XPagesValueCollection(loader,object,c);
}
}
}
} catch(NodeException ex) {
// Just ignore
}
return super.get(name);
}
public boolean canPut(String name) {
return false; // read only
}
}
/**
*Copied from CCCustomRenderingElementEditPart. Needed for makup processing
*/
public static class XPagesValueCollection extends FBSCustomObject {
IValueCollection collection;
XPagesValueCollection(XFacesDOMLoader loader, Object object, IValueCollection collection) {
super(ExtendedDesignTimeJSContext.getJSContext());
this.collection = collection;
}
public boolean hasProperty(String name) {
if(StringUtil.equals(name, "length")) { // $NON-NLS-1$
return true;
}
return super.hasProperty(name);
}
public FBSValue get(String name) throws InterpretException {
if(StringUtil.equals(name, "length")) { // $NON-NLS-1$
return FBSNumber.get(getArrayLength());
}
return super.get(name);
}
public FBSValue get(int index) throws InterpretException {
if(index>=0 && index<collection.size()) {
return getArrayValue(index);
}
return super.get(index);
}
public boolean canPut(String name) {
return false; // read only
}
public boolean isArray() {
return true;
}
public int getArrayLength() {
return collection.size();
}
public FBSValue getArrayValue(int index) throws InterpretException {
return FBSUtility.wrap(ExtendedDesignTimeJSContext.getJSContext(),collection.get(index));
}
}
/**
*Copied from CCCustomRenderingElementEditPart. Needed for makup processing
*/
public static class XPagesObjectCollection extends FBSCustomObject {
XFacesDOMLoader loader;
IObjectCollection collection;
XPagesObjectCollection(XFacesDOMLoader loader, Object object, IObjectCollection collection) {
super(ExtendedDesignTimeJSContext.getJSContext());
this.loader = loader;
this.collection = collection;
}
public boolean hasProperty(String name) {
if(StringUtil.equals(name, "length")) { // $NON-NLS-1$
return true;
}
return super.hasProperty(name);
}
public FBSValue get(String name) throws InterpretException {
if(StringUtil.equals(name, "length")) { // $NON-NLS-1$
return FBSNumber.get(getArrayLength());
}
return super.get(name);
}
public boolean hasIndexedProperty(){
return true;
}
public FBSValue get(int index) throws InterpretException {
if(index>=0 && index<collection.size()) {
return getArrayValue(index);
}
return super.get(index);
}
public boolean canPut(String name) {
return false; // read only
}
public boolean isArray() {
return true;
}
public int getArrayLength() {
return collection.size();
}
public FBSValue getArrayValue(int index) throws InterpretException {
Object o = collection.get(index);
return new XPagesObject(loader,o);
}
}
/**
* @return true if you want to print debug statements for a given test.
*/
public boolean getDebug(){
return debug;
}
/**
* Helper method to show the markup that is being compared
* @param returnedMarkup - markup to compare
* @param expectedMarkup - markup to compare
* @param label - descrition to appear in header of output
*/
public void pringDebug(String returnedMarkup, String expectedMarkup, String label){
if(getDebug()){
System.out.println();
System.out.println("================= "+label+" =================");
System.out.println("Returned Markup = ");
System.out.println(returnedMarkup);
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
System.out.println("Expected Markup = ");
System.out.println(expectedMarkup);
System.out.println("===============================================================================");
System.out.println();
}
}
}