package com.processpuzzle.application.configuration.domain;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.stub;
import java.io.IOException;
import java.text.MessageFormat;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.apache.commons.configuration.CombinedConfiguration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.DefaultExpressionEngine;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.xml.sax.InputSource;
import com.processpuzzle.application.domain.Application;
import com.processpuzzle.sharedfixtures.domaintier.DomainTierTestConfiguration;
public class PropertyContextTest {
private static String CONFIGURATION_DESCRIPTOR_PATH = "classpath:com/processpuzzle/application/configuration/domain/configuration_descriptor.xml";
private static Application application;
private static ProcessPuzzleContext applicationContext;
private static String EXPECTED_CONNECTION_URL = "jdbc:jtds:sqlserver://localhost/ObjectPuzzle_dc_test";
private static String EXPECTED_WORKING_DIRECTORY = "c:\\\\processpuzzle";
private PropertyContext propertyContext = null;
private org.apache.commons.configuration.CombinedConfiguration configuration = null;
private XMLConfiguration customConfig = null;
private XMLConfiguration defaultConfig = null;
@BeforeClass
public static void beforeAllTests() {
application = mock( Application.class );
applicationContext = mock( ProcessPuzzleContext.class );
stub( application.getContext() ).toReturn( applicationContext );
}
@Before
public void beforeEachTests() {
propertyContext = new PropertyContext( application, CONFIGURATION_DESCRIPTOR_PATH );
propertyContext.setUp( Application.Action.start );
configuration = (CombinedConfiguration) propertyContext.getConfiguration();
customConfig = (XMLConfiguration) configuration.getConfiguration("custom_configuration");
defaultConfig = (XMLConfiguration) configuration.getConfiguration("default_configuration");
determineExpectedValues();
}
@Test
public void testSeUp_ForCombinedConfiguration() {
assertTrue( "PropertyContext loads in a CombinedConfiguration.", configuration instanceof CombinedConfiguration );
assertTrue( "Configuration is combined from: ", customConfig instanceof XMLConfiguration );
assertTrue( "Configuration is combined from: ", defaultConfig instanceof XMLConfiguration );
assertTrue( "Expression engine is:", configuration.getExpressionEngine() instanceof DefaultExpressionEngine );
}
@Test ( expected = UndefinedPropertyDescriptorException.class )
public void testSetUp_ForUndefinedDescriptorPath() {
PropertyContext anotherContext = new PropertyContext( application, "UndefinedPath.xml" );
anotherContext.setUp( Application.Action.start );
}
@Test
public void testGetProperty_ForXmlConfig() {
assertEquals( "#808080", customConfig.getProperty("colors.background"));
assertEquals( "Even an element's attribute is a property!", "#800080", customConfig.getProperty("colors.link[@visited]"));
assertEquals( "The number of values of 'buttons.name' property is:.", 3, customConfig.getList("buttons.name").size() );
}
@Test
public void testGetProperty_ForHieracrhicalAccess() {
assertTrue( "Keys should be defined with hierarchical syntax.", customConfig.containsKey("colors.background"));
assertEquals( "#808080", customConfig.getString( "colors.background" ));
}
@Test
public void testGetProperty_ForXPathNodeSelector() {
assertEquals( DomainTierTestConfiguration.STRATEGY_NAME, configuration.getString( PropertyKeys.PERSISTENCE_STRATEGY_NAME.getDefaultKey() ));
}
@Test
public void testGetProperty_ForRequiredProperties() {
assertEquals("ProcessPuzzle", propertyContext.getProperty( PropertyKeys.APPLICATION_NAME.getDefaultKey() ));
assertEquals("1.0", propertyContext.getProperty( PropertyKeys.APPLICATION_VERSION.getDefaultKey() ));
assertNotNull( propertyContext.getProperty( PropertyKeys.APPLICATION_SERVER_WORKING_FOLDER.getDefaultKey() ));
assertNotNull("c:\\processpuzzle", propertyContext.getProperty( PropertyKeys.APPLICATION_CLIENT_WORKING_FOLDER.getDefaultKey() ));
assertEquals("ProcessPuzzle", propertyContext.getProperty( PropertyKeys.APPLICATION_DEFAULT_USER_NAME.getDefaultKey() ));
assertEquals("ProcessPuzzle", propertyContext.getProperty( PropertyKeys.APPLICATION_DEFAULT_USER_PASSWORD.getDefaultKey() ));
assertEquals("dropAndCreate", propertyContext.getProperty( PropertyKeys.APPLICATION_DATABASE_CREATION.getDefaultKey() ));
}
@Test
public void testAddProperty_ForXPathNodeSelector() {
configuration.addProperty("tables/table[1]/type", "system");
configuration.addProperty("colors/foreground", "#000000");
assertEquals( "system", configuration.getString("tables/table[1]/type"));
assertEquals( "#000000", configuration.getString("colors/foreground"));
}
@Test
public void testOverrideProperty() {
assertEquals("Check existing value", "ProcessPuzzle", propertyContext.getProperty( PropertyKeys.APPLICATION_NAME.getDefaultKey() ));
propertyContext.overrideProperty( PropertyKeys.APPLICATION_NAME, "bakfity" );
assertEquals("bakfity", propertyContext.getProperty( PropertyKeys.APPLICATION_NAME.getDefaultKey() ));
//Restore original value
propertyContext.overrideProperty( PropertyKeys.APPLICATION_NAME, "ProcessPuzzle" );
assertEquals("Check existing value", PersistentDataInitializationStrategies.dropAndCreate.toString(), propertyContext.getProperty( PropertyKeys.APPLICATION_DATABASE_CREATION.getDefaultKey() ));
propertyContext.overrideProperty( PropertyKeys.APPLICATION_NAME, PersistentDataInitializationStrategies.dropAndCreate );
assertEquals( PersistentDataInitializationStrategies.dropAndCreate.toString(), propertyContext.getProperty( PropertyKeys.APPLICATION_NAME.getDefaultKey() ));
//Restore original value
propertyContext.overrideProperty( PropertyKeys.APPLICATION_NAME, PersistentDataInitializationStrategies.update );
}
@Test
public void testJustAConfiguration() {
try {
XMLConfiguration config = new XMLConfiguration("com/processpuzzle/application/configuration/domain/custom_configuration.xml");
assertTrue( config.containsKey("colors.background"));
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
fail("ConfigurationException was not expected :-)");
}
}
@Test
public void testSetUp_ForOverride() {
assertThat("Properties in 'custom_configuration.xml' should override properties defined in 'default_configuration.xml'.",
configuration.getString("ac:application.ac:serverWorkingFolder"), equalTo( EXPECTED_WORKING_DIRECTORY ));
String key = MessageFormat.format( PropertyKeys.PERSISTENCE_STRATEGY_EVENT_HANDLER_PROPERTIES.getXPathKey(),
new Object[] { DomainTierTestConfiguration.STRATEGY_NAME, DomainTierTestConfiguration.PERSISTENCE_PROVIDER_NAME });
key += "/pr:hibernate/pr:connection/pr:url";
//assertThat( configuration.getString( key ), equalTo( EXPECTED_CONNECTION_URL ));
}
@Test
public void testShortcutGetters() {
assertEquals("ProcessPuzzle", propertyContext.getApplicationName() );
assertEquals("1.0", propertyContext.getApplicationVersion() );
assertNotNull( propertyContext.getServerWorkingFolder() );
assertNotNull( EXPECTED_WORKING_DIRECTORY, propertyContext.getClientWorkingFolder() );
assertEquals("ProcessPuzzle", propertyContext.getDefaultUserName() );
assertEquals("ProcessPuzzle", propertyContext.getDefaultUserPassword() );
}
@After
public void afterEachTests() {
propertyContext.tearDown( Application.Action.stop );
propertyContext = null;
}
private void determineExpectedValues() {
String customConfigurationPath = CONFIGURATION_DESCRIPTOR_PATH.substring( 0, CONFIGURATION_DESCRIPTOR_PATH.indexOf( "configuration_descriptor.xml" ) ) + "custom_configuration.xml";
XPathFactory factory=XPathFactory.newInstance();
XPath xPath=factory.newXPath();
ResourceLoader loader = null;
Resource resource = null;
NamespaceContext context = new ProcessPuzzleContextNamespace();
xPath.setNamespaceContext( context );
loader = (ResourceLoader) new DefaultResourceLoader();
resource = loader.getResource( customConfigurationPath );
determineConnectionUrl( xPath, resource );
determineExpectedWorkingDirectory( xPath, resource );
}
private void determineConnectionUrl( XPath xPath, Resource resource ) {
XPathExpression xPathExpression = null;
InputSource inputSource = null;
String key = MessageFormat.format( PropertyKeys.PERSISTENCE_STRATEGY_EVENT_HANDLER_PROPERTIES.getXPathKey(),
new Object[] { DomainTierTestConfiguration.STRATEGY_NAME, DomainTierTestConfiguration.PERSISTENCE_PROVIDER_NAME });
key += "/pr:hibernate/pr:connection/pr:url";
try {
inputSource = new InputSource( resource.getInputStream() );
xPathExpression = xPath.compile( "/pp:processPuzzleConfiguration/" + key );
EXPECTED_CONNECTION_URL = xPathExpression.evaluate( inputSource );
} catch( XPathExpressionException e ) {
fail( "Coudn't set up expected value: 'expectedDatabaseName'" );
} catch( IOException e ) {
e.printStackTrace();
}
}
private void determineExpectedWorkingDirectory( XPath xPath, Resource resource ) {
XPathExpression xPathExpression = null;
InputSource inputSource = null;
try {
inputSource = new InputSource( resource.getInputStream() );
xPathExpression = xPath.compile( "/pp:processPuzzleConfiguration/" + PropertyKeys.APPLICATION_SERVER_WORKING_FOLDER.getXPathKey() );
EXPECTED_WORKING_DIRECTORY = (String) xPathExpression.evaluate( inputSource, XPathConstants.STRING );
} catch( XPathExpressionException e ) {
fail( "Coudn't set up expected values: 'expectedWorkingDirectory'");
} catch( IOException e ) {
e.printStackTrace();
}
}
}