Package ch.agent.crnickl.jdbc

Source Code of ch.agent.crnickl.jdbc.WriteMethodsForSchema

/*
*   Copyright 2012-2013 Hauser Olsson GmbH
*
* 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 ch.agent.crnickl.jdbc;

import java.sql.PreparedStatement;
import java.sql.ResultSet;

import ch.agent.crnickl.T2DBException;
import ch.agent.crnickl.T2DBMsg;
import ch.agent.crnickl.T2DBMsg.E;
import ch.agent.crnickl.api.AttributeDefinition;
import ch.agent.crnickl.api.DBObjectType;
import ch.agent.crnickl.api.Database;
import ch.agent.crnickl.api.Property;
import ch.agent.crnickl.api.Schema;
import ch.agent.crnickl.api.SeriesDefinition;
import ch.agent.crnickl.api.Surrogate;
import ch.agent.crnickl.api.UpdatableSchema;
import ch.agent.crnickl.impl.AttributeDefinitionImpl;
import ch.agent.crnickl.impl.DatabaseBackend;
import ch.agent.crnickl.impl.Permission;
import ch.agent.crnickl.impl.UpdatableSchemaImpl;
import ch.agent.crnickl.impl.UpdatableSchemaVisitor;

/**
* A stateless object with methods providing write access to schemas.
* @author Jean-Paul Vetterli
*/
public class WriteMethodsForSchema extends ReadMethodsForSchema {

  private static class Visitor implements UpdatableSchemaVisitor {

    private WriteMethodsForSchema m;

    private Visitor(WriteMethodsForSchema methods) {
      this.m = methods;
    }

    @Override
    public void visit(UpdatableSchema schema, SeriesDefinition def,
        SeriesDefinition original) throws T2DBException {
      if (def == null) {
        // delete series definition
        m.deleteSchemaComponents(schema, original.getNumber());
      } else {
        if (def.isErasing()) {
          AttributeDefinitionImpl<String> attribDef =
              new AttributeDefinitionImpl<String>(def.getNumber(),
              DatabaseBackend.MAGIC_NAME_NR, null, null);
          attribDef.edit();
          attribDef.setErasing(true);
          if (original == null) {
            // create erasing series
            m.createSchemaComponent(schema, def.getNumber(), null, attribDef);
          } else {
            // update series to erasing
            if (!original.isErasing())
              m.updateSchemaComponent(schema, def.getNumber(), null, attribDef);
          }
        }
        // description taken care of in the other visit() method
      }
    }

    @Override
    public void visit(UpdatableSchema schema, SeriesDefinition seriesDef,
        AttributeDefinition<?> attrDef,
        AttributeDefinition<?> origAttrDef) throws T2DBException {
      int seriesNr = seriesDef == null ? 0 : seriesDef.getNumber();
      if (attrDef == null) {
        // delete attribute definition
        m.deleteSchemaComponent(schema, seriesNr, origAttrDef.getNumber());
      } else {
        String description = null;
        if (seriesNr != 0) {
          if (attrDef.getNumber() == DatabaseBackend.MAGIC_NAME_NR)
            description = seriesDef.getDescription();
        }
        if (origAttrDef == null) {
          // create attribute definition
          m.createSchemaComponent(schema, seriesNr, description, attrDef);
        } else {
          // update attribute definition
          m.updateSchemaComponent(schema, seriesNr, description, attrDef);
        }
      }
    }
  }
 
  private UpdatableSchemaVisitor visitor;
 
  public WriteMethodsForSchema() {
    visitor = new Visitor(this);
  }
 
  private PreparedStatement create_schema;
  private static final String CREATE_SCHEMA = "insert into " + DB.SCHEMA_NAME + "(parent, label) values(?, ?)";
  /**
   * Create an empty schema in the database.
   * Throw an exception if the operation cannot be done.
   *
   * @param schema a schema
   * @throws T2DBException
   */
  public void createSchema(UpdatableSchema schema) throws T2DBException {
    Surrogate surrogate = null;
    Throwable cause = null;
    try {
      check(Permission.CREATE, schema);
      Schema base = schema.getBase();
      if (base != null)
        check(Permission.READ, base);
      create_schema = open(CREATE_SCHEMA, schema, create_schema);
      create_schema.setInt(1, getIdOrZero(base));
      create_schema.setString(2, schema.getName());
      surrogate = makeSurrogate(schema, executeAndGetNewId(create_schema));
      // IMPORTANT: upgrade surrogate before handling the schema's components
      schema.getSurrogate().upgrade(surrogate);
      updateSchemaComponents(schema);
    } catch (Exception e) {
      cause = e;
    } finally {
      create_schema = close(create_schema);
    }
    if (surrogate == null || cause != null)
      throw T2DBMsg.exception(cause, E.E30122, schema.getName());
  }
 
  private PreparedStatement delete_schema;
  private PreparedStatement delete_schema_components;
  private static final String DELETE_SCHEMA = "delete from " + DB.SCHEMA_NAME + " where id = ?";
  private static final String DELETE_SCHEMA_COMPONENTS = "delete from " + DB.SCHEMA_ITEM + " where id = ?";
  /**
   * Delete a schema from the database.
   * Throw an exception if the operation fails.
   *
   * @param schema a schema
   * @throws T2DBException
   */
  public void deleteSchema(UpdatableSchema schema) throws T2DBException {
    boolean done = false;
    Throwable cause = null;
    try {
      check(Permission.MODIFY, schema);
      delete_schema_components = open(DELETE_SCHEMA_COMPONENTS, schema, delete_schema_components);
      int id = getId(schema);
      delete_schema_components.setInt(1, id);
      delete_schema_components.execute();
      delete_schema = open(DELETE_SCHEMA, schema, delete_schema);
      delete_schema.setInt(1, id);
      delete_schema.execute();
      done = delete_schema.getUpdateCount() > 0;
    } catch (Exception e) {
      cause = e;
    } finally {
      delete_schema_components = close(delete_schema_components);
      delete_schema = close(delete_schema);
    }
    if (!done || cause != null)
      throw T2DBMsg.exception(cause, E.E30123, schema.getName());
  }

  private PreparedStatement create_schema_component;
  private static final String CREATE_SCHEMA_COMPONENT =
    "insert into " + DB.SCHEMA_ITEM + "(id, ssn, attrib, prop, value, descrip) " +
    "values(?, ?, ?, ?, ?, ?)";
  /**
   * Create an attribute definition in the database.
   * Throw an exception if the operation cannot be done.
   *
   * @param schema a schema
   * @param seriesNr a series number
   * @param description a string
   * @param def an attribute definition
   * @throws T2DBException
   */
  private void createSchemaComponent(UpdatableSchema schema, int seriesNr, String description, AttributeDefinition<?> def) throws T2DBException {
    boolean done = false;
    try {
      check(Permission.MODIFY, schema);
      create_schema_component = open(CREATE_SCHEMA_COMPONENT, schema, create_schema_component);
      create_schema_component.setInt(1, getId(schema));
      create_schema_component.setInt(2, seriesNr);
      create_schema_component.setInt(3, def.getNumber());
      if (def.isErasing()) {
        create_schema_component.setInt(4, 0);
        create_schema_component.setString(5, "");
        create_schema_component.setString(6, "");
      } else {
        Database database = schema.getSurrogate().getDatabase();
        Property<?> prop = ((JDBCDatabase)database).getReadMethodsForProperty().
            getProperty(def.getProperty().getSurrogate());
        if (prop == null)
          throw T2DBMsg.exception(E.E30130);
        create_schema_component.setInt(4, getId(prop));
        String value = def.getProperty().getValueType().toString(def.getValue());
        create_schema_component.setString(5, value == null ? "" : value);
        create_schema_component.setString(6, description == null ? "" : description);
      }
      create_schema_component.execute();
      done = create_schema_component.getUpdateCount() > 0;
    } catch (Exception e) {
      if (!done) {
        if (seriesNr == 0)
          throw T2DBMsg.exception(e, E.E30124, def.getNumber());
        else
          throw T2DBMsg.exception(e, E.E30125, def.getNumber(), seriesNr);
      }
    } finally {
      create_schema_component = close(create_schema_component);
    }
  }

  private PreparedStatement update_schema;
  private static final String UPDATE_SCHEMA =
    "update " + DB.SCHEMA_NAME + " set label = ?, parent = ? where id = ?";
  /**
   * Update the schema in the database.
   * Throw an exception if the operation cannot be done.
   *
   * @param schema a schema
   * @return true if the schema was updated
   * @throws T2DBException
   */
  public boolean updateSchema(UpdatableSchema schema) throws T2DBException {
    boolean done = false;
    Throwable cause = null;
    RawSchema rawSchema = getRawSchema(schema.getSurrogate());
    boolean nameEdited = nameEdited(schema, rawSchema);
    boolean baseEdited = baseEdited(schema, rawSchema);
    if (nameEdited || baseEdited) {
      try {
        Schema base = schema.getBase();
        check(Permission.MODIFY, schema);
        if (baseEdited && base != null)
          check(Permission.READ, base);
        update_schema = open(UPDATE_SCHEMA, schema, update_schema);
        update_schema.setString(1, schema.getName());
        update_schema.setInt(2, getIdOrZero(base));
        update_schema.setInt(3, getId(schema));
        update_schema.execute();
        done = update_schema.getUpdateCount() > 0;
      } catch (Exception e) {
        cause = e;
      } finally {
        update_schema = close(update_schema);
      }
    }
    try {
      done |= updateSchemaComponents(schema);
    } catch (Exception e) {
      cause = e;
    }
    if (!done || cause != null)
      throw T2DBMsg.exception(cause, E.E30126, schema);
    return done;
  }
 
  private boolean updateSchemaComponents(UpdatableSchema schema) throws T2DBException {
    return ((UpdatableSchemaImpl) schema).traverse(false, visitor) > 0;
  }
 
  private PreparedStatement delete_schema_by_attribute;
  private static final String DELETE_SCHEMA_BY_ATTRIBUTE =
    "delete from " + DB.SCHEMA_ITEM + " where id = ? and ssn = ? and attrib = ?";
  /**
   * Delete an attribute definition from the database.
   * Throw an exception if the operation cannot be done.
   *
   * @param schema a schema
   * @param seriesNr a series number
   * @param attribNr an attribute number
   * @throws T2DBException
   */
  private void deleteSchemaComponent(UpdatableSchema schema, int seriesNr, int attribNr) throws T2DBException {
    boolean done = false;
    Throwable cause = null;
    try {
      check(Permission.MODIFY, schema);
      delete_schema_by_attribute = open(DELETE_SCHEMA_BY_ATTRIBUTE, schema, delete_schema_by_attribute);
      delete_schema_by_attribute.setInt(1, getId(schema));
      delete_schema_by_attribute.setInt(2, seriesNr);
      delete_schema_by_attribute.setInt(3, attribNr);
      delete_schema_by_attribute.execute();
      if (delete_schema_by_attribute.getUpdateCount() > 0)
        done = true;
    } catch (Exception e) {
      cause = e;
    } finally {
      delete_schema_by_attribute = close(delete_schema_by_attribute);
    }
    if (!done || cause != null)
      throw T2DBMsg.exception(cause, E.E30128, schema, seriesNr, attribNr);
  }
 
  private PreparedStatement delete_schema_by_series;
  private static final String DELETE_SCHEMA_BY_SERIES =
    "delete from " + DB.SCHEMA_ITEM + " where id = ? and ssn = ?";
  /**
   * Delete a series definition from the database.
   * Throw an exception if the operation cannot be done.
   *
   * @param schema a schema
   * @param seriesNr a series number
   * @throws T2DBException
   */
  private void deleteSchemaComponents(UpdatableSchema schema, int seriesNr) throws T2DBException {
    boolean done = false;
    Throwable cause = null;
    try {
      check(Permission.MODIFY, schema);
      delete_schema_by_series = open(DELETE_SCHEMA_BY_SERIES, schema, delete_schema_by_series);
      delete_schema_by_series.setInt(1, getId(schema));
      delete_schema_by_series.setInt(2, seriesNr);
      delete_schema_by_series.execute();
      if (delete_schema_by_series.getUpdateCount() > 0)
        done = true;
    } catch (Exception e) {
      cause = e;
    } finally {
      delete_schema_by_series = close(delete_schema_by_series);
    }
    if (!done || cause != null)
      throw T2DBMsg.exception(cause, E.E30129, schema, seriesNr);
  }
 
  private PreparedStatement update_schema_by_attribute;
  private static final String UPDATE_SCHEMA_BY_ATTRIBUTE =
    "update " + DB.SCHEMA_ITEM + " set value = ?, descrip = ? where id = ? and ssn = ? and attrib = ?";
  /**
   * Update an attribute definition in the database.
   * Throw an exception if the operation cannot be done.
   *
   * @param schema a schema
   * @param seriesNr a series number
   * @param description a string
   * @param def an attribute definition
   * @throws T2DBException
   */
  private void updateSchemaComponent(UpdatableSchema schema, int seriesNr, String description, AttributeDefinition<?> def) throws T2DBException {
    boolean done = false;
    Throwable cause = null;
    try {
      check(Permission.MODIFY, schema);
      update_schema_by_attribute = open(UPDATE_SCHEMA_BY_ATTRIBUTE, schema, update_schema_by_attribute);
      String value = def.getProperty().getValueType().toString(def.getValue());
      update_schema_by_attribute.setString(1, value == null ? "" : value);
      update_schema_by_attribute.setString(2, description == null ? "" : description);
      update_schema_by_attribute.setInt(3, getId(schema));
      update_schema_by_attribute.setInt(4, seriesNr);
      update_schema_by_attribute.setInt(5, def.getNumber());
      update_schema_by_attribute.execute();
      if(update_schema_by_attribute.getUpdateCount() > 0)
        done = true;
    } catch (Exception e) {
      cause = e;
    } finally {
      update_schema_by_attribute = close(update_schema_by_attribute);
    }
    if (!done || cause != null)
      throw T2DBMsg.exception(cause, E.E30127, schema, seriesNr, def.getNumber());
  }
 
  private boolean nameEdited(UpdatableSchema schema, RawSchema current) {
    return !schema.getName().equals(current.getName());
  }
 
  private boolean baseEdited(UpdatableSchema schema, RawSchema current) {
    UpdatableSchema base = schema.getBase();
    int editedBaseId = getIdOrZero(base);
    int currentBaseId = current.getParent();
    return editedBaseId != currentBaseId;
  }
 
  private PreparedStatement find_entity_with_schema;
  private static final String FIND_ENTITY_WITH_SCHEMA = "select id from " + DB.CHRONICLE + " where schema_id = ?";
  /**
   * Find a chronicle referencing the schema.
   * This looks like a "reading" method but is used in the context of schema updating.
   *
   * @param schema a schema
   * @return a chronicle surrogate or null
   * @throws T2DBException
   */
  public Surrogate findChronicle(Schema schema) throws T2DBException {
    Surrogate result = null;
    Database database = schema.getSurrogate().getDatabase();
    try {
      find_entity_with_schema = open(FIND_ENTITY_WITH_SCHEMA, database, find_entity_with_schema);
      find_entity_with_schema.setInt(1, getId(schema));
      ResultSet rs = find_entity_with_schema.executeQuery();
      while (rs.next()) {
        result = makeSurrogate(database, DBObjectType.CHRONICLE, rs.getInt(1));
        break;
      }
    } catch (Exception e) {
      throw T2DBMsg.exception(e, E.E30117);
    } finally {
      find_entity_with_schema = close(find_entity_with_schema);
    }
    return result;
  }
 
  private PreparedStatement find_entity_with_property;
  private static final String FIND_ENTITY_WITH_PROPERTY = "select chronicle from " + DB.ATTRIBUTE_VALUE + " where prop = ?";
  /**
   * Find a chronicle with an explicit attribute value for a given property and schema.
   * This looks like a "reading" method but is used in the context of schema updating.
   *
   * @param property a property
   * @param schema a schema
   * @return a surrogate or null
   * @throws T2DBException
   */
  public Surrogate findChronicle(Property<?> property, Schema schema) throws T2DBException {
    Surrogate result = null;
    Database database = property.getSurrogate().getDatabase();
    try {
      find_entity_with_property = open(FIND_ENTITY_WITH_PROPERTY, property, find_entity_with_property);
      find_entity_with_property.setInt(1, getId(property));
      ResultSet rs = find_entity_with_property.executeQuery();
      while(rs.next()) {
        Surrogate entityKey = makeSurrogate(database, DBObjectType.CHRONICLE, rs.getInt(1));
        Schema s = database.getChronicle(entityKey).getSchema(true);
        if (s.dependsOnSchema(schema)) {
          result = entityKey;
          break;
        }
      }
    } catch (Exception e) {
      throw T2DBMsg.exception(e, E.E30117);
    } finally {
      find_entity_with_property = close(find_entity_with_property);
    }
    return result;
  }

  private PreparedStatement find_entity_with_series;
  private static final String FIND_ENTITY_WITH_SERIES = "select chronicle from " + DB.SERIES + " where ssn = ?";
  /**
   * Find a chronicle depending one a given series in a schema.
   * This looks like a "reading" method but is used in the context of schema updating.
   *
   * @param ss a series definition
   * @param schema a schema
   * @return a surrogate or null
   * @throws T2DBException
   */
  public Surrogate findChronicle(SeriesDefinition ss, Schema schema) throws T2DBException {
    Surrogate result = null;
    Database database = schema.getSurrogate().getDatabase();
    try {
      find_entity_with_series = open(FIND_ENTITY_WITH_SERIES, database, find_entity_with_series);
      find_entity_with_series.setInt(1, ss.getNumber());
      ResultSet rs = find_entity_with_series.executeQuery();
      while (rs.next()) {
        Surrogate entityKey = makeSurrogate(database, DBObjectType.CHRONICLE, rs.getInt(1));
        Schema s = database.getChronicle(entityKey).getSchema(true);
        if (s.dependsOnSchema(schema)) {
          result = entityKey;
          break;
        }
      }
    } catch (Exception e) {
      throw T2DBMsg.exception(e, E.E30117);
    } finally {
      find_entity_with_series = close(find_entity_with_series);
    }
    return result;
  }

}
TOP

Related Classes of ch.agent.crnickl.jdbc.WriteMethodsForSchema

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.