/*
* Copyright 2004-2015 the Seasar Foundation and the Others.
*
* 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.seasar.extension.jdbc.gen.internal.version;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.seasar.extension.jdbc.gen.internal.util.DefaultExcludesFilenameFilter;
import org.seasar.extension.jdbc.gen.internal.util.FileComparetor;
import org.seasar.extension.jdbc.gen.internal.util.FileUtil;
import org.seasar.extension.jdbc.gen.version.ManagedFile;
import org.seasar.framework.util.StringUtil;
/**
* {@link ManagedFile}の実装クラスです。
*
* @author taedium
*/
public class ManagedFileImpl implements ManagedFile {
/** 親の{@link ManagedFile} */
protected ManagedFile parent;
/** ファイル情報 */
protected FileInfo fileInfo;
/** 環境名つきファイル情報 */
protected FileInfo envNamedFileInfo;
/**
* インスタンスを構築します。
*
* @param basePath
* ベースパス
* @param relativePath
* ベースパスからの相対パス
* @param env
* 環境名
*/
protected ManagedFileImpl(String basePath, String relativePath, String env) {
this(null, basePath, relativePath, env);
}
/**
* インスタンスを構築します。
*
* @param parent
* 親の{@link ManagedFile}、このインスタンスがバージョンディレクトリの場合{@code null}
* @param basePath
* ベースパス
* @param relativePath
* ベースパスからの相対パス
* @param env
* 環境名
*/
protected ManagedFileImpl(ManagedFile parent, String basePath,
String relativePath, String env) {
if (basePath == null) {
throw new NullPointerException("basePath");
}
if (relativePath == null) {
throw new NullPointerException("relativePath");
}
this.parent = parent;
fileInfo = new FileInfo(basePath, basePath, relativePath, env);
if (env != null) {
envNamedFileInfo = new FileInfo(basePath + "#" + env, basePath,
relativePath, env);
}
}
public File asFile() {
return getFile();
}
public String getRelativePath() {
return getFileInfo().relativePath;
}
public String getName() {
return getFile().getName();
}
public boolean delete() {
return getFile().delete();
}
public boolean exists() {
return getFile().exists();
}
public boolean isDirectory() {
return getFile().isDirectory();
}
public ManagedFile getParent() {
return parent;
}
public boolean mkdir() {
return getFile().mkdir();
}
public boolean mkdirs() {
return getFile().mkdirs();
}
public boolean createNewFile() {
return FileUtil.createNewFile(getFile());
}
public List<ManagedFile> listManagedFiles() {
File[] files = getFile().listFiles();
if (files == null) {
return Collections.emptyList();
}
List<ManagedFile> list = new ArrayList<ManagedFile>(files.length);
for (File file : files) {
list.add(createChildInternal(file.getName()));
}
return list;
}
public List<ManagedFile> listManagedFiles(FilenameFilter filter) {
File[] files = getFile().listFiles(filter);
if (files == null) {
return Collections.emptyList();
}
List<ManagedFile> list = new ArrayList<ManagedFile>(files.length);
for (File file : files) {
list.add(createChildInternal(file.getName()));
}
return list;
}
public ManagedFile createChild(String childName) {
return createChildInternal(childName);
}
/**
* このインスタンスの子となるバージョン管理されたディレクトリを作成します。
*
* @param relativePath
* このインスタンスが表すファイルからの相対パス
* @return バージョン管理されたファイル
*/
protected ManagedFile createChildInternal(String relativePath) {
FileInfo info = getFileInfo();
ManagedFileImpl file = new ManagedFileImpl(this, info.logicalBasePath,
info.relativePath + File.separator + relativePath, info.env);
return file;
}
public List<File> listAllFiles() {
final Map<String, File> fileMap = new LinkedHashMap<String, File>();
if (envNamedFileInfo != null) {
traverseDirectory(envNamedFileInfo, fileMap);
}
traverseDirectory(fileInfo, fileMap);
return getFileList(fileMap);
}
/**
* ファイルのリストを返します。
*
* @param fileMap
* パスの文字列をキー、 {@link File}を値とするマップ
* @return ファイルのリストを
*/
protected List<File> getFileList(Map<String, File> fileMap) {
if (envNamedFileInfo == null) {
File[] files = fileMap.values().toArray(new File[fileMap.size()]);
return Arrays.asList(files);
}
List<String> pathList = new ArrayList<String>(fileMap.keySet());
Collections.sort(pathList);
List<File> fileList = new ArrayList<File>(pathList.size());
for (String path : pathList) {
fileList.add(fileMap.get(path));
}
return fileList;
}
/**
* ディレクトリを横断します。
*
* @param fileInfo
* ディレクトリの情報
* @param fileMap
* ディレクトリからの相対パスをキー、ファイルを値とするマップ
*/
protected void traverseDirectory(final FileInfo fileInfo,
final Map<String, File> fileMap) {
FileUtil.traverseDirectory(fileInfo.file,
new DefaultExcludesFilenameFilter(), new FileComparetor(),
new FileUtil.FileHandler() {
public void handle(File file) {
String canonicalPath = FileUtil.getCanonicalPath(file);
String path = StringUtil.trimPrefix(canonicalPath,
fileInfo.actualBasePath + File.separator);
if (!fileMap.containsKey(path)) {
fileMap.put(path, file);
}
}
});
}
public boolean hasChild() {
String[] paths = getFile().list();
return paths != null && paths.length > 0;
}
/**
* ファイルを返します。
*
* @return ファイル
*/
protected File getFile() {
return getFileInfo().file;
}
/**
* ファイル情報を返します。
*
* @return ファイル情報
*/
protected FileInfo getFileInfo() {
return envNamedFileInfo != null ? envNamedFileInfo : fileInfo;
}
/**
* ファイル情報です。
*
* @author taedium
*/
protected static class FileInfo {
/** 実際のベースパス */
protected String actualBasePath;
/** 論理的なベースパス */
protected String logicalBasePath;
/** ベースパスからの相対パス */
protected String relativePath;
/** 環境名 */
protected String env;
/** ファイル */
protected File file;
/**
* インスタンスを構築します。
*
* @param actualBasePath
* 実際のベースパス
* @param logicalBasePath
* 論理的なベースパス
* @param relativePath
* ベースパスからの相対パス
* @param env
* 環境名
*/
public FileInfo(String actualBasePath, String logicalBasePath,
String relativePath, String env) {
this.actualBasePath = actualBasePath;
this.logicalBasePath = logicalBasePath;
this.relativePath = relativePath;
this.env = env;
File f = new File(actualBasePath, relativePath);
this.file = FileUtil.getCanonicalFile(f);
}
}
}