svnno****@sourc*****
svnno****@sourc*****
2008年 9月 12日 (金) 06:50:08 JST
Revision: 1914 http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi?root=jiemamy&view=rev&rev=1914 Author: shin1 Date: 2008-09-12 06:50:08 +0900 (Fri, 12 Sep 2008) Log Message: ----------- ChangeSupportの自動生成を実装 テンプレートの微調整等 Modified Paths: -------------- sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/CollectionProperty.java sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/JiemamyModelDoclet.java sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/resources/ChangeListener.vm sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/resources/ChangeSupport.vm Removed Paths: ------------- sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/App.java -------------- next part -------------- Deleted: sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/App.java =================================================================== --- sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/App.java 2008-09-11 17:43:24 UTC (rev 1913) +++ sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/App.java 2008-09-11 21:50:08 UTC (rev 1914) @@ -1,106 +0,0 @@ -package org.jiemamy.core.eventcodegen; - -import java.io.File; -import java.io.FileWriter; -import java.io.Writer; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; -import org.apache.velocity.exception.ParseErrorException; -import org.apache.velocity.exception.ResourceNotFoundException; -import org.jiemamy.core.model.AbstractModel; - -public class App { - static String SRC_ROOT = "../org.jiemamy.core/src/main/java"; - - public static void main(String[] args) throws Exception { - setupVelocity(); - SRC_ROOT = new File(".").getAbsoluteFile().getParent() + "/" + SRC_ROOT; - if (!SRC_ROOT.endsWith("/")) { - SRC_ROOT = SRC_ROOT + "/"; - } - processDirectory(new File(SRC_ROOT)); - } - - /** - * Velocityの初期化を行う。 - * - * @throws Exception - */ - public static void setupVelocity() throws Exception { - Properties p = new Properties(); - p.setProperty("resource.loader", "class"); - p.setProperty("class.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); - p.setProperty("input.encoding", "UTF-8"); - Velocity.init(p); - } - - /** - * org.jiemamy.coreのJavaソースディレクトリ配下を辿ってModelクラスのソースを探す。 - * org.jiemamy.core.modelパッケージ内のソースを発見した場合はそのClassをLoadし、 - * AbstractModelのサブクラスだった時は{@link #processModel(AbstractModel)}にそのインスタンスを渡す。 - * - * @param dir - * org.jiemamy.coreプロジェクトのJavaソースディレクトリ。 - */ - public static void processDirectory(File dir) { - if (dir.isDirectory()) { - for (File f : dir.listFiles()) { - if (f.isDirectory() && !f.getName().startsWith(".")) { - processDirectory(f); - } else if (f.isFile() && f.getAbsolutePath().indexOf("org/jiemamy/core/model/") >= 0) { - String modelJava = f.getAbsolutePath().replaceFirst(SRC_ROOT, ""); - modelJava = modelJava.replaceFirst(".java", ""); - modelJava = modelJava.replace("/", "."); - try { - Class<?> clazz = Class.forName(modelJava); - // Instance化出来ないものはInstantialtionExceptionを発生させて弾く。 - clazz.newInstance(); - // AbstractModelのサブクラスでないものはClassCastExceptionを発生させて弾く。 - Class<? extends AbstractModel> modelClass = clazz.asSubclass(AbstractModel.class); - processModel(modelClass); - } catch (Exception ex) { - // 無視する。 - } - } - } - } - } - - /** - * AbstractModelに対応するChangeListenerとChangeSupportのソースを生成する。 - * - * @param model - * @throws Exception - * @throws ParseErrorException - * @throws ResourceNotFoundException - */ - public static void processModel(Class<? extends AbstractModel> modelClass) throws ResourceNotFoundException, - ParseErrorException, Exception { - System.out.println(modelClass); - Field[] fields = modelClass.getDeclaredFields(); - // TODO Collection用Fieldを拾って、List<CollectionProperty>を作成する。 - List<CollectionProperty> properties = new ArrayList<CollectionProperty>(); - for (Field field : fields) { - System.out.println(" #" + field.getName() + ":" + field.getType().getName()); - properties.add(new CollectionProperty(field.getName(), field.getType(), null)); - } - - // - VelocityContext velocityContext = new VelocityContext(); - Template listenerTemplate = Velocity.getTemplate("ChangeListener.vm"); - Writer writer = new FileWriter("target/" + modelClass.getPackage().getName() + "." + modelClass.getSimpleName() - + "ChangeListener.java"); - velocityContext.put("modelClassName", modelClass.getSimpleName()); - velocityContext.put("properties", properties); - listenerTemplate.merge(velocityContext, writer); - writer.flush(); - writer.close(); - } -} Modified: sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/CollectionProperty.java =================================================================== --- sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/CollectionProperty.java 2008-09-11 17:43:24 UTC (rev 1913) +++ sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/CollectionProperty.java 2008-09-11 21:50:08 UTC (rev 1914) @@ -1,16 +1,51 @@ package org.jiemamy.core.eventcodegen; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.jiemamy.core.utils.collectionimpl.ObservableList; +import org.jiemamy.core.utils.collectionimpl.ObservableMap; +import org.jiemamy.core.utils.collectionimpl.ObservableSet; + public class CollectionProperty { private String name; + private String nameUpper; + private String nameSingle; private Class<?> collectionClass; + private Class<?> observableCollectionClass; private Class<?> elementClass; - public CollectionProperty(String name, Class<?> collectionClass, Class<?> elementClass) { + public CollectionProperty(String name, Class<?> collectionClass, + Class<?> elementClass) { this.name = name; + this.nameUpper = name.substring(0, 1).toUpperCase() + name.substring(1); + this.nameSingle = toSingle(name); this.collectionClass = collectionClass; this.elementClass = elementClass; + if (collectionClass.equals(List.class)) { + observableCollectionClass = ObservableList.class; + } else if (collectionClass.equals(Set.class)) { + observableCollectionClass = ObservableSet.class; + } else if (collectionClass.equals(Map.class)) { + observableCollectionClass = ObservableMap.class; + } } + /** + * 複数形を単数系に変換する. + * + * @param plural + * @return + */ + private String toSingle(String plural) { + if (plural.endsWith("es")) { + return plural.substring(0, name.length() - 2); + } else { + return plural.substring(0, name.length() - 1); + } + } + public Class<?> getCollectionClass() { return collectionClass; } @@ -34,4 +69,28 @@ public void setElementClass(Class<?> elementClass) { this.elementClass = elementClass; } + + public String getNameUpper() { + return nameUpper; + } + + public void setNameUpper(String nameUpper) { + this.nameUpper = nameUpper; + } + + public Class<?> getObservableCollectionClass() { + return observableCollectionClass; + } + + public void setObservableCollectionClass(Class<?> observableCollectionClass) { + this.observableCollectionClass = observableCollectionClass; + } + + public String getNameSingle() { + return nameSingle; + } + + public void setNameSingle(String nameSingle) { + this.nameSingle = nameSingle; + } } Modified: sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/JiemamyModelDoclet.java =================================================================== --- sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/JiemamyModelDoclet.java 2008-09-11 17:43:24 UTC (rev 1913) +++ sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/java/org/jiemamy/core/eventcodegen/JiemamyModelDoclet.java 2008-09-11 21:50:08 UTC (rev 1914) @@ -4,11 +4,11 @@ import java.io.FileWriter; import java.io.Writer; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Set; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; @@ -109,35 +109,30 @@ throws ResourceNotFoundException, ParseErrorException, Exception { System.out.println(classDoc.qualifiedTypeName() + ":" + getPackageName(classDoc)); - + List<String> importClasses = new ArrayList<String>(); + importClasses.add(classDoc.qualifiedTypeName()); + importClasses.add("org.jiemamy.core.event.ModelChangeListener"); + importClasses + .add("org.jiemamy.core.event.ObservableCollectionChangeEvent"); List<CollectionProperty> properties = new ArrayList<CollectionProperty>(); FieldDoc[] fields = classDoc.fields(); for (FieldDoc fieldDoc : fields) { String fieldTypeName = fieldDoc.type().qualifiedTypeName(); Class<?> fieldType = Class.forName(fieldTypeName); - try { - // ListのサブクラスでないものはClassCastExceptionを発生させて弾く。 - fieldType.asSubclass(List.class); - properties.add(new CollectionProperty(fieldDoc.name(), - Class.forName(fieldDoc.type().qualifiedTypeName() - .toString()), Class - .forName(getParameterClassName(fieldDoc)))); - continue; - } catch (Exception ex) { - // + if (isSubClass(fieldType, List.class) + || isSubClass(fieldType, List.class)) { + // ListまたはSetのサブクラス + String parameterClassName = getParameterClassName(fieldDoc); + duplicateCheckAndAddToList(importClasses, fieldTypeName); + duplicateCheckAndAddToList(importClasses, parameterClassName); + properties + .add(new CollectionProperty(fieldDoc.name(), Class + .forName(fieldDoc.type().qualifiedTypeName() + .toString()), Class + .forName(parameterClassName))); } - try { - // SetのサブクラスでないものはClassCastExceptionを発生させて弾く。 - fieldType.asSubclass(Set.class); - properties.add(new CollectionProperty(fieldDoc.name(), - Class.forName(fieldDoc.type().qualifiedTypeName() - .toString()), Class - .forName(getParameterClassName(fieldDoc)))); - continue; - } catch (Exception ex) { - // - } } + Collections.sort(importClasses); // Templateからjavaファイルを生成する。 try { String packageName = getPackageName(classDoc).replaceAll( @@ -146,25 +141,63 @@ if (!dir.exists()) { dir.mkdirs(); } + VelocityContext velocityContext = new VelocityContext(); + velocityContext.put("package", packageName); + velocityContext.put("importClasses", importClasses); + velocityContext.put("modelClassName", classDoc.name().toString()); + velocityContext.put("modelClassNameLower", classDoc.name() + .toString().substring(0, 1).toLowerCase() + + classDoc.name().toString().substring(1)); + velocityContext.put("properties", properties); + Template listenerTemplate = Velocity + .getTemplate("ChangeListener.vm"); File file = new File(dir.getAbsolutePath() + "/" + classDoc.name().toString() + "ChangeListener.java"); System.out.println(file.getAbsolutePath()); - VelocityContext velocityContext = new VelocityContext(); - Template listenerTemplate = Velocity - .getTemplate("ChangeListener.vm"); Writer writer = new FileWriter(file); - velocityContext.put("package", packageName); - velocityContext.put("modelClassName", classDoc.name().toString()); - velocityContext.put("properties", properties); listenerTemplate.merge(velocityContext, writer); writer.flush(); writer.close(); + + importClasses.add("java.util.ArrayList"); + importClasses.add("org.jiemamy.core.event.ModelChangeEvent"); + importClasses + .add("org.jiemamy.core.event.ObservableCollectionChangeListener"); + for (CollectionProperty property : properties) { + duplicateCheckAndAddToList(importClasses, property + .getObservableCollectionClass().getName()); + } + Collections.sort(importClasses); + Template supportTemplate = Velocity.getTemplate("ChangeSupport.vm"); + file = new File(dir.getAbsolutePath() + "/" + + classDoc.name().toString() + "ChangeSupport.java"); + System.out.println(file.getAbsolutePath()); + writer = new FileWriter(file); + supportTemplate.merge(velocityContext, writer); + writer.flush(); + writer.close(); } catch (Exception ex) { ex.printStackTrace(); } } /** + * あるクラスがあるクラスのサブクラスかどうか。 + * + * @param subClass + * @param superClass + * @return + */ + private static boolean isSubClass(Class<?> subClass, Class<?> superClass) { + try { + subClass.asSubclass(superClass); + return true; + } catch (Exception ex) { + return false; + } + } + + /** * パッケージ名を取得する。 * * @param classDoc @@ -188,4 +221,24 @@ int index2 = parameterizedType.lastIndexOf('>'); return parameterizedType.substring(index1 + 1, index2); } + + /** + * List内の要素に存在しない時のみListに追加する。 + * + * @param <E> + * @param list + * @param element + */ + private static <E> void duplicateCheckAndAddToList(List<E> list, E element) { + boolean exist = false; + for (E e : list) { + if (e.equals(element)) { + exist = true; + break; + } + } + if (!exist) { + list.add(element); + } + } } Modified: sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/resources/ChangeListener.vm =================================================================== --- sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/resources/ChangeListener.vm 2008-09-11 17:43:24 UTC (rev 1913) +++ sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/resources/ChangeListener.vm 2008-09-11 21:50:08 UTC (rev 1914) @@ -18,10 +18,6 @@ */ package ${package}; -import java.util.List; - -import org.jiemamy.core.event.ModelChangeListener; -import org.jiemamy.core.event.ObservableCollectionChangeEvent; #foreach(${importClass} in ${importClasses}) import ${importClass.toString()}; #end @@ -33,12 +29,12 @@ */ public interface ${modelClassName}ChangeListener extends ModelChangeListener { - #foreach($property in $properties) +#foreach($property in $properties) /** - * {@link ${modelClassName}}が保持する{@link ${property.name}}のCollectionに対する変更を処理する。 + * {@link ${modelClassName}}が保持する{@link ${property.elementClass.name}}のCollectionに対する変更を処理する。 * @param event */ - void ${property.name}CollectionChange(ObservableCollectionChangeEvent<${property.collectionClass.name}<${property.elementClass.name}>, ${property.elementClass.name}> event); - #end + void ${property.nameSingle}CollectionChange(ObservableCollectionChangeEvent<${property.collectionClass.simpleName}<${property.elementClass.simpleName}>, ${property.elementClass.simpleName}> event); +#end } Modified: sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/resources/ChangeSupport.vm =================================================================== --- sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/resources/ChangeSupport.vm 2008-09-11 17:43:24 UTC (rev 1913) +++ sandbox/org.jiemamy.core.eventcodegen/trunk/org.jiemamy.core.eventcodegen/src/main/resources/ChangeSupport.vm 2008-09-11 21:50:08 UTC (rev 1914) @@ -18,19 +18,13 @@ */ package org.jiemamy.core.event.model; -import java.util.ArrayList; -import java.util.List; - -import org.jiemamy.core.event.ModelChangeEvent; -import org.jiemamy.core.event.ModelChangeListener; -import org.jiemamy.core.event.ObservableCollectionChangeEvent; -import org.jiemamy.core.event.ObservableCollectionChangeListener; #foreach($importClass in $importClasses) import $importClass; #end /** * Event関連の処理をModel内に直接記述するとModelのSourceの可読性が低くなるため、${modelClassName}からそれらを引き受ける。 + * * @author shin1ogawa */ public class ${modelClassName}ChangeSupport { @@ -38,25 +32,39 @@ /** ${modelClassName}自身のEventを監視するListenerのリスト */ private List<${modelClassName}ChangeListener> listeners = new ArrayList<${modelClassName}ChangeListener>(); - #foreach($property in $properties) +#foreach($property in $properties) + /** * ${property.name}のリストを監視するListener * @see ObservableCollectionChangeListener - * @see #fireColumnsCollectionChangeEvent(ObservableCollectionChangeEvent) + * @see #fire${property.nameUpper}CollectionChangeEvent(ObservableCollectionChangeEvent) */ - private ObservableCollectionChangeListener<List<${property.elementClass.name}>, ${property.elementClass.name}> ${property.name}CollectionChangeListener = - new ObservableCollectionChangeListener<List<${property.elementClass.name}>, ${property.elementClass.name}>() { + private ObservableCollectionChangeListener<${property.collectionClass.simpleName}<${property.elementClass.simpleName}>, ${property.elementClass.simpleName}> ${property.name}CollectionChangeListener = + new ObservableCollectionChangeListener<${property.collectionClass.simpleName}<${property.elementClass.simpleName}>, ${property.elementClass.simpleName}>() { /** * {@inheritDoc} */ - public void collectionChanged(ObservableCollectionChangeEvent<List<${property.elementClass.name}>, ${property.elementClass.name}> event) { - fireColumnsCollectionChangeEvent(event); + public void collectionChanged(ObservableCollectionChangeEvent<${property.collectionClass.simpleName}<${property.elementClass.simpleName}>, ${property.elementClass.simpleName}> event) { + fire${property.nameUpper}CollectionChangeEvent(event); } }; - #end +#end + + /** + * ${modelClassName}の属性の変更Eventを処理するListener + * @see #fireModelChange(ModelChangeEvent) + */ + private ModelChangeListener ${modelClassNameLower}ChangeListener = new ModelChangeListener() { + + /** + * {@inheritDoc} + */ + public void modelChanged(ModelChangeEvent event) { + fireModelChange(event); + } + }; - /** * コンストラクタ。 * @param source {@link ${modelClassName}} @@ -64,9 +72,9 @@ */ public ${modelClassName}ChangeSupport(${modelClassName} source) { source.addModelChangeListener(${modelClassNameLower}ChangeListener); - #foreach($property in $properties) - ((ObservableList<ColumnModel>) source.get${property.nameUpper}()).addListener(${property.name}CollectionChangeListener); - #end +#foreach($property in $properties) + ((${property.observableCollectionClass.simpleName}<${property.elementClass.simpleName}>) source.get${property.nameUpper}()).addListener(${property.name}CollectionChangeListener); +#end } /** @@ -78,18 +86,18 @@ listeners.add(l); } - #foreach($property in $properties) +#foreach($property in $properties) /** * ${property.name}のcollectionを監視するListenerに通知されたEventを${modelClassName}の監視Listenerへ通知する。 * @param event {@link ObservableCollectionChangeEvent} */ - public void fireChecksCollectionChangeEvent( - ObservableCollectionChangeEvent<List<${property.elementClass.name}>, ${property.elementClass.name}> event) { + public void fire${property.nameUpper}CollectionChangeEvent( + ObservableCollectionChangeEvent<${property.collectionClass.simpleName}<${property.elementClass.simpleName}>, ${property.elementClass.simpleName}> event) { for (TableModelChangeListener l : listeners) { - l.${property.name}CollectionChange(event); + l.${property.nameSingle}CollectionChange(event); } } - #end +#end /** * ${modelClassName}自身を監視するListenerに通知されたEventを${modelClassName}の監視Listenerへ通知する。