
/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package org.jsimpledb.spring;

import org.jsimpledb.JSimpleDB;
import org.jsimpledb.kv.KVDatabase;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * Parses <code>&lt;jsimpledb:jsimpledb&gt;</code> tags.
 *
 * @see org.jsimpledb.spring
 */
class JSimpleDBBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    private static final String KVSTORE_ATTRIBUTE = "kvstore";
    private static final String SCHEMA_VERSION_ATTRIBUTE = "schema-version";
    private static final String STORAGE_ID_GENERATOR_ATTRIBUTE = "storage-id-generator";
    private static final String AUTO_GENERATE_STORAGE_IDS_ATTRIBUTE = "auto-generate-storage-ids";

    @Override
    protected Class<JSimpleDB> getBeanClass(Element element) {
        return JSimpleDB.class;
    }

    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {

        // Get KVDatabase bean name
        if (!element.hasAttribute(KVSTORE_ATTRIBUTE)) {
            parserContext.getReaderContext().fatal("<" + element.getTagName() + "> beans must have a \""
              + KVSTORE_ATTRIBUTE + "\" attribute containing the name of a bean of type " + KVDatabase.class.getName(),
              parserContext.extractSource(element));
            return;
        }
        builder.addPropertyReference("KVStore", element.getAttribute(KVSTORE_ATTRIBUTE));

        // Get schema version
        if (!element.hasAttribute(SCHEMA_VERSION_ATTRIBUTE)) {
            parserContext.getReaderContext().fatal("<" + element.getTagName() + "> beans must have a \""
              + SCHEMA_VERSION_ATTRIBUTE + "\" attribute containing the database schema version",
              parserContext.extractSource(element));
            return;
        }
        builder.addPropertyValue("schemaVersion", element.getAttribute(SCHEMA_VERSION_ATTRIBUTE));

        // Get storage ID generator bean name (optional)
        final boolean autogenStorageIds = !element.hasAttribute(AUTO_GENERATE_STORAGE_IDS_ATTRIBUTE)
          || Boolean.valueOf(element.getAttribute(AUTO_GENERATE_STORAGE_IDS_ATTRIBUTE));
        if (!autogenStorageIds)
            builder.addPropertyValue("storageIdGenerator", null);
        if (element.hasAttribute(STORAGE_ID_GENERATOR_ATTRIBUTE)) {
            if (!autogenStorageIds) {
                parserContext.getReaderContext().fatal("<" + element.getTagName() + "> cannot have a `"
                  + STORAGE_ID_GENERATOR_ATTRIBUTE + "' attribute and " + AUTO_GENERATE_STORAGE_IDS_ATTRIBUTE + "=\"false\"",
                  parserContext.extractSource(element));
                return;
            }
            builder.addPropertyReference("storageIdGenerator", element.getAttribute(STORAGE_ID_GENERATOR_ATTRIBUTE));
        }

        // Construct JSimpleDBFactoryBean bean definition
        builder.getRawBeanDefinition().setBeanClass(JSimpleDBFactoryBean.class);

        // Look for nested <scan-classes> and <scan-field-types>
        final NodeList nodeList = element.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            if (!(nodeList.item(i) instanceof Element))
                continue;
            final Element child = (Element)nodeList.item(i);
            if (!JSimpleDBNamespaceHandler.JSIMPLEDB_NAMESPACE_URI.equals(child.getNamespaceURI()))
                continue;
            if (child.getLocalName().equals(JSimpleDBNamespaceHandler.SCAN_CLASSES_TAG))
                builder.addPropertyValue("modelClasses", new ScanClassesBeanDefinitionParser().parse(child, parserContext));
            else if (child.getLocalName().equals(JSimpleDBNamespaceHandler.SCAN_FIELD_TYPES_TAG)) {
                builder.addPropertyValue("fieldTypeClasses",
                  new ScanFieldTypesBeanDefinitionParser().parse(child, parserContext));
            } else {
                parserContext.getReaderContext().fatal("unsupported <" + child.getTagName() + "> element found"
                  + " inside <" + element.getTagName() + "> element", parserContext.extractSource(element));
                return;
            }
        }
    }
}


@@ -129,44 +129,8 @@
 DB;%0A
-import org.jsimpledb.kv.KVDatabase;%0A
 impo
@@ -1176,16 +1176,27 @@
 ean name
+ (optional)
 %0A       
@@ -1192,33 +1192,32 @@
 al)%0A        if (
-!
 element.hasAttri
@@ -1244,319 +1244,13 @@
 TE))
- %7B
 %0A    
-        parserContext.getReaderContext().fatal(%22%3C%22 + element.getTagName() + %22%3E beans must have a %5C%22%22%0A              + KVSTORE_ATTRIBUTE + %22%5C%22 attribute containing the name of a bean of type %22 + KVDatabase.class.getName(),%0A              parserContext.extractSource(element));%0A            return;%0A        %7D%0A
     
@@ -1365,16 +1365,27 @@
  version
+ (optional)
 %0A       
@@ -1389,17 +1389,16 @@
     if (
-!
 element.
@@ -1440,297 +1440,13 @@
 TE))
- %7B
 %0A    
-        parserContext.getReaderContext().fatal(%22%3C%22 + element.getTagName() + %22%3E beans must have a %5C%22%22%0A              + SCHEMA_VERSION_ATTRIBUTE + %22%5C%22 attribute containing the database schema version%22,%0A              parserContext.extractSource(element));%0A            return;%0A        %7D%0A
     

Update JSimpleDBBeanDefinitionParser to reflect changes in f2b97d2f.