/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.security.userstore.config;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom.Attribute;
import org.jdom.Element;
import com.enonic.cms.api.plugin.ext.userstore.UserStoreConfig;
import com.enonic.cms.api.plugin.ext.userstore.UserStoreConfigField;
import com.enonic.cms.api.plugin.ext.userstore.UserFieldType;
public class UserStoreConfigParser
{
private final static String ROOT_ELEMENT_NAME = "config";
private final static String USER_FIELDS_ELEMENT_NAME = "user-fields";
private UserStoreConfigParser()
{
// no access
}
public static UserStoreConfig parse( final Element configEl )
{
return doParse( configEl, true );
}
public static UserStoreConfig parse( final Element configEl, final boolean remoteConfigAllowed )
{
return doParse( configEl, remoteConfigAllowed );
}
private static UserStoreConfig doParse( final Element configEl, final boolean remoteConfigAllowed )
{
final UserStoreConfig config = new UserStoreConfig();
if ( configEl == null )
{
return config;
}
final String elementName = configEl.getName();
if ( !ROOT_ELEMENT_NAME.equals( elementName ) )
{
throw new InvalidUserStoreConfigException( "Illegal root element: " + elementName + ", must be: " + ROOT_ELEMENT_NAME,
configEl );
}
final Element userFieldsEl = configEl.getChild( USER_FIELDS_ELEMENT_NAME );
config.setUserFieldConfigs( parseUserFields( userFieldsEl, remoteConfigAllowed ) );
return config;
}
private static Collection<UserStoreConfigField> parseUserFields( final Element userFieldsEl, final boolean remoteConfigAllowed )
{
if ( userFieldsEl == null )
{
throw new InvalidUserStoreConfigException( "Could not find 'user-fields' element", userFieldsEl );
}
final String elementName = userFieldsEl.getName();
if ( !USER_FIELDS_ELEMENT_NAME.equals( elementName ) )
{
throw new InvalidUserStoreConfigException(
"Given user-fields element is not named '" + USER_FIELDS_ELEMENT_NAME + "': " + elementName, userFieldsEl );
}
final Map<UserFieldType, UserStoreConfigField> fieldConfigs = new HashMap<UserFieldType, UserStoreConfigField>();
final List<Element> fieldConfigElements = userFieldsEl.getChildren();
for ( Element fieldConfigEl : fieldConfigElements )
{
final UserStoreConfigField fieldConfig = parseFieldConfig( fieldConfigEl, remoteConfigAllowed );
if ( fieldConfigs.containsKey( fieldConfig.getType() ) )
{
throw new InvalidUserStoreConfigException( "Duplicate user-field found: " + fieldConfig.getType().getName(),
fieldConfigEl );
}
fieldConfigs.put( fieldConfig.getType(), fieldConfig );
}
return fieldConfigs.values();
}
private static UserStoreConfigField parseFieldConfig( final Element fieldConfigEl, final boolean remoteConfigAllowed )
{
final String fieldName = fieldConfigEl.getName();
final UserFieldType type = UserFieldType.fromName( fieldName );
if ( type == null )
{
throw new InvalidUserStoreConfigException( "Unknown user-field: " + fieldName, fieldConfigEl );
}
if ( fieldConfigEl.getChildren().size() > 0 )
{
throw new InvalidUserStoreConfigException(
"Illegal user-field element '" + ( (Element) fieldConfigEl.getChildren().get( 0 ) ).getName() + "'", fieldConfigEl );
}
final UserStoreConfigField fieldConfig = new UserStoreConfigField( type );
/* Requried */
final String required = fieldConfigEl.getAttributeValue( "required" );
if ( required != null )
{
if ( Boolean.parseBoolean( required ) && fieldConfig.getType().isOfType( Boolean.class ) )
{
throw new InvalidUserStoreConfigException( "Illegal attribute 'required'. Not valid for type: " + Boolean.class,
fieldConfigEl );
}
if ( !"true".equals( required ) && !"false".equals( required ) )
{
throw new InvalidUserStoreConfigException( "Illegal attribute value. 'required' must be 'true' or 'false': " + required,
fieldConfigEl );
}
fieldConfig.setRequired( Boolean.parseBoolean( required ) );
}
/* Readonly */
final String readonly = fieldConfigEl.getAttributeValue( "readonly" );
if ( readonly != null )
{
if ( !"true".equals( readonly ) && !"false".equals( readonly ) )
{
throw new InvalidUserStoreConfigException( "Illegal attribute value. 'readonly' must be 'true' or 'false': " + readonly,
fieldConfigEl );
}
fieldConfig.setReadOnly( Boolean.parseBoolean( readonly ) );
}
/* Required/Readonly combinations */
if ( "true".equals( required ) && "true".equals( readonly ) )
{
throw new InvalidUserStoreConfigException( "Illegal attribute combination. Both 'readonly' and 'requried' cannot be 'true'",
fieldConfigEl );
}
/* Remote */
final String remote = fieldConfigEl.getAttributeValue( "remote" );
if ( remote != null )
{
if ( "true".equals( remote ) && !remoteConfigAllowed )
{
throw new InvalidUserStoreConfigException(
"Illegal attribute. 'remote' attribute cannot be used without a remote connector.", fieldConfigEl );
}
if ( !"true".equals( remote ) && !"false".equals( remote ) )
{
throw new InvalidUserStoreConfigException( "Illegal attribute value. 'remote' must be 'true' or 'false': " + remote,
fieldConfigEl );
}
fieldConfig.setRemote( Boolean.parseBoolean( remote ) );
}
/* Iso */
final String iso = fieldConfigEl.getAttributeValue( "iso" );
if ( iso != null )
{
if ( type != UserFieldType.ADDRESS )
{
throw new InvalidUserStoreConfigException( "Illegal attribute value. 'iso' only valid for type: " + UserFieldType.ADDRESS,
fieldConfigEl );
}
if ( !"true".equals( iso ) && !"false".equals( iso ) )
{
throw new InvalidUserStoreConfigException( "Illegal attribute value. 'iso' must be 'true' or 'false': " + iso,
fieldConfigEl );
}
fieldConfig.setIso( Boolean.parseBoolean( iso ) );
}
/* Other illegal attributes */
for ( final Object obj : fieldConfigEl.getAttributes() )
{
final Attribute attribute = (Attribute) obj;
if ( !"required".equals( attribute.getName() ) && !"readonly".equals( attribute.getName() ) &&
!"remote".equals( attribute.getName() ) && !"iso".equals( attribute.getName() ) )
{
throw new InvalidUserStoreConfigException( "Illegal attribute '" + attribute.getName() + "'", fieldConfigEl );
}
}
return fieldConfig;
}
}