/*
* Copyright (C) 2011 Laurent Caillette
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.novelang.rendering.multipage;
import java.util.Map;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.xml.sax.Attributes;
import static com.google.common.collect.ImmutableList.of;
import static org.novelang.rendering.multipage.MultipageElement.*;
import org.novelang.common.metadata.PageIdentifier;
import org.novelang.outfit.Husk;
import org.novelang.outfit.xml.IncorrectXmlException;
import org.novelang.outfit.xml.StackBasedElementReader;
import org.novelang.outfit.xml.XmlNamespaces;
/**
* Reads XML representing a list of pages as internally rendered by
* {@link org.novelang.rendering.multipage.XslPageIdentifierExtractor}.
*
* @author Laurent Caillette
*/
/*package*/ class XmlMultipageReader
extends StackBasedElementReader< MultipageElement, Void, Object >
{
public XmlMultipageReader() {
super(
XmlNamespaces.TREE_NAMESPACE_URI,
ELEMENT_PATHS,
MULTIPAGE_ELEMENT_TO_STRING,
NULL_FUNCTION_FOR_ATTRIBUTE,
FIND_FROM_LOCAL_NAME
) ;
}
private final Map< PageIdentifier, String > pageIdentifiers = Maps.newLinkedHashMap() ;
public ImmutableMap< PageIdentifier, String > getPageIdentifiers() {
return ImmutableMap.copyOf( pageIdentifiers ) ;
}
// ========
// Stacking
// ========
@Override
protected Object preparePush( final MultipageElement element, final Attributes attributes )
throws IncorrectXmlException
{
switch( element ) {
case PAGES :
return null ;
case PAGE :
return Husk.create( PageBuildup.class ) ;
case PAGE_IDENTIFIER:
return null ;
case PAGE_PATH:
return null ;
default : throw new IllegalArgumentException( "Unsupported: " + element ) ;
}
}
@Override
protected Object preparePop() throws IncorrectXmlException {
final MultipageElement topSegment = getTopSegment();
switch( topSegment ) {
case PAGES :
return null ;
case PAGE:
final PageBuildup pageBuildup = ( PageBuildup ) getBuildupOnTop() ;
pageIdentifiers.put( pageBuildup.getPageIdentifier(), pageBuildup.getPath() ) ;
return null ;
case PAGE_IDENTIFIER:
final PageBuildup buildup0 = ( PageBuildup ) getBuildupUnderTop() ;
final String text = StringUtils.trim( getAndClearCollectedText() ) ;
return buildup0.withPageIdentifier( new PageIdentifier( text ) ) ;
case PAGE_PATH:
final PageBuildup buildup1 = ( PageBuildup ) getBuildupUnderTop() ;
return buildup1.withPath( StringUtils.trim( getAndClearCollectedText() ) ) ;
default :
throw new IllegalArgumentException( "Unsupported: " + topSegment ) ;
}
}
private static interface PageBuildup {
PageIdentifier getPageIdentifier() ;
PageBuildup withPageIdentifier( PageIdentifier name ) ;
String getPath() ;
PageBuildup withPath( String path ) ;
}
// ================
// Boring constants
// ================
private static final ImmutableSet< ImmutableList< MultipageElement > > ELEMENT_PATHS =
ImmutableSet.of(
of( PAGES ),
of( PAGES, PAGE ),
of( PAGES, PAGE, PAGE_IDENTIFIER ),
of( PAGES, PAGE, PAGE_PATH )
)
;
private static final Function< MultipageElement, String > MULTIPAGE_ELEMENT_TO_STRING =
new Function< MultipageElement, String >() {
@Override
public String apply( final MultipageElement input ) {
return input.getLocalName() ;
}
}
;
private static final Function< String, MultipageElement > FIND_FROM_LOCAL_NAME =
new Function< String, MultipageElement >() {
@Override
public MultipageElement apply( final String input ) {
return MultipageElement.fromLocalName( input ) ;
}
}
;
private static final Function< Void, String > NULL_FUNCTION_FOR_ATTRIBUTE =
new Function< Void, String >() {
@Override
public String apply( final Void input ) {
throw new UnsupportedOperationException( "Should never be called" ) ;
}
}
;
}