@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); } }
/** * {@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; }
/** * {@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)); } } } }