/*
 * Copyright 2002-2008 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.samples.petclinic.config;

import javax.sql.DataSource;

import org.springframework.config.java.annotation.Bean;
import org.springframework.config.java.annotation.Configuration;
import org.springframework.config.java.annotation.ExternalValue;
import org.springframework.config.java.annotation.valuesource.PropertiesValueSource;
import org.springframework.config.java.support.ConfigurationSupport;
import org.springframework.core.io.Resource;

/**
 * Configuration for an in-memory (embedded) petclinic database.
 * <p/>
 *
 * Uses {@code @PropertiesValueSource} and {@code @ExternalValue} to look up
 * the locations of the database schema and seed data for populating the db.
 * <p/>
 *
 * Note that ExternalValues need not be simple strings.  {@code schemaLocation}
 * and {@code dataLocation} are of type {@code Resource}, and are type-converted
 * on the fly.
 * <p/>
 *
 * The {@code @ExternalValue} fields are private here, and can be any visibility.
 * They will be assigned by JavaConfig at the right time when this configuration is
 * being processed.  Note that if the fields are assigned a default value, that value
 * will be used if the property name cannot be found.  Also, if no explicit value
 * is supplied as an attribute to the {@code @ExternalValue} annotation, the name
 * field name will be used to look up the externalized value.  This can be used to
 * achieve a more convention-over-configuration approach.
 * <p/>
 *
 * {@link EmbeddedDataSourceFactory} is a Spring {@link FactoryBean} implementation
 * that sets up the in-memory database.  Note that this configuration extends
 * {@link ConfigurationSupport} in order to be able to use its getObject() method.
 *
 * @see ExternalDataSourceConfig
 * @see PetclinicApplicationConfig
 * @see JdbcPetclinicApplicationConfig
 * @see JpaPetclinicApplicationConfig
 * @see ExternalValue
 * @see PropertiesValueSource
 * @see ConfigurationSupport#getObject(FactoryBean)
 * @see src/main/resources/db/db.properties
 *
 * @author Chris Beams
 */
@Configuration
@PropertiesValueSource(locations="db/db.properties")
public class EmbeddedDataSourceConfig extends ConfigurationSupport {
    private @ExternalValue("db.databaseName") String databaseName;
    private @ExternalValue("db.schemaLocation") Resource schemaLocation;
    private @ExternalValue("db.dataLocation") Resource dataLocation;

    public @Bean DataSource dataSource() {
        EmbeddedDataSourceFactory dsFactory = new EmbeddedDataSourceFactory();
        dsFactory.setDatabaseName(databaseName);
        dsFactory.setSchemaLocation(schemaLocation);
        dsFactory.setDataLocation(dataLocation);
        return getObject(dsFactory, DataSource.class);
    }
}
