All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.thesett.catalogue.config.CatalogueConfigBeanImpl Maven / Gradle / Ivy

There is a newer version: 0.9.104
Show newest version
/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * 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 com.thesett.catalogue.config;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.jdbc.Work;

import com.thesett.aima.attribute.impl.EnumeratedStringAttribute;
import com.thesett.aima.attribute.impl.HierarchyAttribute;
import com.thesett.aima.attribute.impl.HierarchyType;
import com.thesett.aima.state.ComponentType;
import com.thesett.aima.state.Type;
import com.thesett.catalogue.model.Catalogue;
import com.thesett.catalogue.model.ViewType;
import com.thesett.common.config.ConfigBeanContext;
import com.thesett.common.config.ConfigException;
import com.thesett.common.util.ReflectionUtils;
import com.thesett.common.util.StringUtils;
import com.thesett.index.config.IndexStoreConfigBean;

/**
 * CatalogueConfigBeanImpl performs application start-up time configurations to prepare a catalogue model for use. It
 * loads and validates the in-memory knowledge level model of the catalogue.
 *
 * 

'Reference types' are types that specify a restricted set of values that are enumerated in a database. For * example enumerations such as { male; female } or hierarchical labelings and so on are called reference types. * *

The start-up configuration consists of checking that the reference types have been created and populated in the * database. If the database has been created from scratch, then the reference tables need to be filled in (this is * usually only done during testing against a temporary database). For existing reference tables, the data is loaded * into memory for each type, to establish type in memory and possibly finalize it. * *

This config bean depends on {@link ModelLoaderConfigBean}, {@link HibernateConfigBean}, {@link ModeConfigBean} * and {@link IndexStoreConfigBean} having been succesfully configured first. * *

Configuration is handled differently depending on the value of the development mode switch: * *

    *
  • In development mode the database is created (by {@link HibernateConfigBean}) and any reference types, are * populated by this bean. The database will always be empty at the end of the catalogue configuration. *
  • In production mode the database schema is verified against the catalogue model and reference type data is * verified against the catalogue model and loaded into memory by this bean. At the moment the free text search * {@link com.thesett.index.Index} implementations used do not persist their data so all the data in the database is * re-indexed during configuration too. Once persistent indexes are implemented this step will be changed to an optional * verification step that checks that the indexes and database are in synch and corrects any mismatches.
  • *
* *

*
CRC Card
Responsibilities Collaborations *
Transform the raw catalogue model into the knowledge level catalogue model. *
Verify or populate the database reference types. *
Re-index all text search indexes. *
* * @author Rupert Smith */ public class CatalogueConfigBeanImpl implements Serializable, CatalogueConfigBean { /** Used for logging. */ private static final Logger log = Logger.getLogger(CatalogueConfigBeanImpl.class); /** Flag used to indicate that this config bean has been succesfully run. */ private final boolean configured = false; /** Used to hold the package name under which the model has been generated. */ private String modelPackage; /** Holds the catalogue as a first order logic model. */ private Catalogue model; /** Holds a referece to the hibernate config bean to get hibernate sessions from. */ protected HibernateConfigBean hibernateBean; /** * Checks whether or not the config bean has been succesfully run and is in a configured state. * * @return True if the config bean has run its configuration succesfully. */ public boolean getConfigured() { return configured; } /** {@inheritDoc} */ public Catalogue getCatalogue() { return model; } /** {@inheritDoc} */ public String getModelPackage() { return modelPackage; } /** {@inheritDoc} */ public void setModelPackage(String packageName) { this.modelPackage = packageName; } /** * Ensures that all hierarchy attribute classes are established in the database and in memory. * * @param force Setting this to true tells the config bean to re-run its configuration action even if * it has already been run. * @param configBeanContext A reference to the configurator that is managing the whole configuration process. * * @throws ConfigException If some error occurs that means that the configuration cannot be succesfully completed. */ public void doConfigure(boolean force, ConfigBeanContext configBeanContext) throws ConfigException { // If already configured then only reconfigure if force is set to true if (configured && !force) { return; } // Ensure that the catalogue model loader config bean has been run, and get a reference to it. ModelLoaderConfigBean loaderBean = (ModelLoaderConfigBean) configBeanContext.getConfiguredBean( "com.thesett.catalogue.config.ModelLoaderConfigBean"); // Ensure that the hibernate config bean has been set up, and get a reference to it. hibernateBean = (HibernateConfigBean) configBeanContext.getConfiguredBean( "com.thesett.catalogue.config.HibernateConfigBean"); // Ensure that the mode config bean has been set up, and get a reference to it. ModeConfigBean modeBean = (ModeConfigBean) configBeanContext.getConfiguredBean("com.thesett.catalogue.config.ModeConfigBean"); // Create the catalogue logical model from the raw model. model = loaderBean.getCatalogue(); // Set up a static references to the component types on each component in the model. initializeAllTypes(); // Check if running in development mode. if (modeBean.isDevMode()) { log.debug("In dev mode, creating reference types in the database."); createReferenceTypes(); } // Not in development mode so running in production mode. else { log.warn("Todo: In production mode, loading and checking reference types from the database."); } // Rebuild the indexes from the database if necessary. if (!modeBean.isDevMode()) { log.warn("Todo: In production mode, re-building indexes from the database."); } } /** * Passes the catalogue model to all component type class implementations, so that they can reference back to their * component types in the knowledge level of the catalogue model. */ private void initializeAllTypes() { log.debug("private void initializeComponentTypes(): called"); for (ComponentType componentType : model.getAllComponentTypes()) { setStaticCatalogue(componentType); } for (HierarchyType hierarchyType : model.getAllHierarchyTypes()) { setStaticCatalogue(hierarchyType); } for (EnumeratedStringAttribute.EnumeratedStringType enumerationType : model.getAllEnumTypes()) { setStaticCatalogue(enumerationType); } } /** * Calls the static 'setCatalogue' method on a type, so that the type can reach the catalogue. * * @param type The type to call the static 'setCatalogue' method on. */ private void setStaticCatalogue(Type type) { try { String typeName = type.getName(); String typeClassName = StringUtils.toCamelCaseUpper(typeName); Class clz = null; if (type instanceof ViewType) { clz = ReflectionUtils.forName(model.getModelPackage() + "." + typeClassName + "Impl"); } else { clz = ReflectionUtils.forName(model.getModelPackage() + "." + typeClassName); } //Class clz = type.getBaseClass(); Method setCatalogueMethod = clz.getMethod("setModel", Catalogue.class); ReflectionUtils.callStaticMethod(setCatalogueMethod, new Object[] { model }); } catch (NoSuchMethodException e) { throw new IllegalStateException(e); } } /** Initialized all reference types in the database. */ private void createReferenceTypes() { createHierarchyReferenceTypes(); createEnumerationReferenceTypes(); } /** Initializes all hierarchy reference types in the database. */ private void createHierarchyReferenceTypes() { log.debug("private void createHierarchyReferenceTypes(): called"); for (HierarchyType hierarchyType : model.getAllHierarchyTypes()) { String hierarchyName = hierarchyType.getName(); String hierarchyClassName = StringUtils.toCamelCaseUpper(hierarchyName); Class theBeanClass = ReflectionUtils.forName(model.getModelPackage() + "." + hierarchyClassName); for (Iterator hierarchyIterator = hierarchyType.getAllPossibleValuesIterator(false); hierarchyIterator.hasNext();) { HierarchyAttribute hierarchyAttribute = hierarchyIterator.next(); Session session = hibernateBean.getSecondarySession(); Transaction transaction = session.beginTransaction(); // Create an instance of the hierarchy bean class using a constructor on the hierarchy value. Class[] arguments = new Class[] { HierarchyAttribute.class }; Constructor beanConstructor = ReflectionUtils.getConstructor(theBeanClass, arguments); Object theBean = ReflectionUtils.newInstance(beanConstructor, new Object[] { hierarchyAttribute }); log.debug("Created hierarchy bean: " + theBean); // Store the hierarchy value in the database. session.save(theBean); transaction.commit(); session.close(); } } } /** Initializes all enumeration reference types in the database. */ private void createEnumerationReferenceTypes() { log.debug("private void createEnumerationReferenceTypes(): called"); final AtomicLong id = new AtomicLong(); for (EnumeratedStringAttribute.EnumeratedStringType enumType : model.getAllEnumTypes()) { Session session = hibernateBean.getSecondarySession(); Transaction transaction = session.beginTransaction(); for (Iterator enumIterator = enumType.getAllPossibleValuesIterator(false); enumIterator.hasNext();) { final EnumeratedStringAttribute enumAttribute = enumIterator.next(); String enumName = enumAttribute.getType().getName(); String enumClassName = StringUtils.toCamelCaseUpper(enumName); // Create an instance of the enumeration bean class using a constructor on the enumeration value. Class theBeanClass = ReflectionUtils.forName(model.getModelPackage() + "." + enumClassName); Class[] arguments = new Class[] { EnumeratedStringAttribute.class }; Constructor beanConstructor = ReflectionUtils.getConstructor(theBeanClass, arguments); enumAttribute.setId(id.get()); Object theBean = ReflectionUtils.newInstance(beanConstructor, new Object[] { enumAttribute }); log.debug("Created enum bean: " + theBean); // Store the hierarchy value in the database. final String tableName = enumClassName + "_enumeration"; session.doWork(new Work() { public void execute(Connection connection) throws SQLException { PreparedStatement sql = null; sql = connection.prepareStatement("DELETE FROM " + tableName); sql.execute(); String value = enumAttribute.getStringValue(); sql = connection.prepareStatement("INSERT INTO " + tableName + " VALUES (?, ?)"); sql.setLong(1, id.getAndIncrement()); sql.setString(2, value); sql.execute(); } }); } transaction.commit(); session.close(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy