@Override
  public List<AlternativeGenerator> getAlternativeGenerators() {
    List<AlternativeGenerator> generators = CollectionsUtil.newArrayList(10);
    generators.add(
        new AlternativeGenerator() {
          @Override
          public String getName() {
            return "sequence";
          }

          @Override
          public void generate(
              List<Map<String, String>> objectDef, AbstractDbObjectParser context) {
            if (CollectionUtils.isEmpty(objectDef)) return;

            try {
              FileUtils.write(
                  new File(context.getOutputDirectory(), "01_CREATE_SEQUENCES.sql"),
                  "create TABLE sequences("
                      + "name varchar(255) primary key,"
                      + "seq BIGINT default 1);");
            } catch (IOException e) {
              throw new IORuntimeException(e);
            }
          }
        });
    return generators;
  }
/**
 * 期待値を読み込む実装クラスです。
 *
 * <p>期待値はExcelから読み込みます。
 *
 * @author taedium
 */
public class ExpectedDataReaderImpl implements ExpectedDataReader {

  /** ロガー */
  protected static final Logger logger = Logger.getLogger(ExpectedDataReaderImpl.class);

  /** 期待値が記述されたExcelのパスのリスト */
  protected final List<String> expectedDataXlsPaths = CollectionsUtil.newArrayList();

  /** データアクセッサー */
  protected DataAccessor dataAccessor;

  /**
   * データアクセッサーを設定します。
   *
   * @param dataAccessor データアクセッサー
   */
  @Binding(bindingType = BindingType.MUST)
  public void setDataAccessor(final DataAccessor dataAccessor) {
    this.dataAccessor = dataAccessor;
  }

  /**
   * 期待値が記述されたExcelのパスを登録します。
   *
   * @param path 期待値が記述されたExcelのパス
   */
  public void addExpectedDataXlsPath(final String path) {
    expectedDataXlsPaths.add(path);
  }

  public DataSet read(TestContext testContext) {
    final String dirPath = testContext.getTestClassPackagePath();
    final boolean trimString = testContext.isTrimString();
    for (final String path : expectedDataXlsPaths) {
      if (ResourceUtil.isExist(path)) {
        return readXls(path, trimString);
      }
      final String newPath = dirPath + "/" + path;
      if (ResourceUtil.isExist(newPath)) {
        return readXls(newPath, trimString);
      }
    }
    return null;
  }

  /**
   * 指定されたExcelを読みデータセットとして返します。
   *
   * @param path Excelのパス
   * @param trimString 文字列に含まれる空白を取り除く場合<code>true</code>
   * @return Excel内のデータのデータセット表現
   */
  protected DataSet readXls(final String path, final boolean trimString) {
    if (logger.isDebugEnabled()) {
      logger.log("DSSR0104", new Object[] {path});
    }
    return dataAccessor.readXls(path, trimString);
  }
}
Example #3
0
 /**
  * {@link #ignoreWhitespace()}が呼び出された場合で パラメータ値の要素が空文字列または空白のみの文字列なら <code>null</code>、
  * それ以外なら元の値からなるリストを返します。
  *
  * @param values パラメータ値のコレクション
  * @return {@link #ignoreWhitespace()}が呼び出された場合でパラメータ値の要素が空文字列または空白のみの文字列なら <code>null</code>、
  *     それ以外なら元の値からなるリスト
  */
 protected Collection<?> normalizeList(final Collection<?> values) {
   if (!excludesWhitespace || values == null) {
     return values;
   }
   final List<Object> list = CollectionsUtil.newArrayList(values.size());
   for (final Object value : values) {
     final Object normalizedValue = normalize(value);
     if (normalizedValue != null) {
       list.add(normalizedValue);
     }
   }
   return list;
 }
Example #4
0
 /**
  * {@link #ignoreWhitespace()}が呼び出された場合で パラメータ値の要素が空文字列または空白のみの文字列なら <code>null</code>、
  * それ以外なら元の値からなる配列を返します。
  *
  * @param values パラメータ値の配列
  * @return {@link #ignoreWhitespace()}が呼び出された場合でパラメータ値の要素が空文字列または空白のみの文字列なら <code>null</code>、
  *     それ以外なら元の値からなる配列
  */
 protected Object[] normalizeArray(final Object... values) {
   if (!excludesWhitespace || values == null) {
     return values;
   }
   final List<Object> list = CollectionsUtil.newArrayList(values.length);
   for (int i = 0; i < values.length; ++i) {
     final Object normalizedValue = normalize(values[i]);
     if (normalizedValue != null) {
       list.add(normalizedValue);
     }
   }
   return list.toArray(new Object[list.size()]);
 }
/**
 * 未ロードのクラスをトランスフォームし、トランスフォーム後のクラスのクラスを適切なクラスローダーにロードするクラスローダです。
 *
 * @author taedium
 */
public class TransformClassLoader extends AbstractClassLoader {

  /** 永続クラスのトランスフォーマ */
  protected PersistenceClassTransformer persistenceClassTransformer;

  /** 永続ユニット情報 */
  protected PersistenceUnitInfo persistenceUnitInfo;

  /** クラストランスフォーマのリスト */
  protected List<ClassTransformer> transformers = CollectionsUtil.newArrayList();

  /**
   * インスタンスを構築します。
   *
   * <p>コンテキストクラスローダからロードされるクラス及び、<code>java.</code>または<code>javax.</code>で始まるクラスを除いて
   * 親クラスローダに委譲せず、{@link PersistenceClassTransformer#transform(PersistenceUnitInfo, String, byte[])}
   * を呼び出してロードするように構成します。
   */
  public TransformClassLoader() {
    this(Thread.currentThread().getContextClassLoader());
  }

  /**
   * インスタンスを構築します。
   *
   * <p>ブートストラップクラスローダからロードされるクラス及び、<code>java.</code>または<code>javax.</code>で始まるクラスを除いて
   * 親クラスローダに委譲せず、{@link PersistenceClassTransformer#transform(PersistenceUnitInfo, String, byte[])}
   * を呼び出してロードするように構成します。
   *
   * @param parent 親クラスローダ
   */
  public TransformClassLoader(ClassLoader parent) {
    super(parent);
  }

  /**
   * インスタンスを構築します。
   *
   * <p><code>includedNames</code>に含まれる名前のクラスのみ、 親クラスローダに委譲せず、 {@link
   * PersistenceClassTransformer#transform(PersistenceUnitInfo, String, byte[])}を呼び出してロードするように構成します。
   * ただし、ブートストラップクラスローダからロードされるクラス及び、 <code>java.</code>または<code>javax.</code>で始まるクラスを除きます。
   *
   * @param parent 親クラスローダ
   * @param includedNames 親より先にロードする対象となるクラス名のセット
   */
  public TransformClassLoader(final ClassLoader parent, final Set<String> includedNames) {
    super(parent, includedNames);
  }

  /**
   * 永続クラスのトランスフォーマを登録します。
   *
   * @param persistenceClassTransformer 永続クラスのトランスフォーマ
   */
  public void registerPersistenceClassTransformer(
      final PersistenceClassTransformer persistenceClassTransformer) {
    this.persistenceClassTransformer = persistenceClassTransformer;
  }

  /**
   * 永続ユニット情報を登録します。
   *
   * @param persistenceUnitInfo 永続ユニット情報
   */
  public void registerPersistenceUnitInfo(final PersistenceUnitInfo persistenceUnitInfo) {
    this.persistenceUnitInfo = persistenceUnitInfo;
  }

  /**
   * クラストランスフォーマを登録します。
   *
   * @param transformer クラストランスフォーマ
   */
  public void addTransformer(final ClassTransformer transformer) {
    transformers.add(transformer);
  }

  @Override
  protected Class<?> doDefineClass(String className, byte[] bytes) {
    return persistenceClassTransformer.transform(persistenceUnitInfo, className, bytes);
  }
}
/**
 * {@link AutoBatchUpdate}の実装クラスです。
 *
 * @author koichik
 * @param <T> エンティティの型です。
 */
public class AutoBatchUpdateImpl<T> extends AbstractAutoBatchUpdate<T, AutoBatchUpdate<T>>
    implements AutoBatchUpdate<T> {

  /** UDPATE文 */
  protected static final String UPDATE_STATEMENT = "update ";

  /** バージョンプロパティを更新対象に含める場合<code>true</code> */
  protected boolean includeVersion;

  /** 更新対象とするプロパティ */
  protected final Set<String> includesProperties = CollectionsUtil.newHashSet();

  /** 更新から除外するプロパティ */
  protected final Set<String> excludesProperties = CollectionsUtil.newHashSet();

  /** 更新対象となるプロパティメタデータの{@link List} */
  protected final List<PropertyMeta> targetProperties = CollectionsUtil.newArrayList();

  /** set句 */
  protected final SetClause setClause = new SetClause();

  /** where句 */
  protected final WhereClause whereClause = new WhereClause();

  /**
   * @param jdbcManager 内部的なJDBCマネージャ
   * @param entities エンティティのリスト
   */
  public AutoBatchUpdateImpl(final JdbcManagerImplementor jdbcManager, final List<T> entities) {
    super(jdbcManager, entities);
  }

  public AutoBatchUpdate<T> includesVersion() {
    includeVersion = true;
    return this;
  }

  public AutoBatchUpdate<T> includes(final CharSequence... propertyNames) {
    includesProperties.addAll(Arrays.asList(toStringArray(propertyNames)));
    return this;
  }

  public AutoBatchUpdate<T> excludes(final CharSequence... propertyNames) {
    excludesProperties.addAll(Arrays.asList(toStringArray(propertyNames)));
    return this;
  }

  public AutoBatchUpdate<T> suppresOptimisticLockException() {
    suppresOptimisticLockException = true;
    return this;
  }

  @Override
  protected void prepare(final String methodName) {
    prepareCallerClassAndMethodName(methodName);
    prepareTargetProperties();
    prepareSetClause();
    prepareWhereClause();
    prepareSql();
  }

  /** set句に設定されるプロパティの準備をします。 */
  protected void prepareTargetProperties() {
    for (final PropertyMeta propertyMeta : entityMeta.getAllColumnPropertyMeta()) {
      final String propertyName = propertyMeta.getName();
      if (propertyMeta.isId() || !propertyMeta.getColumnMeta().isUpdatable()) {
        continue;
      }
      if (propertyMeta.isVersion() && !includeVersion) {
        continue;
      }
      if (!includesProperties.isEmpty() && !includesProperties.contains(propertyName)) {
        continue;
      }
      if (excludesProperties.contains(propertyName)) {
        continue;
      }
      targetProperties.add(propertyMeta);
    }
  }

  /** set句の準備をします。 */
  protected void prepareSetClause() {
    for (final PropertyMeta propertyMeta : targetProperties) {
      setClause.addSql(propertyMeta.getColumnMeta().getName());
    }
    if (!includeVersion && entityMeta.hasVersionPropertyMeta()) {
      final PropertyMeta propertyMeta = entityMeta.getVersionPropertyMeta();
      final String columnName = propertyMeta.getColumnMeta().getName();
      setClause.addSql(columnName, columnName + " + 1");
    }
  }

  /** where句の準備をします。 */
  protected void prepareWhereClause() {
    for (final PropertyMeta propertyMeta : entityMeta.getIdPropertyMetaList()) {
      whereClause.addAndSql(
          ConditionType.EQ.getCondition(propertyMeta.getColumnMeta().getName(), null));
    }
    if (!includeVersion && entityMeta.hasVersionPropertyMeta()) {
      final PropertyMeta propertyMeta = entityMeta.getVersionPropertyMeta();
      whereClause.addAndSql(
          ConditionType.EQ.getCondition(propertyMeta.getColumnMeta().getName(), null));
    }
  }

  @Override
  protected void prepareParams(final T entity) {
    for (final PropertyMeta propertyMeta : targetProperties) {
      final Object value = FieldUtil.get(propertyMeta.getField(), entity);
      addParam(value, propertyMeta);
    }
    for (final PropertyMeta propertyMeta : entityMeta.getIdPropertyMetaList()) {
      final Object value = FieldUtil.get(propertyMeta.getField(), entity);
      addParam(value, propertyMeta);
    }
    if (!includeVersion && entityMeta.hasVersionPropertyMeta()) {
      final PropertyMeta propertyMeta = entityMeta.getVersionPropertyMeta();
      final Object value = FieldUtil.get(propertyMeta.getField(), entity);
      addParam(value, propertyMeta);
    }
  }

  /**
   * SQLに変換します。
   *
   * @return SQL
   */
  @Override
  protected String toSql() {
    final String tableName = entityMeta.getTableMeta().getFullName();
    final StringBuilder buf =
        new StringBuilder(
            UPDATE_STATEMENT.length()
                + tableName.length()
                + setClause.getLength()
                + whereClause.getLength());
    return new String(
        buf.append(UPDATE_STATEMENT)
            .append(tableName)
            .append(setClause.toSql())
            .append(whereClause.toSql()));
  }

  @Override
  protected boolean isOptimisticLock() {
    return !includeVersion && entityMeta.hasVersionPropertyMeta();
  }

  @Override
  protected void incrementVersions() {
    if (includeVersion) {
      return;
    }
    final Field field = entityMeta.getVersionPropertyMeta().getField();
    for (final T entity : entities) {
      if (field.getType() == int.class || field.getType() == Integer.class) {
        final int version = IntegerConversionUtil.toPrimitiveInt(FieldUtil.get(field, entity)) + 1;
        FieldUtil.set(field, entity, Integer.valueOf(version));
      } else if (field.getType() == long.class || field.getType() == Long.class) {
        final long version = LongConversionUtil.toPrimitiveLong(FieldUtil.get(field, entity)) + 1;
        FieldUtil.set(field, entity, Long.valueOf(version));
      }
    }
  }
}