Added ChainedOptions to the person sample, and made country and company into drop-down lists.

This commit is contained in:
Ulrik Sandberg
2007-07-18 22:27:36 +00:00
parent e84c6b31eb
commit c937c97cbb
31 changed files with 1010 additions and 104 deletions

View File

@@ -0,0 +1,16 @@
<ivy-module version="1.0">
<info organisation="net.sf"
module="chainedoptions-src"
revision="0.9.0"
status="release"
publication="20050831153500"
default="true"
/>
<configurations>
<conf name="default" visibility="public" extends="source"/>
<conf name="source" visibility="public"/>
</configurations>
<publications>
<artifact name="chainedoptions-src" type="zip" ext="zip" conf="source"/>
</publications>
</ivy-module>

View File

@@ -16,6 +16,7 @@
<classpathentry kind="lib" path="lib/global/ognl.jar"/>
<classpathentry kind="lib" path="lib/test/gsbase.jar"/>
<classpathentry kind="lib" path="lib/global/shared-asn1-codec.jar"/>
<classpathentry kind="lib" path="lib/global/chainedoptions.jar" sourcepath="lib/source/chainedoptions-src.zip"/>
<classpathentry kind="src" output="target/itest-classes" path="src/itest/java"/>
<classpathentry kind="lib" path="lib/test/spring-mock.jar" sourcepath="lib/source/spring-src.zip"/>
<classpathentry kind="lib" path="lib/global/commons-lang.jar" sourcepath="lib/source/commons-lang-src.zip"/>

View File

@@ -0,0 +1,5 @@
#Tue Jul 17 23:38:33 CEST 2007
eclipse.preferences.version=1
org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true
org.springframework.ide.eclipse.core.builders.enable.beansvalidator=true
org.springframework.ide.eclipse.core.builders.enable.webflowvalidator=true

View File

@@ -6,13 +6,11 @@
<configs>
<config>src/main/webapp/WEB-INF/flows/detail-group-flow-beans.xml</config>
<config>src/main/webapp/WEB-INF/flows/search-group-flow-beans.xml</config>
<config>src/webapp/WEB-INF/apacheDsContext.xml</config>
<config>src/main/webapp/WEB-INF/flows/search-flow-beans.xml</config>
<config>src/webapp/WEB-INF/applicationContext.xml</config>
<config>src/webapp/WEB-INF/applicationContext-acegi-security.xml</config>
<config>src/webapp/WEB-INF/ldaptemplate-servlet.xml</config>
<config>src/main/webapp/WEB-INF/flows/detail-flow-beans.xml</config>
<config>src/main/webapp/WEB-INF/ldaptemplate-webflow-config.xml</config>
<config>src/main/webapp/WEB-INF/optionsContext.xml</config>
<config>src/main/webapp/WEB-INF/applicationContext.xml</config>
</configs>
<configSets>
<configSet>
@@ -20,15 +18,13 @@
<allowBeanDefinitionOverriding>false</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
<config>src/webapp/WEB-INF/apacheDsContext.xml</config>
<config>src/webapp/WEB-INF/applicationContext.xml</config>
<config>src/webapp/WEB-INF/applicationContext-acegi-security.xml</config>
<config>src/webapp/WEB-INF/ldaptemplate-servlet.xml</config>
<config>src/main/webapp/WEB-INF/flows/detail-flow-beans.xml</config>
<config>src/main/webapp/WEB-INF/flows/detail-group-flow-beans.xml</config>
<config>src/main/webapp/WEB-INF/flows/search-flow-beans.xml</config>
<config>src/main/webapp/WEB-INF/flows/search-group-flow-beans.xml</config>
<config>src/main/webapp/WEB-INF/ldaptemplate-webflow-config.xml</config>
<config>src/main/webapp/WEB-INF/applicationContext.xml</config>
<config>src/main/webapp/WEB-INF/optionsContext.xml</config>
</configs>
</configSet>
</configSets>

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<ivy-module version="1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.jayasoft.org/misc/ivy/samples/ivy.xsd">
<info organisation="org.springframework"
<info organisation="org.springframework"
module="spring-ldap-person-sample" />
<configurations>
@@ -16,105 +16,110 @@
<dependencies defaultconf="global->default">
<!-- global dependencies -->
<dependency org="commons-logging" name="commons-logging"
<dependency org="commons-logging" name="commons-logging"
rev="1.0.4" />
<dependency org="log4j" name="log4j" rev="1.2.9" />
<dependency org="oro" name="oro" rev="2.0.8" />
<dependency org="taglibs" name="standard" rev="1.1.2" />
<dependency org="jstl" name="jstl" rev="1.1.2" />
<dependency org="org.springframework" name="spring-ldap"
<dependency org="net.sf" name="chainedoptions" rev="0.9.0" />
<dependency org="net.sf" name="chainedoptions-src" rev="0.9.0"
conf="source->@">
<artifact name="chainedoptions-src" type="zip" ext="zip" />
</dependency>
<dependency org="org.springframework" name="spring-ldap"
rev="latest.integration" conf="global->default;source->@" />
<dependency org="org.springframework" name="spring-web"
<dependency org="org.springframework" name="spring-web"
rev="2.0.4" />
<dependency org="org.springframework" name="spring-webmvc"
<dependency org="org.springframework" name="spring-webmvc"
rev="2.0.4" />
<dependency org="org.springframework" name="spring-webflow"
<dependency org="org.springframework" name="spring-webflow"
rev="1.0.2" />
<dependency org="org.springframework" name="spring-webflow-src"
<dependency org="org.springframework" name="spring-webflow-src"
rev="1.0.2" conf="source->source">
<artifact name="spring-webflow-src" type="zip" ext="zip" />
</dependency>
<dependency org="org.springframework" name="spring-binding"
<dependency org="org.springframework" name="spring-binding"
rev="1.0.2" />
<dependency org="org.springframework" name="spring-binding-src"
<dependency org="org.springframework" name="spring-binding-src"
rev="1.0.2" conf="source->source">
<artifact name="spring-binding-src" type="zip" ext="zip" />
</dependency>
<dependency org="ognl" name="ognl" rev="2.6.9" />
<dependency org="org.acegisecurity" name="acegi-security"
<dependency org="org.acegisecurity" name="acegi-security"
rev="1.0.3" />
<dependency org="org.acegisecurity" name="acegi-security-src"
<dependency org="org.acegisecurity" name="acegi-security-src"
rev="1.0.3" conf="source->source">
<artifact name="acegi-security-src" type="zip" />
</dependency>
<dependency org="org.springframework" name="spring-aop"
<dependency org="org.springframework" name="spring-aop"
rev="2.0.4" />
<dependency org="aopalliance" name="aopalliance" rev="1.0" />
<!-- kind of nasty, acegi needs some 1.2.7 stuff, so we override with newer! -->
<dependency org="org.springframework" name="spring-jdbc"
<dependency org="org.springframework" name="spring-jdbc"
rev="2.0.4" />
<dependency org="org.springframework" name="spring-remoting"
<dependency org="org.springframework" name="spring-remoting"
rev="2.0.4" />
<dependency org="org.springframework" name="spring-support"
<dependency org="org.springframework" name="spring-support"
rev="2.0.4" />
<!-- dependencies for Apache Directory Server -->
<dependency org="org.apache.directory.server"
<dependency org="org.apache.directory.server"
name="apacheds-core" rev="1.0.0" conf="global->default" />
<dependency org="org.apache.directory.server"
<dependency org="org.apache.directory.server"
name="apacheds-core-shared" rev="1.0.0" conf="global->default" />
<dependency org="org.apache.directory.server"
<dependency org="org.apache.directory.server"
name="apacheds-server-jndi" rev="1.0.0" conf="global->default" />
<dependency org="org.apache.directory.server"
<dependency org="org.apache.directory.server"
name="apacheds-server-main" rev="1.0.0" conf="global->default" />
<dependency org="org.apache.directory.server"
<dependency org="org.apache.directory.server"
name="apacheds-protocol-shared" rev="1.0.0" conf="global->default" />
<dependency org="org.apache.directory.server"
<dependency org="org.apache.directory.server"
name="apacheds-protocol-changepw" rev="1.0.0" conf="global->default" />
<dependency org="org.apache.directory.server"
<dependency org="org.apache.directory.server"
name="apacheds-protocol-kerberos" rev="1.0.0" conf="global->default" />
<dependency org="org.apache.directory.server"
<dependency org="org.apache.directory.server"
name="apacheds-kerberos-shared" rev="1.0.0" conf="global->default" />
<dependency org="org.apache.directory.server"
<dependency org="org.apache.directory.server"
name="apacheds-protocol-ldap" rev="1.0.0" conf="global->default" />
<dependency org="org.apache.directory.shared" name="shared-asn1"
<dependency org="org.apache.directory.shared" name="shared-asn1"
rev="0.9.5.3" conf="global->default" />
<dependency org="org.apache.directory.shared"
<dependency org="org.apache.directory.shared"
name="shared-asn1-codec" rev="0.9.5.3" conf="global->default" />
<dependency org="org.apache.directory.shared" name="shared-ldap"
<dependency org="org.apache.directory.shared" name="shared-ldap"
rev="0.9.5.3" conf="global->default" />
<dependency org="antlr" name="antlr" rev="2.7.2"
<dependency org="antlr" name="antlr" rev="2.7.2"
conf="global->default" />
<dependency org="jdbm" name="jdbm" rev="1.0"
<dependency org="jdbm" name="jdbm" rev="1.0"
conf="global->default" />
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.0"
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.0"
conf="global->default" />
<dependency org="org.apache.mina" name="mina-core" rev="1.0.0"
<dependency org="org.apache.mina" name="mina-core" rev="1.0.0"
conf="global->default" />
<dependency org="org.apache.mina" name="mina-filter-ssl"
<dependency org="org.apache.mina" name="mina-filter-ssl"
rev="1.0.0" conf="global->default" />
<!-- End dependencies for Apache Directory Server -->
<!-- build time only dependencies -->
<dependency org="javax.servlet" name="servlet-api" rev="2.4"
<dependency org="javax.servlet" name="servlet-api" rev="2.4"
conf="buildtime->default" />
<!-- test-time only dependencies -->
<dependency org="com.cenqua.clover" name="clover" rev="1.3.12"
<dependency org="com.cenqua.clover" name="clover" rev="1.3.12"
conf="test->default" />
<dependency org="org.springframework" name="spring-mock"
<dependency org="org.springframework" name="spring-mock"
rev="2.0.4" conf="test->default" />
<dependency org="junit" name="junit" rev="3.8.1"
<dependency org="junit" name="junit" rev="3.8.1"
conf="test->default" />
<dependency org="easymock" name="easymock" rev="1.2_Java1.3"
<dependency org="easymock" name="easymock" rev="1.2_Java1.3"
conf="test->default" />
<dependency org="gsbase" name="gsbase" rev="2.0.1"
<dependency org="gsbase" name="gsbase" rev="2.0.1"
conf="test->default" />
</dependencies>

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.dao;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.samples.person.domain.Company;
/**
* Maps from DirContextOperations (DirContextAdapters, really) to Company
* objects. A DN for a company will be of the form <code>ou=[name],c=country</code>
*
* @author Ulrik Sandberg
*/
public class CompanyContextMapper implements ContextMapper {
/*
* @see org.springframework.ldap.core.ContextMapper#mapFromContext(java.lang.Object)
*/
public Object mapFromContext(Object ctx) {
DirContextOperations dirContext = (DirContextOperations) ctx;
Company company = new Company();
company.setName(dirContext.getStringAttribute("ou"));
return company;
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.dao;
import java.util.List;
/**
* Data Access Object interface for the Company entity.
*
* @author Ulrik Sandberg
*/
public interface CompanyDao {
public List findByCountry(String country);
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.dao;
import java.util.List;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.filter.EqualsFilter;
/**
* Default implementation of CompanyDao. This implementation uses
* DirContextOperations (DirContextAdapter really, but for mock testing purposes
* we use the interface) for managing attribute values. It has been specified in
* the Spring Context that the DirObjectFactory should be used when creating
* objects from contexts, which defaults to creating DirContextAdapter objects.
* This means that we can use a ContextMapper to map from the found contexts to
* our domain objects.
*
* @author Ulrik Sandberg
*/
public class CompanyDaoImpl implements CompanyDao {
/**
* The template object that performs all data access work.
*/
LdapOperations ldapOperations;
public List findByCountry(String country) {
EqualsFilter filter = new EqualsFilter("objectclass", "organizationalUnit");
DistinguishedName base = new DistinguishedName();
base.add("c", country);
return ldapOperations.search(base, filter.toString(),
getContextMapper());
}
ContextMapper getContextMapper() {
return new CompanyContextMapper();
}
public void setLdapOperations(LdapOperations ldapOperations) {
this.ldapOperations = ldapOperations;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.dao;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.samples.person.domain.Country;
/**
* Maps from DirContextOperations (DirContextAdapters, really) to Country
* objects. A DN for a country will be of the form <code>c=[name]</code>
*
* @author Ulrik Sandberg
*/
public class CountryContextMapper implements ContextMapper {
/*
* @see org.springframework.ldap.core.ContextMapper#mapFromContext(java.lang.Object)
*/
public Object mapFromContext(Object ctx) {
DirContextOperations dirContext = (DirContextOperations) ctx;
Country country = new Country();
country.setName(dirContext.getStringAttribute("c"));
// we don't use country codes, so just use the country name as code
country.setCode(country.getName());
return country;
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.dao;
import java.util.List;
/**
* Data Access Object interface for the Country entity.
*
* @author Ulrik Sandberg
*/
public interface CountryDao {
public List findAll();
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.dao;
import java.util.List;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.filter.EqualsFilter;
/**
* Default implementation of CountryDao. This implementation uses
* DirContextOperations (DirContextAdapter really, but for mock testing purposes
* we use the interface) for managing attribute values. It has been specified in
* the Spring Context that the DirObjectFactory should be used when creating
* objects from contexts, which defaults to creating DirContextAdapter objects.
* This means that we can use a ContextMapper to map from the found contexts to
* our domain objects.
*
* @author Ulrik Sandberg
*/
public class CountryDaoImpl implements CountryDao {
/**
* The template object that performs all data access work.
*/
LdapOperations ldapOperations;
/*
* @see org.springframework.ldap.samples.person.dao.CountryDao#findAll()
*/
public List findAll() {
EqualsFilter filter = new EqualsFilter("objectclass", "country");
return ldapOperations.search(DistinguishedName.EMPTY_PATH, filter
.encode(), getContextMapper());
}
ContextMapper getContextMapper() {
return new CountryContextMapper();
}
public void setLdapOperations(LdapOperations ldapOperations) {
this.ldapOperations = ldapOperations;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.domain;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.springframework.core.style.ToStringCreator;
/**
* Simple class representing a company.
*
* @author Ulrik Sandberg
*/
public class Company {
private String name;
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass()) {
return false;
}
return EqualsBuilder.reflectionEquals(this, obj);
}
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
public String toString() {
return new ToStringCreator(this).toString();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.domain;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.springframework.core.style.ToStringCreator;
/**
* Simple class representing a country.
*
* @author Ulrik Sandberg
*/
public class Country {
private String code;
private String name;
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass()) {
return false;
}
return EqualsBuilder.reflectionEquals(this, obj);
}
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
public String toString() {
return new ToStringCreator(this).toString();
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.options;
import net.sf.chainedoptions.AbstractBeanConverter;
import net.sf.chainedoptions.LabelValueBean;
import org.springframework.ldap.samples.person.domain.Company;
/**
* Responsible for converting the properties of a Company domain object into a
* LabelValueBean.
*
* @author Ulrik Sandberg
*/
public class CompanyConverter extends AbstractBeanConverter {
/*
* @see net.sf.chainedoptions.AbstractBeanConverter#convertBean(java.lang.Object)
*/
protected LabelValueBean convertBean(Object bean) {
Company company = (Company) bean;
return new LabelValueBean(company.getName(), company.getName());
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.options;
import java.util.List;
import net.sf.chainedoptions.AbstractChainedOption;
import net.sf.chainedoptions.BeanConverter;
import net.sf.chainedoptions.ChainedOptionStrategy;
import org.springframework.ldap.samples.person.dao.CompanyDao;
import org.springframework.util.Assert;
/**
* Responsible for retrieving available companies for a given country, sorting
* them, and adjusting the command object if necessary. Collaborates with
* {@link ChainedOptionStrategy}, {@link BeanConverter}, {@link CompanyDao}.
*
* @author Ulrik Sandberg
*/
public class CompanyOption extends AbstractChainedOption {
private String countryProperty;
private CompanyDao companyDao;
/*
* @see net.sf.chainedoptions.AbstractChainedOption#retrieveOptions(java.lang.Object,
* java.lang.Object)
*/
public List retrieveOptions(Object command, Object context) {
String country = (String) getProperty(command, countryProperty);
List companyBeans = companyDao.findByCountry(country);
List companies = getConverter().convert(companyBeans);
return getStrategy(command).adjustAndSort(companies, context);
}
/*
* @see net.sf.chainedoptions.AbstractChainedOption#initChainedOption()
*/
protected void initChainedOption() {
super.initChainedOption();
Assert.notNull(companyDao, "Property <20>companyDao<61> must be set");
Assert.notNull(countryProperty, "Property <20>countryProperty<74> must be set");
Assert.notNull(getConverter(), "Property <20>converter<65> must be set");
}
public void setCompanyDao(CompanyDao companyDao) {
this.companyDao = companyDao;
}
public void setCountryProperty(String countryProperty) {
this.countryProperty = countryProperty;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.options;
import org.springframework.ldap.samples.person.domain.Country;
import net.sf.chainedoptions.AbstractBeanConverter;
import net.sf.chainedoptions.LabelValueBean;
/**
* Responsible for converting the properties of a Country domain object into a
* LabelValueBean.
*
* @author Ulrik Sandberg
*/
public class CountryConverter extends AbstractBeanConverter {
/*
* @see net.sf.chainedoptions.AbstractBeanConverter#convertBean(java.lang.Object)
*/
protected LabelValueBean convertBean(Object bean) {
Country country = (Country) bean;
return new LabelValueBean(country.getName(), country.getCode());
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.options;
import java.util.List;
import net.sf.chainedoptions.AbstractChainedOption;
import net.sf.chainedoptions.BeanConverter;
import net.sf.chainedoptions.ChainedOptionStrategy;
import org.springframework.ldap.samples.person.dao.CountryDao;
import org.springframework.util.Assert;
/**
* Responsible for retrieving available countries, sorting them, and adjusting
* the command object if necessary. Collaborates with
* {@link ChainedOptionStrategy}, {@link BeanConverter}, {@link CountryDao}.
*
* @author Ulrik Sandberg
*/
public class CountryOption extends AbstractChainedOption {
private CountryDao countryDao;
/*
* @see net.sf.chainedoptions.AbstractChainedOption#retrieveOptions(java.lang.Object,
* java.lang.Object)
*/
public List retrieveOptions(Object command, Object context) {
List countryBeans = countryDao.findAll();
List countries = getConverter().convert(countryBeans);
return getStrategy(command).adjustAndSort(countries, context);
}
/*
* @see net.sf.chainedoptions.AbstractChainedOption#initChainedOption()
*/
protected void initChainedOption() {
super.initChainedOption();
Assert.notNull(countryDao, "Property <20>countryDao<61> must be set");
Assert.notNull(getConverter(), "Property <20>converter<65> must be set");
}
public void setCountryDao(CountryDao countryDao) {
this.countryDao = countryDao;
}
}

View File

@@ -16,23 +16,28 @@
package org.springframework.ldap.samples.person.web;
import net.sf.chainedoptions.ChainedOptionManager;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
import org.springframework.util.Assert;
import org.springframework.webflow.action.FormAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
/**
* Action implementation that handles edit of a person. Registers appropriate
* property editors.
* property editors, and provides an action method for setting up reference
* data.
*
* @author Mattias Arthursson
*
* @author Ulrik Sandberg
*/
public class EditPersonFormAction extends FormAction {
private ChainedOptionManager chainedOptionManager;
/*
* (non-Javadoc)
*
* @see org.springframework.webflow.action.FormAction#registerPropertyEditors(org.springframework.webflow.execution.RequestContext,
* org.springframework.beans.PropertyEditorRegistry)
*/
@@ -41,4 +46,25 @@ public class EditPersonFormAction extends FormAction {
registry.registerCustomEditor(String[].class,
new StringArrayPropertyEditor());
}
public Event referenceData(RequestContext context) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("Executing referenceData");
}
Object formObject = getFormObject(context);
chainedOptionManager.referenceData(context.getRequestScope().asMap(),
formObject, null);
return success();
}
protected void initAction() {
Assert.notNull(chainedOptionManager,
"The property 'chainedOptionManager' must not be null");
}
public void setChainedOptionManager(
ChainedOptionManager chainedOptionManager) {
this.chainedOptionManager = chainedOptionManager;
}
}

View File

@@ -73,11 +73,21 @@
<bean id="dummyGroupDao"
class="org.springframework.ldap.samples.person.dao.DummyGroupDao">
</bean>
<bean id="groupDao"
class="org.springframework.ldap.samples.person.dao.GroupDaoImpl">
<property name="ldapOperations" ref="ldapOperations" />
</bean>
<bean id="groupDao"
class="org.springframework.ldap.samples.person.dao.GroupDaoImpl">
<property name="ldapOperations" ref="ldapOperations" />
</bean>
<bean id="countryDao"
class="org.springframework.ldap.samples.person.dao.CountryDaoImpl">
<property name="ldapOperations" ref="ldapOperations" />
</bean>
<bean id="companyDao"
class="org.springframework.ldap.samples.person.dao.CompanyDaoImpl">
<property name="ldapOperations" ref="ldapOperations" />
</bean>
<bean id="personServiceTarget"
class="org.springframework.ldap.samples.person.service.PersonServiceImpl">

View File

@@ -9,7 +9,8 @@
<property name="formObjectClass" value="org.springframework.ldap.samples.person.domain.Person"/>
<property name="validator">
<bean class="org.springframework.ldap.samples.person.domain.PersonValidator"/>
</property>
</property>
<property name="chainedOptionManager" ref="editPersonChainedOptionManager" />
</bean>
</beans>

View File

@@ -28,28 +28,36 @@
<view-state id="displayDetails" view="showDetails">
<transition on="back" to="finish" />
<transition on="edit" to="editDetails" />
<transition on="edit" to="setupEditDetails" />
</view-state>
<view-state id="editDetails" view="editDetails">
<render-actions>
<!-- setup form with person -->
<action bean="editPersonFormAction" method="setupForm"/>
</render-actions>
<transition on="cancel" to="displayDetails" />
<transition on="submit" to="displayDetails">
<!-- get updated form data back into person object -->
<action bean="editPersonFormAction" method="bindAndValidate"/>
<!-- update database with person in flowScope-->
<bean-action bean="personService" method="update">
<method-arguments>
<argument expression="flowScope.person" />
</method-arguments>
</bean-action>
</transition>
</view-state>
<action-state id="setupEditDetails">
<!-- setup form with person -->
<action bean="editPersonFormAction" method="setupForm"/>
<transition to="editDetails" />
</action-state>
<view-state id="editDetails" view="editDetails">
<render-actions>
<action bean="editPersonFormAction" method="referenceData"/>
</render-actions>
<transition on="cancel" to="displayDetails" />
<transition on="formChange" to="editDetails">
<action bean="editPersonFormAction" method="bind"/>
</transition>
<transition on="submit" to="displayDetails">
<!-- get updated form data back into person object -->
<action bean="editPersonFormAction" method="bindAndValidate"/>
<!-- update database with person in flowScope-->
<bean-action bean="personService" method="update">
<method-arguments>
<argument expression="flowScope.person" />
</method-arguments>
</bean-action>
</transition>
</view-state>
<end-state id="finish" />

View File

@@ -24,26 +24,23 @@
<td><form:input path="fullName" disabled="true" /></td>
</tr>
<tr>
<td><b>Company</b></td>
<td><form:input path="company" /></td>
<td><b>Country</B></td>
<td><form:select path="country" onchange="this.form._eventId.value='formChange';this.form.submit()"><form:options items="${countries}" itemLabel="label" itemValue="value"/></form:select></td>
</tr>
<tr>
<td><b>Country</B></td>
<td><form:input path="country" /></td>
<td><b>Company</b></td>
<td><form:select path="company"><form:options items="${companies}" itemLabel="label" itemValue="value"/></form:select></td>
</tr>
<tr>
<td><b>Phone</b></td>
<td><form:input path="phone" /></td>
</tr>
<tr>
<td><b>Description</b></td>
<td><form:input path="description" /></td>
</tr>
<tr>
<td colspan="2" class="buttonBar">
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}">
<input type="submit" class="button" name="_eventId_submit" value="Update">
<input type="submit" class="button" name="_eventId_cancel" value="Cancel">
<input type="hidden" name="_eventId" value="">
<input type="button" class="button" name="update" value="Update" onclick="this.form._eventId.value='submit';this.form.submit()">
<input type="button" class="button" name="cancel" value="Cancel" onclick="this.form._eventId.value='cancel';this.form.submit()">
</td>
</tr>
</table>

View File

@@ -37,8 +37,8 @@
${person.fullName}
</a>
</td>
<td>${person.company}</td>
<td>${person.country}</td>
<td>${person.company}</td>
<td>${person.phone}</td>
</tr>
</c:forEach>

View File

@@ -10,31 +10,23 @@
<td>Person Details</td>
</tr>
<tr>
<td colpan="2"><hr></td>
<td colspan="2"><hr></td>
</tr>
<tr>
<td><b>Name</b></td>
<td>${person.fullName}</td>
</tr>
<tr>
<td><b>Company</b></td>
<td>${person.company}</td>
</tr>
<tr>
<td><b>Country</B></td>
<td>${person.country}</td>
</tr>
<tr>
<td><b>Phone</b></td>
<td>${person.phone}</td>
<td><b>Company</b></td>
<td>${person.company}</td>
</tr>
<tr>
<td><b>Description</b></td>
<td align="top">
<c:forEach var="description" items="${person.description}">
${description} <br />
</c:forEach>
</td>
<td><b>Phone</b></td>
<td>${person.phone}</td>
</tr>
<tr>
<td colspan="2" class="buttonBar">

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="editPersonChainedOptionManager"
class="net.sf.chainedoptions.ChainedOptionManagerImpl">
<property name="chainedOptions">
<list>
<ref bean="countryChainedOption" />
<ref bean="companyChainedOption" />
</list>
</property>
</bean>
<bean id="countryChainedOption"
class="org.springframework.ldap.samples.person.options.CountryOption">
<property name="countryDao">
<ref bean="countryDao" />
</property>
<property name="commandProperty">
<value>country</value>
</property>
<property name="optionsKey">
<value>countries</value>
</property>
<property name="defaultStrategy">
<bean
class="net.sf.chainedoptions.support.FirstItemStrategy" />
</property>
<property name="converter">
<bean
class="org.springframework.ldap.samples.person.options.CountryConverter" />
</property>
</bean>
<bean id="companyChainedOption"
class="org.springframework.ldap.samples.person.options.CompanyOption">
<property name="companyDao">
<ref bean="companyDao" />
</property>
<property name="commandProperty">
<value>company</value>
</property>
<property name="optionsKey">
<value>companies</value>
</property>
<property name="countryProperty">
<value>country</value>
</property>
<property name="defaultStrategy">
<bean
class="net.sf.chainedoptions.support.FirstItemStrategy" />
</property>
<property name="converter">
<bean
class="org.springframework.ldap.samples.person.options.CompanyConverter" />
</property>
</bean>
</beans>

View File

@@ -8,7 +8,7 @@ version="2.4">
<display-name>LdapTemplate Example</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml /WEB-INF/applicationContext-acegi-security.xml</param-value>
<param-value>/WEB-INF/applicationContext.xml /WEB-INF/applicationContext-acegi-security.xml /WEB-INF/optionsContext.xml</param-value>
</context-param>
<filter>

View File

@@ -0,0 +1,97 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.dao;
import java.util.Collections;
import java.util.List;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
/**
* Unit tests for the CompanyDaoImpl class.
*
* @author Ulrik Sandberg
*/
public class CompanyDaoImplTest extends TestCase {
private MockControl ldapOperationsControl;
private LdapOperations ldapOperationsMock;
private MockControl contextMapperControl;
private ContextMapper contextMapperMock;
private CompanyDaoImpl tested;
protected void setUp() throws Exception {
super.setUp();
ldapOperationsControl = MockControl.createControl(LdapOperations.class);
ldapOperationsMock = (LdapOperations) ldapOperationsControl.getMock();
contextMapperControl = MockControl.createControl(ContextMapper.class);
contextMapperMock = (ContextMapper) contextMapperControl.getMock();
tested = new CompanyDaoImpl() {
ContextMapper getContextMapper() {
return contextMapperMock;
}
};
tested.setLdapOperations(ldapOperationsMock);
}
protected void tearDown() throws Exception {
super.tearDown();
ldapOperationsControl = null;
ldapOperationsMock = null;
contextMapperControl = null;
contextMapperMock = null;
tested = null;
}
protected void replay() {
ldapOperationsControl.replay();
contextMapperControl.replay();
}
protected void verify() {
ldapOperationsControl.verify();
contextMapperControl.verify();
}
public void testFindByCountry() {
List expectedList = Collections.singletonList(null);
ldapOperationsControl.expectAndReturn(ldapOperationsMock.search(
new DistinguishedName("c=Sweden"), "(objectclass=organizationalUnit)",
contextMapperMock), expectedList);
replay();
List result = tested.findByCountry("Sweden");
verify();
assertSame(expectedList, result);
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright 2005-2007 the original author or authors.
*
* 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 org.springframework.ldap.samples.person.dao;
import java.util.Collections;
import java.util.List;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
/**
* Unit tests for the CountryDaoImpl class.
*
* @author Ulrik Sandberg
*/
public class CountryDaoImplTest extends TestCase {
private MockControl ldapOperationsControl;
private LdapOperations ldapOperationsMock;
private MockControl contextMapperControl;
private ContextMapper contextMapperMock;
private CountryDaoImpl tested;
protected void setUp() throws Exception {
super.setUp();
ldapOperationsControl = MockControl.createControl(LdapOperations.class);
ldapOperationsMock = (LdapOperations) ldapOperationsControl.getMock();
contextMapperControl = MockControl.createControl(ContextMapper.class);
contextMapperMock = (ContextMapper) contextMapperControl.getMock();
tested = new CountryDaoImpl() {
ContextMapper getContextMapper() {
return contextMapperMock;
}
};
tested.setLdapOperations(ldapOperationsMock);
}
protected void tearDown() throws Exception {
super.tearDown();
ldapOperationsControl = null;
ldapOperationsMock = null;
contextMapperControl = null;
contextMapperMock = null;
tested = null;
}
protected void replay() {
ldapOperationsControl.replay();
contextMapperControl.replay();
}
protected void verify() {
ldapOperationsControl.verify();
contextMapperControl.verify();
}
public void testFindAll() {
List expectedList = Collections.singletonList(null);
ldapOperationsControl.expectAndReturn(ldapOperationsMock.search(
DistinguishedName.EMPTY_PATH, "(objectclass=country)",
contextMapperMock), expectedList);
replay();
List result = tested.findAll();
verify();
assertSame(expectedList, result);
}
}

View File

@@ -15,6 +15,10 @@
*/
package org.springframework.ldap.samples.person.web;
import java.util.HashMap;
import net.sf.chainedoptions.ChainedOptionManager;
import org.easymock.MockControl;
import org.springframework.ldap.samples.person.domain.Person;
import org.springframework.ldap.samples.person.service.PersonService;
@@ -31,6 +35,10 @@ public class DetailFlowExecutionTest extends AbstractXmlFlowExecutionTests {
private PersonService personServiceMock;
private MockControl chainedOptionManagerControl;
private ChainedOptionManager chainedOptionManagerMock;
private MutableAttributeMap attributeMap;
protected void setUp() throws Exception {
@@ -39,6 +47,9 @@ public class DetailFlowExecutionTest extends AbstractXmlFlowExecutionTests {
personServiceControl = MockControl.createControl(PersonService.class);
personServiceMock = (PersonService) personServiceControl.getMock();
chainedOptionManagerControl = MockControl.createControl(ChainedOptionManager.class);
chainedOptionManagerMock = (ChainedOptionManager) chainedOptionManagerControl.getMock();
attributeMap = new LocalAttributeMap();
attributeMap.put("country", "Sweden");
attributeMap.put("company", "company1");
@@ -49,14 +60,18 @@ public class DetailFlowExecutionTest extends AbstractXmlFlowExecutionTests {
super.tearDown();
personServiceControl = null;
personServiceMock = null;
chainedOptionManagerControl = null;
chainedOptionManagerMock = null;
}
protected void replay() {
personServiceControl.replay();
chainedOptionManagerControl.replay();
}
protected void verify() {
personServiceControl.verify();
chainedOptionManagerControl.verify();
}
public void testStartFlow() {
@@ -84,6 +99,7 @@ public class DetailFlowExecutionTest extends AbstractXmlFlowExecutionTests {
public void testEdit() {
expectFindByPrimaryKey();
expectReferenceData();
replay();
startFlow(attributeMap);
@@ -97,6 +113,7 @@ public class DetailFlowExecutionTest extends AbstractXmlFlowExecutionTests {
public void testCancel() {
expectFindByPrimaryKey();
expectReferenceData();
replay();
startFlow(attributeMap);
@@ -111,6 +128,7 @@ public class DetailFlowExecutionTest extends AbstractXmlFlowExecutionTests {
public void testSubmit() {
expectFindByPrimaryKey();
expectReferenceData();
expectUpdate();
replay();
@@ -124,6 +142,12 @@ public class DetailFlowExecutionTest extends AbstractXmlFlowExecutionTests {
assertModelAttributeNotNull("person", view);
}
private void expectReferenceData() {
Person person = setupPerson();
HashMap map = new HashMap();
chainedOptionManagerMock.referenceData(map, person, null);
}
private void expectFindByPrimaryKey() {
expectFindByPrimaryKey(1);
}
@@ -163,5 +187,6 @@ public class DetailFlowExecutionTest extends AbstractXmlFlowExecutionTests {
*/
protected void registerMockServices(MockFlowServiceLocator serviceRegistry) {
serviceRegistry.registerBean("personService", personServiceMock);
serviceRegistry.registerBean("editPersonChainedOptionManager", chainedOptionManagerMock);
}
}