/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/wvcm/test/junit/src/org/apache/wvcm/test/ControllableResourceTest.java,v 1.3 2004/07/30 06:52:32 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:52:32 $
 *
 * ====================================================================
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Slide", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * [Additional notices, if required by prior licensing conditions]
 *
 */

package org.apache.wvcm.test;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.wvcm.ControllableFolder;
import javax.wvcm.ControllableResource;
import javax.wvcm.PropertyNameList;
import javax.wvcm.PropertyNameList.AttributeName;
import javax.wvcm.PropertyNameList.NestedPropertyName;
import javax.wvcm.PropertyNameList.PropertyName;
import javax.wvcm.Resource;
import javax.wvcm.Version;
import javax.wvcm.Workspace;
import javax.wvcm.WvcmException;
import javax.wvcm.WvcmException.ReasonCode;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.wvcm.test.common.AbstractTest;
import org.apache.wvcm.test.common.util.PropertiesHelper;
import org.apache.wvcm.test.common.util.ReasonCodeChecker;

/**
 * Provides functional tests for the ControllableResource interface.
 *
 * @author <a href="mailto:peter.nevermann@softwareag.com">Peter Nevermann</a>
 * @version $Revision: 1.3 $
 */
public class ControllableResourceTest extends AbstractTest {
	
	// logger
	private static Logger logger = Logger.getLogger("org.apache.wvcm.test.ControllableResourceTest");
	
	// TODO: REMOVE SYSTEM OUT PRINTLN FROM ALL METHODS IN CLASS. ADD ASSERTS IN THE IMPLEMENTED ONES WHERE NEEDED..
	private PropertiesHelper propsHelper = new PropertiesHelper();
	
	private String reference1Path = null;
    private String reference2Path = null;
	private String destinationPath = null;
	private String testResxCopy = "testCopy.xml";
	
    
	private String testRefResx1 = "testRef1.xml";
	private String testRefResx2 = "testRef2.xml";
	
    /**
	 * Default Constructor. Initialization of diverse paths used in the tests.
	 *
	 * @param    testName            Name of the test to run.
	 *
	 * @throws   Exception
	 *
	 */
    public ControllableResourceTest(String testName) throws Exception {
		super(testName);
		resourcePath = rootFolderPath()+"/test.xml";
		folderPath = rootFolderPath()+"/foo";
		resourceInFolderPath = folderPath+"/test.xml";
		missingFolderPath = rootFolderPath()+"/bar";
		resourceInMissingFolderPath = rootFolderPath()+"/bar/test.xml";
		
		destinationPath = rootFolderPath() + "/" + testResxCopy;
		
		reference1Path = rootFolderPath() + "/" + testRefResx1;
		reference2Path = rootFolderPath() + "/" + testRefResx1;
    }
    
    /**
	 * Method suite
	 *
	 * @return   a Test
	 */
    public static Test suite() {
		return new TestSuite(ControllableResourceTest.class);
    }
    
    /**
	 * Start test suite contained in this class using the text interface. If a
	 * parameter is passed, it will use it as a test name and run only that test
	 * case.
	 *
	 * @param args   commandline options (first argument = test method name to run)
	 *
	 * @throws Exception
	 */
    public static void main( String[] args ) throws Exception{
		if (args.length == 1) {
			TestSuite testSuite = new TestSuite();
			testSuite.addTest(new ControllableResourceTest(args[0]));
			junit.textui.TestRunner.run(testSuite);
		}
		else {
			junit.textui.TestRunner.run( suite() );
		}
    }
    
    /**
	 * Common test setup.
	 *
	 * @throws Exception
	 */
    protected void setUp() throws Exception {
		super.setUp ();
    }
    
    /**
	 * Tears down the fixture, for example, close a network connection.
	 * This method is called after a test is executed.
	 *
	 * @throws Exception
	 */
    protected void tearDown() throws Exception {
    }
    
	/**
	 * <ul>
	 * <li>Create a resource and put it under control.
	 * <li>Copy it (overwrite true) to a free location.
	 * <li>Check that the resource result is not under control.
	 * <li>Same with overwrite false.
	 *
	 * @throws Exception
	 */
	public void testDoCopyControlledResource() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a resource and put it under control.
	 * <li>Copy it overwriting a non controlled resource (overwrite true).
	 * <li>Check that the resource has been copied.
	 *
	 * @throws Exception
	 */
	public void testDoCopyControlledResxOverwriteTrue() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a resource and put it under control.
	 * <li>Copy it overwriting a non controlled resource. Overwrite is false.
	 * <li>Resource should not be copied.
	 *
	 * @throws Exception
	 */
	public void testDoCopyControlledResxOverwriteFalse() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Get a resource that identifies a version.
	 * <li>Copy it (overwrite true) to a free location.
	 * <li>Check that the resource result of the copy is not under control
	 * <li>Same with overwrite false.
	 *
	 * @throws Exception
	 */
	public void testDoCopyVersion() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a controlled resource.
	 * <li>Try to write some content on it.
	 * <li>Exception should be thrown.
	 * <li>Check it out (IsCheckedOut property is true).
	 * <li>Do write content on it.
	 * <li>Check content has been written.
	 *
	 * @throws Exception
	 */
	public void testDoWriteContentOnControlledResource() throws Exception {
		fail("Not Implemented.");
	}
    
	/**
	 * <ul>
	 * <li>Create a controllable resource.
	 * <li>Check if it is there.
	 *
	 * @throws Exception
	 */
    public void testDoCreateControllableResource() throws Exception {
		location = provider.location(resourcePath);
		resource = createControllableResource(location);
		assertTrue("Created resource cannot be found in server.",
				   resourceExistsOnServer(resourcePath) );
    }
    
    /**
	 * <ul>
	 * <li>Create a folder and then a controllable resource in the folder.
	 * <li>Check if the controllable resource has been created.
	 *
	 * @throws Exception
	 */
    public void testDoCreateResourceInFolder() throws Exception {
		location = provider.location(folderPath);
		folder = createControllableFolder(location);
		assertTrue("Created folder cannot be found in server..",
				   resourceExistsOnServer(folderPath) );
		
		location = provider.location( resourceInFolderPath );
		ControllableResource resource = location.controllableResource();
		resource.doCreateResource();
		assertTrue("Created resource cannot be found in server.",
				   resourceExistsOnServer(resourceInFolderPath) );
    }
	
	/**
	 * <ul>
	 * <li>Create a controllable resource.
	 * <li>Try to create again the resource.
	 * <li>WvcmException should be thrown with the appropiate ReasonCode.
	 *
	 * @throws Exception
	 */
	public void testDoCreateResourceTwice() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableFolder(location);
		assertTrue( resourceExistsOnServer(resourcePath) );
		try {
			resource.doCreateResource();
			fail("Creating a resource twice should have thrown an exception.");
		}
		catch (WvcmException expected) {
			assertEquals( ReasonCode.RESOURCE_ALREADY_EXISTS_AT_LOCATION,
						 expected.getReasonCode() );
		}
	}
	
    /**
	 * <ul>
	 * <li>Create a ControllableResource and put it under control.
	 * <li>Read the check properties from the resource.
	 * <li>Check if the resource is checked out (should not).
	 * <li>Check out the resource.
	 * <li>Check again if the resource is checked out (should be).
	 *
	 * @throws Exception
	 */
    public void testDoCheckout() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		resource = propsHelper.getResourceWithCheckProperties(resource);
		assertFalse("Unexpected value received. Resource seems to be checked out",
					resource.getIsCheckedOut());
		
		resource.doCheckout();
		resource = propsHelper.getResourceWithCheckProperties(resource);
		assertTrue("Unexpected value received. Resource seems to be checked in",
				   resource.getIsCheckedOut() );
    }
    
    /**
	 * <ul>
	 * <li>Create a controllable resource and put it under control.
	 * <li>Get property IS_CHECKED_OUT. Should be false.
	 * <li>Check out the resource.
	 * <li>Get property IS_CHECKED_OUT. Should be true.
	 * <li>Check in the resource.
	 * <li>Get property IS_CHECKED_OUT. Should be false.
	 *
	 * @throws Exception
	 */
    public void testDoCheckin() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		PropertyNameList wantedprops =
			new PropertyNameList( new PropertyName[]{PropertyName.IS_CHECKED_OUT} );
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		assertFalse("Resource should not show it is checked out.",
					resource.getIsCheckedOut() );
		resource.doCheckout();
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		assertTrue("Resource should not show it is checked in.",
				   resource.getIsCheckedOut() );
		resource.doCheckin();
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		assertFalse("Resource should not show it is checked out.",
					resource.getIsCheckedOut() );
    }
	
	/**
	 * <ul>
	 * <li>Create a ControllableResource and put it under control.
	 * <li>Check the resource out.
	 * <li>Check it in again (keepCheckedOut = false, fork=false)
	 * <li>Repeat check in.
	 * <li>Exception must be thrown. Check ReasonCode
	 *
	 * @throws Exception
	 */
	public void testDoCheckinTwice() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a controllable resource.
	 * <li>Check if this resource will get a version history when put under control.
	 * <li>Should return true.
	 *
	 * @throws Exception
	 */
    public void testGetVersionControllableFile() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		PropertyNameList wantedprops =
			new PropertyNameList( new PropertyName[]{PropertyName.VERSION_CONTROLLABLE} );
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		assertTrue("Unexpected result from version controllable.",
				   resource.getVersionControllable() );
    }
    
    /**
	 * <ul>
	 * <li>Create a resource and put it under control.
	 * <li>Get property VERSION_NAME as nested property from CHECKED_IN.
	 * <li>Get Version (from method {@link javax.wvcm.ControllableResource#getCheckedIn()
	 * getCheckedIn()}).
	 * <li>Check version received and its name.
	 *
	 * @throws Exception
	 */
    public void testGetCheckedInNested() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		PropertyName[] vPNames = {PropertyName.VERSION_NAME};
		PropertyNameList wantedprops =
			new PropertyNameList( new PropertyName[]{
					new NestedPropertyName(PropertyName.CHECKED_IN,
										   new PropertyNameList(vPNames))} );
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		String expectedFirstVersion = "1.0";
		Version version = resource.getCheckedIn();
		assertNotNull("Version received should not be null.",
					 version);
		assertEquals("Version number received was not the expected.",
					 expectedFirstVersion,
					 version.getVersionName());
    }
    
    /**
	 * <ul>
	 * <li>Create a controllable resource and put it under control.
	 * <li>Read property CHECKED_IN from the resource.
	 * <li>Get the version and from its location the version number.
	 * <li>Check that the version received is not null and that is number is correct.
	 *
	 * @throws Exception
	 */
    public void testGetCheckedInPlain() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		Version version = propsHelper.getCheckedInPropertyAndVersion(resource);
		String expectedFirstVersion = "1.0";
		String receivedVersionName = version.location().string().substring(
			version.location().string().lastIndexOf("/")+1);

		assertNotNull("Version received should not be null.",
					 version);
		assertEquals("Version number received was not the expected.",
					 expectedFirstVersion,
					 receivedVersionName);
    }
    
    /**
	 * <ul>
	 * <li>Create a ControllableResource.
	 * <li>Get the workspace of which it is a member.
	 * <li>Check that the returned workspace is the same one as the workspace of
	 * the parent of the created resource.
	 *
	 * @throws Exception
	 */
    public void testGetWorkspace() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		PropertyNameList wantedprops = new PropertyNameList(
			new PropertyName[] {
				PropertyName.CHECKED_IN,
					PropertyName.WORKSPACE
			}
		);
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		Version version = resource.getCheckedIn();
		if(logger.isLoggable(Level.CONFIG))
			logger.config("Version: " + version.location().string());
		
		// create workspace
		List wfl = provider.serverWorkspaceFolderList( null );
		assertNotNull( wfl );
		assertFalse( wfl.size() == 0 );
		String workspacePath = wfl.get(0)+"/ws1";
		location = provider.location( workspacePath );
		Workspace workspace = createWorkspace(location);
		
		String resourceInWsPath = workspacePath+"/test.xml";
		location = provider.location( resourceInWsPath );
		ControllableResource resourceInWs = location.controllableResource();
		resourceInWs.doCreateVersionControlledResource( version );
		resourceInWs = (ControllableResource)resourceInWs.doReadProperties( wantedprops );
		System.out.println("Workspace: "+resourceInWs.getWorkspace().location().string());
		assertEquals(workspace.location().string(), resourceInWs.getWorkspace().location().string());
		
		String resource2InWsPath = workspacePath+"/test2.xml";
		location = provider.location( resource2InWsPath );
		ControllableResource resource2InWs = location.controllableResource();
		resource2InWs.doCreateResource();
		resource2InWs = (ControllableResource)resource2InWs.doReadProperties( wantedprops );
		System.out.println("Workspace: "+resource2InWs.getWorkspace().location().string());
		assertEquals(workspace.location().string(), resource2InWs.getWorkspace().location().string());
    }
	
	/**
	 * <ul>
	 * <li>Create a controllable resource.
	 * <li>Write some content to it and put it under control.
	 * <li>Get property CREATOR_DISPLAY_NAME.
	 * <li>Check that the property value corresponds to the user name.
	 *
	 * @throws Exception
	 */
	// TODO: THE CHECK IN THIS METHOD... IS IT CORRECT?
    public void testGetCreatorDisplayName() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		
		String cid = propsHelper.getContentIdentifier(resource);
		resource.doWriteContent(
			getClass().getResourceAsStream(testResourcesRoot + "test.xml"), cid );
		resource.doControl();
		
		PropertyNameList wantedprops = new PropertyNameList(
			new PropertyName[]{PropertyName.CREATOR_DISPLAY_NAME} );
		
		resource = (ControllableResource)resource.doReadProperties(wantedprops);
		assertTrue(resource.getCreatorDisplayName().endsWith(username));
	}
	
	/**
	 * <ul>
	 * <li>Create ControllableResource and put it under version control
	 * <li>Get a Resource instance on the created resx.
	 * <li>Try to unbind the resx.
	 * <li>An exception should be thrown. Check Exception Cause.
	 *
	 * @throws Exception
	 */
	// TODO: SEE WHAT EXCEPTION CAUSE COMES AND ADD IT TO CHECK.
	public void testDoUnbindOnCheckedIn() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a folder. Create a Resource in the folder.
	 * <li>Put the folder under control (it must be checked-in).
	 * <li>Try to unbind the resource in the folder.
	 * <li>An Exception should be thrown. Resource should not be unbound.
	 *
	 * @throws Exception
	 */
	public void testDoUnbindResourceOnControlledFolder() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a resource and put it under control.
	 * <li>Try to rebind it to a free destination.
	 * <li>An exception should be thrown.
	 *
	 * @throws Exception
	 */
	// TODO: CHECK IF EXPECTED RESULT IS CORRECT.
	public void testDoRebindCheckedInResx() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a resource, put it under control and check it out.
	 * <li>Make a rebind on the resource.
	 * <li>Check that any references to the resource in a ActivityCheckoutList
	 * have been updated.
	 *
	 * @throws Exception
	 */
	public void testDoRebindCheckedOutResx() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a folder and a resource in it.
	 * <li>Put the folder under control (folder is checked in).
	 * <li>Try to make a rebind on the resource (overwrite true and false).
	 * <li>Exception should be thrown.
	 *
	 * @throws Exception
	 */
	// NOT YET IMPLEMENTED.
	//	public void testDoRebindFromControlledFolder() throws Exception {
	//		fail("Not Implemented.");
	//	}
	
	/**
	 * <ul>
	 * <li>Create two folders and a resource in one of them.
	 * <li>Put the destination folder under control (folder is checked in).
	 * <li>Try to rebind the resource (overwrite true and false).
	 * <li>Exception should be thrown.
	 *
	 * @throws Exception
	 */
	// NOT YET IMPLEMENTED
	//	public void testDoRebindTowardsControlledFolder() throws Exception {
	//		fail("Not Implemented.");
	//	}
	
    /**
	 * <ul>
	 * <li>Create a controllable resource and put it under control.
	 * <li>Get property IS_CHECKED_OUT. Should be false.
	 * <li>Check out the resource.
	 * <li>Read property IS_CHECKED_OUT. Should be true.
	 * <li>Uncheckout the resource.
	 * <li>Read property IS_CHECKED_OUT. Should be false.
	 *
	 * @throws Exception
	 */
    public void testDoUncheckout() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		PropertyNameList wantedprops =
			new PropertyNameList( new PropertyName[]{PropertyName.IS_CHECKED_OUT} );
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		assertFalse("Resource should show it is not checked out.",
					resource.getIsCheckedOut() );
		resource.doCheckout();
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		assertTrue("Resource should show it is checked out.",
				   resource.getIsCheckedOut() );
		resource.doUncheckout();
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		assertFalse("Resource should show it is not checked out.",
					resource.getIsCheckedOut() );
    }
    
    /**
	 * <ul>
	 * <li>Create a controllable resource and put it under control.
	 * <li>Read properties CHECKED_IN, and an attribute (created by user).
	 * <li>Get checked in version. Check that version is the first one.
	 * <li>Try to get attribute. Expect exception (value not set yet).
	 * <li>Checkout, give the attribute some value and check in resource.
	 * <li>Get again version. Check that version is the second one, and that the
	 * attribute value is there.
	 * <li>Perform an update on the value of the attribute (new value is the one
	 * from the first version).
	 * <li>Check that all versions modified (returned in the iterator) have the
	 * updated attribute value, in this case, each of them throw an exception.
	 *
	 * @throws Exception
	 */
    public void testDoUpdate() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		String attValue = "A_Test_Attribute_Value";
		String expectedFirstVersion = "1.0";
		String expectedSecondVersion = "1.1";
		AttributeName myatt = new AttributeName( "http://my.namespace.org", "my-att" );
		
		// Originally:
		//		PropertyName[] rPNames = {PropertyName.CHECKED_IN, myatt};
		// if this is given, then I cannot read the version name.
		// if it is done with version name, I have to read properties in the loop down.
		
		PropertyName[] vPNames = {PropertyName.VERSION_NAME};
		PropertyName[] rPNames = {new NestedPropertyName(PropertyName.CHECKED_IN,
														 new PropertyNameList(vPNames)), myatt};
		PropertyNameList wantedprops =
			new PropertyNameList( rPNames );
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		Version version_1_0 = resource.getCheckedIn();
		
		// FIXME: CHECK HOW TO GET PROPERTY VERSION_NAME TOGETHER WITH THE OTHER TWO.
		// Get the version name from the location.
		//		String receivedVersionName = version_1_0.location().string().substring(
		//			version_1_0.location().string().lastIndexOf("/") + 1);
		assertTrue("First version is not as expected.",
				   version_1_0.getVersionName().equals(expectedFirstVersion));
		
		try {
			resource.getAttribute(myatt);
			fail("Should have thrown exception");
		}
		catch (WvcmException expected) {
			assertEquals("Unexpected reason for expected exception.",
						 ReasonCode.VALUE_UNAVAILABLE,
						 expected.getReasonCode());
		}
		
		resource.doCheckout();
		resource.setAttribute( myatt, attValue );
		resource.doWriteProperties();
		resource.doCheckin();
		
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		Version version_1_1 = resource.getCheckedIn();
		assertTrue("First version is not as expected.",
				   version_1_1.getVersionName().equals(expectedSecondVersion));
		assertTrue("Attribute Value not expected..",
				   resource.getAttribute(myatt).toString().equals(attValue));
		
		Iterator i = resource.doUpdate( version_1_0, wantedprops );
		ControllableResource tempResx;
		Version tempVersion;
		while( i.hasNext() ) {
			tempResx = (ControllableResource)i.next();
			
			// FIXME: CHECK WHY CHECKED_IN CANNOT BE READ HERE IF IN THE WANTED PROPS I GIVE THE VERSION NAME.
			//tempResx = (ControllableResource)tempResx.doReadProperties(wantedprops);
			tempVersion = tempResx.getCheckedIn();
			
			try {
				tempResx.getAttribute(myatt);
				fail("Should have thrown exception since attribute is not set.");
			}
			catch (WvcmException expected) {
				assertEquals("Unexpected reason for expected exception.",
							 ReasonCode.VALUE_UNAVAILABLE,
							 expected.getReasonCode());
			}
		}
    }
	
	/**
	 * <ul>
	 * <li>Checking a problem found on reading properties.
	 * <li>
	 *
	 * @throws Exception
	 */
	public void testDoUpdateCheckReadProps() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		String attValue = "A_Test_Attribute_Value";
		String expectedFirstVersion = "1.0";
		String expectedSecondVersion = "1.1";
		AttributeName myatt = new AttributeName( "http://my.namespace.org", "my-att" );
		
		PropertyName[] rPNames = {PropertyName.CHECKED_IN, myatt};
		PropertyNameList wantedprops =
			new PropertyNameList( rPNames );
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		Version version_1_0 = resource.getCheckedIn();
		
		String receivedVersionName = version_1_0.location().string().substring(
			version_1_0.location().string().lastIndexOf("/") + 1);
		assertTrue("First version is not as expected.",
				   receivedVersionName.equals(expectedFirstVersion));
		
		try {
			resource.getAttribute(myatt);
			fail("Should have thrown exception");
		}
		catch (WvcmException expected) {
			assertEquals("Unexpected reason for expected exception.",
						 ReasonCode.VALUE_UNAVAILABLE,
						 expected.getReasonCode());
		}
		
		resource.doCheckout();
		resource.setAttribute( myatt, attValue );
		resource.doWriteProperties();
		resource.doCheckin();
		
		resource = (ControllableResource)resource.doReadProperties( wantedprops );
		Version version_1_1 = resource.getCheckedIn();
		receivedVersionName = version_1_1.location().string().substring(
			version_1_1.location().string().lastIndexOf("/") + 1);
		assertTrue("First version is not as expected.",
				   receivedVersionName.equals(expectedSecondVersion));
		assertTrue("Attribute Value not expected..",
				   resource.getAttribute(myatt).toString().equals(attValue));
		
		Iterator i = resource.doUpdate( version_1_0, wantedprops );
		ControllableResource tempResx;
		Version tempVersion;
		while( i.hasNext() ) {
			tempResx = (ControllableResource)i.next();
			tempVersion = tempResx.getCheckedIn();
			
			try {
				tempResx.getAttribute(myatt);
				fail("Should have thrown exception since attribute is not set.");
			}
			catch (WvcmException expected) {
				assertEquals("Unexpected reason for expected exception.",
							 ReasonCode.VALUE_UNAVAILABLE,
							 expected.getReasonCode());
			}
		}
	}
    
	/**
	 * <ul>
	 * <li>Try to create a resource on an unexisting folder.
	 * <li>Exception should be thrown.
	 * <li>Check reason code in received exception.
	 *
	 * @throws Exception
	 */
    public void testDoCreateControllableResourceMissingFolder() throws Exception {
		location = provider.location( resourceInMissingFolderPath );
		resource = location.controllableResource();
		location = provider.location( missingFolderPath );
		ControllableFolder missingFolder = (ControllableFolder)location.folder();
		try {
			missingFolder.doUnbind();
			resource.doUnbind();
			resource.doCreateResource();
			fail("A CONFLICT should have been thrown.");
		}
		catch (WvcmException we) {}
    }
    
	/**
	 * <ul>
	 * <li>Create a resource and put it under control.
	 * <li>Read CHECKED_IN PROPERTY and get root version.
	 * <li>Create a workspace folder.
	 * <li>Create a VersionControlledResource of the root version of the test
	 * resource (a VCR is a resource placed in a workspace that shares the same
	 * history as the resource it has been created from).
	 * <li>Get Version from the VCR created.
	 * <li>Check this version is the same as the test resource.
	 *
	 * @throws Exception
	 */
	// TODO: REMOVE SYSTEM.OUT.PRINTLN AND ADD CHECKS.
    public void testDoCreateVCR() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		Version version = propsHelper.getCheckedInPropertyAndVersion(resource);
		
		// create workspace
		List wfl = provider.serverWorkspaceFolderList( null );
		assertNotNull( wfl );
		assertFalse( wfl.size() == 0 );
		String workspacePath = wfl.get(0) + "/ws1";
		location = provider.location( workspacePath );
		Workspace workspace = createWorkspace(location);
		
		String anotherResourcePath = workspacePath + "/test.xml";
		location = provider.location( anotherResourcePath );
		
		// Create a version controlled resource.
		ControllableResource anotherResource = location.controllableResource();
		anotherResource.doUnbind();
		anotherResource.doCreateVersionControlledResource( version );
		
		// read properties from the version controlled resource.
		Version version2 = propsHelper.getCheckedInPropertyAndVersion(anotherResource);
		assertEquals("Location of versions should be the same.",
					 version.location().string(),
					 version2.location().string());
    }
	
	/**
	 * <ul>
	 * <li>Instantiate a Version.
	 * <li>Try to create a VCR on a location where there is already a resource
	 * (under control and checked in).
	 * <li>An Exception should be thrown.
	 * <li>Repeat with a resource under control but checked out.
	 * <li>Exception should be thrown.
	 * <li>Repeat with a resource not under control.
	 * <li>Exception should be thrown.
	 *
	 * @throws Exception
	 */
	public void testDoCreateVCRExistingResource() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a folder and put it under control.
	 * <li>Instantiate a version.
	 * <li>Try to create a VCR on that folder.
	 * <li>Exception should be thrown.
	 *
	 * @throws Exception
	 */
	// FOLDERS CANNOT BE STILL PUT UNDER CONTROL
	//	public void testDoCreateVCRCheckedInParent() throws Exception {
	//		fail("Not Implemented.");
	//	}
	
	/**
	 * <ul>
	 * <li>Try to create a VCR.
	 * <li>The version used to create a VCR identifies an existing resource (that
	 * is, the property CheckedIn or CheckedOut of that resource identifies one of
	 * the versions in the version history of the version used to create the VCR).
	 * <li>Krasss oder?
	 *
	 * @throws Exception
	 */
	public void testDoCreateVCRExistingHistory() throws Exception {
		fail("Not Implemented.");
	}
    
	/**
	 * <ul>
	 * <li>Create a controllable resource and put it under control.
	 * <li>Read CHECKED_IN property and get root version.
	 * <li>Read label name list on the version.
	 * <li>Add two labels to the resource and check label list in the version.
	 * <li>Remove label and repeat check.
	 * <li>Set label and repeat check.
	 *
	 * @throws Exception
	 */
    public void testDoAddRemoveSetLabel() throws Exception {
		
		// labels to add/remove/set in the test.
		String labelToAdd1 = "label_add_1&_remove";
		String labelToAdd2 = "label_add_2";
		String labelToSet1 = "label_set_1";
		
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		PropertyNameList wantedprops;
		Version version = propsHelper.getCheckedInPropertyAndVersion(resource);
		if (logger.isLoggable(Level.CONFIG))
			logger.config("Version: " + version.location().string());
		
		PropertyName[] vPNames = {PropertyName.LABEL_NAME_LIST};
		wantedprops = new PropertyNameList( vPNames );
		version = (Version)version.doReadProperties( wantedprops );
		
		// No labels have been set... So, an empty list should be received.
		List labelList = version.getLabelNameList();
		assertNotNull("List received should not be null.",
					  labelList);
		assertEquals("Label list size is not expected.",
					 0,
					 labelList.size());

		// add first label
		resource.doAddLabel(labelToAdd1);
		version = (Version)version.doReadProperties( wantedprops );
		labelList = version.getLabelNameList();
		assertEquals("Label list size is not expected.",
					 1,
					 labelList.size());
		assertEquals("Label value is not the expected.",
					 labelToAdd1,
					 labelList.get(0));
		
		resource.doAddLabel(labelToAdd2);
		version = (Version)version.doReadProperties( wantedprops );
		labelList = version.getLabelNameList();
		assertEquals("Label list size is not expected.",
					 2,
					 labelList.size());
		assertEquals("Label value is not the expected.",
					 labelToAdd1,
					 labelList.get(0));
		assertEquals("Label value is not the expected.",
					 labelToAdd2,
					 labelList.get(1));
		
		resource.doRemoveLabel(labelToAdd1);
		version = (Version)version.doReadProperties( wantedprops );
		labelList = version.getLabelNameList();
		assertEquals("Label list size is not expected.",
					 1,
					 labelList.size());
		assertEquals("Label value is not the expected.",
					 labelToAdd2,
					 labelList.get(0));
		
		resource.doSetLabel(labelToSet1);
		version = (Version)version.doReadProperties( wantedprops );
		labelList = version.getLabelNameList();
		assertEquals("Label list size is not expected.",
					 2,
					 labelList.size());
		assertEquals("Label value is not the expected.",
					 labelToAdd2,
					 labelList.get(0));
		assertEquals("Label value is not the expected.",
					 labelToSet1,
					 labelList.get(1));
    }
    
    /**
	 * <ul>
	 * <li>Create controllable resource, add a comment to it and put it under control.
	 * <li>Add a label to it.
	 * <li>Read properties COMMENT, LABEL_NAME_LIST from the resource.
	 * <li>Check resx out, set a comment, persist changes and check it in.
	 * <li>Add a second label to the resource.
	 * <li>Read the labelled version (with the first label).
	 * <li>Check props read (comment + label list).
	 * <li>Read the labelled version again (with the second label).
	 * <li>Check props read (comment + label list).
	 *
	 * @throws Exception
	 */
    public void testDoReadLabelledVersionProperties() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		
		String commentForTest = "A Comment For Test.";
		String secondComment = "A Second Comment For test";
		String aLabelForTest = "label uno";
		String anotherLabelForTest = "label dos";
		
		resource.setComment(commentForTest);
		resource.doWriteProperties();
		resource.doControl();
		
		// Add first label to the root version.
		resource.doAddLabel(aLabelForTest);
		
		PropertyNameList rprops = new PropertyNameList(
			new PropertyName[]{
				PropertyName.COMMENT,
					PropertyName.LABEL_NAME_LIST}
		);
		
		resource.doCheckout();
		resource.setComment(secondComment);
		resource.doWriteProperties();
		resource.doCheckin();

		// add second label to the version 1.1
		resource.doAddLabel( "beta" );
		
		Version version = resource.doReadLabelledVersionProperties(aLabelForTest, rprops);
		String versionName = version.location().string().substring(
			version.location().string().lastIndexOf("/") + 1);
		assertEquals("Wrong version name for this labelled version.",
					 "1.0",
					 versionName);
		assertEquals("Unexpected comment for this labelled version.",
					 aLabelForTest,
					 version.getComment());
		
		System.out.println("  - Labels: "+version.getLabelNameList());
		
		version = resource.doReadLabelledVersionProperties("beta", rprops);
		versionName = version.location().string().substring(
			version.location().string().lastIndexOf("/") + 1);
		assertEquals("Wrong version name for this labelled version.",
					 "1.1",
					 versionName);
		assertEquals("Unexpected comment for this labelled version.",
					 aLabelForTest,
					 version.getComment());
		System.out.println("  - Labels: "+version.getLabelNameList());
    }
	
	/**
	 * <ul>
	 * <li>Create two folders and a resource in one of them.
	 * <li>Put the folder without resource under control (status=checked in).
	 * <li>Try a DoBind on the resource to the folder under control.
	 * <li>A WvcmException should be thrown.
	 *
	 * @throws Exception
	 */
	// NOT YET IMPLEMENTED.
	//	public void testDoBindInControlledFolder() throws Exception {
	//		fail("Not Implemented.");
	//	}
	
	/**
	 * <ul>
	 * <li>Create a resource.
	 * <li>Get two references to that resource (two different instances of the
	 * same location).
	 * <li>Read properties with both instances. Change properties using one of
	 * them and persist the changes. (changes should not yet be seen by the other
	 * instance).
	 * <li>Make a doRefresh with the other instance. Now changes should be seen.
	 *
	 * @throws Exception
	 */
	// THIS HAS NOT YET BEEN IMPLEMENTED.
	//	public void testDoRefreshDirtyTrueNoChanges() throws Exception {
	//		fail("Not Implemented.");
	//	}
	
	/**
	 * <ul>
	 * <li>Create a resource.
	 * <li>Get two references to that resource (two different instances of the
	 * same location).
	 * <li>Read properties with both instances. Change properties using one of
	 * them and persist the changes. (changes should not yet be seen by the other
	 * instance).
	 * <li>Make some changes with the second instance (do not persist changes).
	 * <li>Make a doRefresh with the second instance using ignoreDirty=false.
	 * <li>An Exception should be thrown.
	 *
	 * @throws Exception
	 */
	// THIS IS NOT YET IMPLEMENTED.
	//	public void testDoRefreshDirtyFalseWithChanges() throws Exception {
	//		fail("Not Implemented.");
	//	}
	
	/**
	 * <ul>
	 * <li>Create a resource.
	 * <li>Get two references to that resource (two different instances of the
	 * same location).
	 * <li>Read properties with both instances. Change properties using one of
	 * them and persist the changes. (changes should not yet be seen by the other
	 * instance).
	 * <li>Make some changes with the second instance (do not persist changes).
	 * <li>Make a doRefresh with the second instance using ignoreDirty=true.
	 * <li>The changes done should have been lost and the instance has been
	 * updated with the server state.
	 *
	 * @throws Exception
	 */
	// THIS IS NOT YET IMPLEMENTED.
	//	public void testDoRefreshDirtyTrueWithChanges() throws Exception {
	//		fail("Not Implemented.");
	//	}
	
	/**
	 * <ul>
	 * <li>Create a folder and a controllable resource in it.
	 * <li>Put the resource under control.
	 * <li>Check that the property isCheckedOut is false => resource is under control.
	 * <li>Check that a version history has been created for this resource. That
	 * version history has to be identified by the CheckedIn property.
	 *
	 * @throws Exception
	 */
	public void testDoControl() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a folder and a controllable resource in it.
	 * <li>Put the resource under control.
	 * <li>Put the resource under control again.
	 * <li>An Exception should be thrown.
	 *
	 * @throws Exception
	 */
	public void testDoControlTwice() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>Create a ControllableResource.
	 * <li>Put it under control.
	 * <li>GetIsCheckedOut should return false.
	 * <li>Check the resource out.
	 * <li>GetIsCheckedOut should return true.
	 *
	 * @throws Exception
	 */
	public void testGetIsCheckedOut() throws Exception {
		fail("Not Implemented.");
	}
	
	/**
	 * <ul>
	 * <li>
	 * <li>
	 *
	 * @throws Exception
	 */
	// TODO: ADD DOCUMENTATION
	// TODO: REMOVE CONSOLE OUTPUT. ADD ASSERTIONS.
	// TODO: CHANGE ControllableResource with a Resource variable.
    public void testObjectValuedAttributes() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		resource.doControl();
		
		location = provider.location( reference1Path );
		ControllableResource ref1resource = createControllableResource(location);
		
		location = provider.location( reference2Path );
		ControllableResource ref2resource = createControllableResource(location);
		
		AttributeName attsingle = new AttributeName("http://my.namespace.org", "att-single");
		AttributeName attlist = new AttributeName("http://my.namespace.org", "att-list");
		AttributeName attdate = new AttributeName("http://my.namespace.org", "att-date");
		AttributeName attstring = new AttributeName("http://my.namespace.org", "att-string");
		AttributeName attboolean = new AttributeName("http://my.namespace.org", "att-boolean");
		AttributeName attinteger = new AttributeName("http://my.namespace.org", "att-integer");
		AttributeName attlong = new AttributeName("http://my.namespace.org", "att-long");
		AttributeName attlocale = new AttributeName("http://my.namespace.org", "att-locale");
		AttributeName attshort = new AttributeName("http://my.namespace.org", "att-short");
		AttributeName attbyte = new AttributeName("http://my.namespace.org", "att-byte");
		AttributeName attcharacter = new AttributeName("http://my.namespace.org", "att-character");
		AttributeName attdouble = new AttributeName("http://my.namespace.org", "att-double");
		AttributeName attfloat = new AttributeName("http://my.namespace.org", "att-float");
		List reflist = new ArrayList();
		reflist.add( ref1resource );
		reflist.add( ref2resource );
		
		resource.setAttribute( attsingle, ref1resource );
		resource.setAttribute( attlist, reflist );
		resource.setAttribute( attdate, new Date() );
		resource.setAttribute( attstring, "Pooh and his friends" );
		resource.setAttribute( attboolean, Boolean.TRUE );
		resource.setAttribute( attinteger, new Integer(Integer.MAX_VALUE) );
		resource.setAttribute( attlong, new Long(Long.MAX_VALUE) );
		resource.setAttribute( attlocale, new Locale("de", "") );
		resource.setAttribute( attshort, new Short(Short.MAX_VALUE) );
		resource.setAttribute( attbyte, new Byte(Byte.MAX_VALUE) );
		resource.setAttribute( attcharacter, new Character('@') );
		resource.setAttribute( attdouble, new Double(Double.MAX_VALUE) );
		resource.setAttribute( attfloat, new Float(Float.MAX_VALUE) );
		resource.doWriteProperties();
		
		ref1resource.setAttribute( attstring, "This is ref1" );
		ref1resource.doWriteProperties();
		ref2resource.setAttribute( attstring, "This is ref2" );
		ref2resource.doWriteProperties();
		
		PropertyNameList wantedProperties;
		wantedProperties = new PropertyNameList(
			new PropertyName[] {attsingle,
					attlist,
					attdate,
					attstring,
					attboolean,
					attinteger,
					attlong,
					attlocale,
					attshort,
					attbyte,
					attcharacter,
					attdouble,
					attfloat,
					PropertyName.CHECKED_IN
			}
		);
		
		resource = (ControllableResource)resource.doReadProperties( wantedProperties );
		ref1resource = (ControllableResource)resource.getAttribute( attsingle );
		reflist = (List)resource.getAttribute( attlist );
		Version v = resource.getCheckedIn();
		System.out.println("\nSingle reference: ");
		System.out.println("- "+ref1resource.location().string());
		System.out.println("Multiple reference: ");
		for( Iterator i = reflist.iterator(); i.hasNext(); )
			System.out.println("- "+((Resource)i.next()).location().string());
		System.out.println("Checked-In: "+v.location().string());
		
		System.out.println("\nBasic Types: ");
		Object val;
		val = resource.getAttribute(attstring);
		System.out.println("String ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attdate);
		System.out.println("Date ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attboolean);
		System.out.println("Boolean ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attinteger);
		System.out.println("Integer ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attlong);
		System.out.println("Long ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attlocale);
		System.out.println("Locale ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attshort);
		System.out.println("Short ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attbyte);
		System.out.println("Byte ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attcharacter);
		System.out.println("Character ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attdouble);
		System.out.println("Double ["+val.getClass().getName()+"]: "+val);
		val = resource.getAttribute(attfloat);
		System.out.println("Float ["+val.getClass().getName()+"]: "+val);
		
		NestedPropertyName attsingleNested = new NestedPropertyName(
			attsingle,
			new PropertyNameList(new PropertyName[]{attstring})
		);
		NestedPropertyName attlistNested = new NestedPropertyName(
			attlist,
			new PropertyNameList(new PropertyName[]{attstring})
		);
		wantedProperties = new PropertyNameList(
			new PropertyName[]{attsingleNested, attlistNested, attdate}
		);
		resource = (ControllableResource)resource.doReadProperties( wantedProperties );
		ref1resource = (ControllableResource)resource.getAttribute( attsingle );
		reflist = (List)resource.getAttribute( attlist );
		System.out.println("\nSingle reference: ");
		System.out.println("- "+ref1resource.location().string());
		System.out.println("- att-string="+ref1resource.getAttribute(attstring));
		System.out.println("Multiple reference: ");
		for( Iterator i = reflist.iterator(); i.hasNext(); ) {
			Resource r = (Resource)i.next();
			System.out.println("- "+r.location().string());
			System.out.println("- attstring="+r.getAttribute(attstring));
		}
		System.out.println("Date: "+resource.getAttribute(attdate));
	}
	
	/**
	 * <ul>
	 * <li>Create a resource.
	 * <li>Do a rebind to it in such a way that the workspace property changes.
	 * <li>Check change to the workspace property.
	 *
	 * @throws Exception
	 */
	public void testDoRebindWorkspaceProperty() throws Exception {
		location = provider.location( resourcePath );
		resource = createControllableResource(location);
		
		PropertyNameList wantedProps =
			new PropertyNameList(
			new PropertyName[] {
					PropertyName.WORKSPACE
					
			}
		);
		resource = (ControllableResource)resource.doReadProperties(wantedProps);
		Workspace testWS;
		try {
			testWS = resource.getWorkspace();
			fail("Expected exception not thrown. Workspace should not be available yet.");
		}
		catch (WvcmException expected) {
			assertEquals("Unexpected reason for exception.",
						 "PROPERTY_MISSING",
						 ReasonCodeChecker.getReasonCodeAsString(expected));
		}
		
		
		resource.doControl();
		resource = (ControllableResource)resource.doReadProperties(wantedProps);
		testWS = resource.getWorkspace();
		
		fail("Wait until support for workspace-collection-set has been implemented.");
		
		// TODO: FINISH TEST CASE.
//		resource = (ControllableResource)resource.doReadProperties(wantedprops);
//		List wsList = null;
//		try {
//			wsList = resource.getWorkspaceFolderList();
//			fail("Resource should not have a workspace folder list.");
//		}
//		catch (WvcmException expected) {
//			assertEquals("Unexpected Reason for exception received.",
//						 "VALUE_UNAVAILABLE",
//						 ReasonCodeChecker.getReasonCodeAsString(expected));
//		}
//
//		resource.doControl();
//		resource = (ControllableResource)resource.doReadProperties(wantedprops);
//		try {
//			wsList = resource.getWorkspaceFolderList();
//			fail("Resource should not have a workspace folder list.");
//		}
//		catch (WvcmException expected) {
//			assertEquals("Unexpected Reason for exception received.",
//						 "VALUE_UNAVAILABLE",
//						 ReasonCodeChecker.getReasonCodeAsString(expected));
//		}
	}
}


