001package org.apache.commons.digester3.examples.api.catalog;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements.  See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache License, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License.  You may obtain a copy of the License at
010 * 
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 * 
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */ 
019
020import org.apache.commons.digester3.AbstractObjectCreationFactory;
021import org.xml.sax.Attributes;
022
023/**
024 * The Book class doesn't have a no-argument constructor, so the
025 * standard digester ObjectCreateRule can't be used to create instances
026 * of it.
027 * <p>
028 * To resolve this issue, the FactoryCreateRule can be used in 
029 * conjunction with an appropriate factory class, like this one.
030 * The "createObject" method of the factory is invoked to generate
031 * object instances when required.
032 * <p>
033 * The factory object can access any xml attributes, plus of course
034 * any values set up within it before digester parsing starts (like
035 * JNDI references, database connections, etc) that it may in the
036 * process of generating an appropriate object.
037 * <p>
038 * Note that it is <i>not</i> possible for any data to be extracted
039 * from the body or subelements of the xml element that caused the
040 * createObject method on this factory to be invoked. For example:
041 * <pre>
042 *  [book isdn="12345"]
043 * </pre>
044 * is fine; the isdn value can be accessed during the createObject method.
045 * However, given the xml:
046 * <pre>
047 * [book]
048 *   [isdn]12345[/isdn]
049 *   ...
050 * </pre>
051 * it is not possible to access the isdn number until after the
052 * Book instance has been created.
053 * <p>
054 * Note that even if the class to be created does have a default constructor,
055 * you may wish to use a factory class, in order to initialise the created
056 * object in specific ways, or insert created objects into a central
057 * register, etc.
058 * <p>
059 * And don't forget, either, that factories may be implemented as
060 * inner classes or anonymous classes if appropriate, reducing the
061 * overhead of using this functionality in many cases. 
062 */
063public class BookFactory
064    extends AbstractObjectCreationFactory<Book>
065{
066
067    @Override
068    public Book createObject( Attributes attributes )
069        throws Exception
070    {
071        String isbn = attributes.getValue( "isbn" );
072
073        if ( isbn == null )
074        {
075            throw new Exception( "Mandatory isbn attribute not present on book tag." );
076        }
077
078        return new Book( isbn );
079    }
080
081}