/*
* 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.framework.container.autoregister;
import java.util.ArrayList;
import java.util.List;
import org.seasar.framework.container.AutoBindingDef;
import org.seasar.framework.container.ComponentCustomizer;
import org.seasar.framework.container.ComponentDef;
import org.seasar.framework.container.InstanceDef;
import org.seasar.framework.container.factory.AnnotationHandler;
import org.seasar.framework.container.factory.AnnotationHandlerFactory;
import org.seasar.framework.util.ClassUtil;
import org.seasar.framework.util.ClassTraversal.ClassHandler;
/**
* コンポーネントを自動登録するための抽象クラスです。
*
* @author higa
*/
public abstract class AbstractComponentAutoRegister extends
AbstractAutoRegister implements ClassHandler {
/** クラスファイルの拡張子 */
protected static final String CLASS_SUFFIX = ".class";
/**
* BINDINGアノテーションの定義です。
*/
public static final String autoNaming_BINDING = "bindingType=may";
private AutoNaming autoNaming = new DefaultAutoNaming();
/**
* BINDINGアノテーションの定義です。
*/
public static final String instanceDef_BINDING = "bindingType=may";
private InstanceDef instanceDef;
/**
* BINDINGアノテーションの定義です。
*/
public static final String autoBindingDef_BINDING = "bindingType=may";
private AutoBindingDef autoBindingDef;
private boolean externalBinding = false;
/**
* BINDINGアノテーションの定義です。
*/
public static final String customizer_BINDING = "bindingType=may";
private ComponentCustomizer customizer;
/**
* AutoNamingを返します。
*
* @return AutoNaming
*/
public AutoNaming getAutoNaming() {
return autoNaming;
}
/**
* AutoNamingを設定します。
*
* @param autoNaming
* AutoNaming
*/
public void setAutoNaming(AutoNaming autoNaming) {
this.autoNaming = autoNaming;
}
/**
* インスタンス定義を返します。
*
* @return インスタンス定義
*/
public InstanceDef getInstanceDef() {
return instanceDef;
}
/**
* インスタンス定義を設定します。
*
* @param instanceDef
* インスタンス定義
*/
public void setInstanceDef(InstanceDef instanceDef) {
this.instanceDef = instanceDef;
}
/**
* 自動バインディング定義を返します。
*
* @return 自動バインディング定義
*/
public AutoBindingDef getAutoBindingDef() {
return autoBindingDef;
}
/**
* 自動バインディング定義を設定します。
*
* @param autoBindingDef
* 自動バインディング定義
*/
public void setAutoBindingDef(AutoBindingDef autoBindingDef) {
this.autoBindingDef = autoBindingDef;
}
/**
* 外部バインディングのデフォルト値を返します。
*
* @return 外部バインディングのデフォルト値
*/
public boolean isExternalBinding() {
return externalBinding;
}
/**
* 外部バインディングのデフォルト値を設定します。
*
* @param externalBinding
* 外部バインディングのデフォルト値
*/
public void setExternalBinding(boolean externalBinding) {
this.externalBinding = externalBinding;
}
/**
* コンポーネントカスタマイザを返します。
*
* @return コンポーネントカスタマイザ
*/
public ComponentCustomizer getCustomizer() {
return customizer;
}
/**
* コンポーネントカスタマイザを設定します。
*
* @param customizer
* コンポーネントカスタマイザ
*/
public void setCustomizer(ComponentCustomizer customizer) {
this.customizer = customizer;
}
public void processClass(final String packageName,
final String shortClassName) {
if (isIgnore(packageName, shortClassName)) {
return;
}
for (int i = 0; i < getClassPatternSize(); ++i) {
final ClassPattern cp = getClassPattern(i);
if (cp.isAppliedPackageName(packageName)
&& cp.isAppliedShortClassName(shortClassName)) {
register(ClassUtil.concatName(packageName, shortClassName));
return;
}
}
}
/**
* コンポーネント定義を作成してコンテナに登録します。
*
* @param className
* コンポーネントのクラス
*/
protected void register(final String className) {
final AnnotationHandler annoHandler = AnnotationHandlerFactory
.getAnnotationHandler();
final ComponentDef cd = annoHandler.createComponentDef(className,
instanceDef, autoBindingDef, externalBinding);
if (cd.getComponentName() == null) {
String[] names = ClassUtil.splitPackageAndShortClassName(className);
cd.setComponentName(autoNaming.defineName(names[0], names[1]));
}
annoHandler.appendDI(cd);
customize(cd);
annoHandler.appendInitMethod(cd);
annoHandler.appendDestroyMethod(cd);
annoHandler.appendAspect(cd);
annoHandler.appendInterType(cd);
getContainer().register(cd);
}
/**
* コンポーネント定義をカスタマイズします。
*
* @param componentDef
* コンポーネント定義
*/
protected void customize(ComponentDef componentDef) {
if (customizer != null) {
customizer.customize(componentDef);
}
}
/**
* コンポーネントを検索する対象となるパッケージの配列を返します。
* <p>
* コンポーネントを検索する対象のパッケージは<code>ClassPattern</code>に設定されたパッケージ名から
* 重複やサブパッケージを除いたものになります。 例えば<code>ClassPattern</code>に<code>aaa, aaa.bbb, bbb</code>が指定された場合、
* <code>aaa.bbb</code>は<code>aaa</code>のサブパッケージなので取り除かれ、
* <code>aaa, bbb</code>が検索対象のパッケージとなります。
* </p>
*
* @return コンポーネントを検索する対象となるパッケージの配列
*/
protected String[] getTargetPackages() {
final List result = new ArrayList();
for (int i = 0; i < getClassPatternSize(); ++i) {
final String packageName = getClassPattern(i).getPackageName();
boolean append = true;
for (int j = 0; j < result.size(); ++j) {
final String root = (String) result.get(j);
if (packageName.equals(root)) {
append = false;
break;
} else if (packageName.startsWith(root)) {
append = false;
break;
} else if (root.startsWith(packageName)) {
result.set(j, packageName);
append = false;
break;
}
}
if (append) {
result.add(packageName);
}
}
return (String[]) result.toArray(new String[result.size()]);
}
}