Hatena::¥Ö¥í¥°(Diary)

soundTrick ¤³¤Î¥Ú¡¼¥¸¤ò¥¢¥ó¥Æ¥Ê¤ËÄɲà RSS¥Õ¥£¡¼¥É

2011-01-16 GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã ¤½¤Î3 GIN¤ÈÌû²÷¤ÊÃç´Ö¤¿¤Á

GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã ¤½¤Î3 GIN¤ÈÌû²÷¤ÊÃç´Ö¤¿¤Á

| 14:35 | GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã ¤½¤Î3 GIN¤ÈÌû²÷¤ÊÃç´Ö¤¿¤Á¤ò´Þ¤à¥Ö¥Ã¥¯¥Þ¡¼¥¯ GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã ¤½¤Î3 GIN¤ÈÌû²÷¤ÊÃç´Ö¤¿¤Á¤Î¥Ö¥Ã¥¯¥Þ¡¼¥¯¥³¥á¥ó¥È

ÌÀ¤±¤Þ¤·¤Æ¤ª¤á¤Ç¤È¤¦¤´¤¶¤¤¤Þ¤¹¡£ÁêÊѤï¤é¤ºÆÉ¤ß¤Ë¤¯¤¤Ê¸¾Ï¤Ç¤¹¤¬¤è¤í¤·¤¯¤ª´ê¤¤Ãפ·¤Þ¤¹¡£
º£Ç¯¤â¤¢¤Þ¤êµ­»ö¤ò½ñ¤«¤Ê¤½¤¦¤Ç¤¹¤¬¡¢´èÄ¥¤ê¤¿¤¤¤È»×¤¤¤Þ¤¹¡£

¤µ¤Æ¤³¤³ºÇ¶á¤Ï¤Ò¤¿¤¹¤éappengine + gwt ¤·¤«¤ä¤Ã¤Æ¤¤¤Ê¤¤¤ï¤±¤Ç¤¹¤¬¡¢
ǯËöÊÕ¤ê¤Ë¤ä¤Ã¤¿GWT ¤ÎMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤Ë¤Ä¤¤¤Æ½ñ¤­¤¿¤¤¤È»×¤¤¤Þ¤¹¡£
Ëè²ó¤Î¤È¤ª¤ê¡¢ËÝÌõǽÎϤ¬Ä㤤¤¿¤á¡¢´Ö°ã¤Ã¤Æ¤¤¤ëÉôʬ¤¬¤¢¤ë¤«¤È»×¤¤¤Þ¤¹¤¬¡¢¸«¼é¤Ã¤Æ¤¤¤¿¤À¤±¤¿¤é¹¬¤¤¤Ç¤¹¡£

¤È¤¤¤¦¤³¤È¤ÇÁ°²óGWT¤ÎActivity + Place ¤Ë¤Ä¤¤¤Æµ­ºÜ¤·¤Þ¤·¤¿¤¬¡¢º£²ó¤Ï¤½¤ì¤ËGWTÍѤÎDI¥³¥ó¥Æ¥ÊGIN *1 ¤ò´Þ¤á¤Æ¤è¤ê´Êñ¤ËActivity + Place¤ò¼Â¸½¤·¤¿¤¤¤È»×¤¤¤Þ¤¹¡£

GIN¤È¤Ï

GIN¤ÏGWTÍѤ˺îÀ®¤µ¤ì¤¿DI¥³¥ó¥Æ¥Ê*2¤ÇGoogleÀ½¤ÎDI¥³¥ó¥Æ¥Ê Guice¤ò¤â¤È¤ËºîÀ®¤µ¤ì¤Æ¤¤¤Þ¤¹¡£
Guice¼«ÂΤÏÀßÄê¥Õ¥¡¥¤¥ë¤Ç¤Ê¤¯Java¤Î¥³¡¼¥É¤ÇÀßÄê¤ò½ñ¤¯DI¥³¥ó¥Æ¥Ê¤È¤·¤Æ¡¢appengine¤Ç¤âÍøÍѤǤ­¤ë¤Ê¤É*3
¸Ä¿ÍŪ¤Ë¤Ï¤«¤Ê¤ê¹¥¤­¤ÊDI¥³¥ó¥Æ¥Ê¤Ç¤¹¡£
ÍøÍÑÊýË¡¤â¤Û¤Ü¤Û¤ÜGuice¤ÈƱ¤¸¤Ç¤¹¤¬¡¢AOP¤¬È󥵥ݡ¼¥È¤Ê¤ÉGWTÆÃÍ­¤ÎÊʤ¬¤¢¤Ã¤¿¤ê¤·¤Þ¤¹¡£
ºÙ¤«¤Ê»È¤¤Êý¤Ê¤É¤Ê¤É¤Ï¸ø¼°¥µ¥¤¥È¤ä¥°¥°¥Ã¤Æ¤¯¤À¤µ¤¤¡£
¥Æ¥ó¥·¥ç¥óŪ¤Ë³Æ¸µµ¤¤¬¤¢¤Ã¤¿¤é¤¤¤Ä¤«Â¿Ê¬½ñ¤­¤Þ¤¹¡£¡£¡£

¤Ã¤Æ¤³¤È¤Ç¼ÂÁõ¡ª¡ª

º£²ó¤Ï¾åµ­¤ÎGIN¤òÍøÍѤ·¤Æ¡¢Activity + Place¤ò³Ú¤Ë¤·¤Æ¤ß¤Þ¤¹¡£ ¤Á¤Ê¤ß¤Ë»²¹Í¤Ë¤·¤¿¤Î¤ÏGWT¤ÎML¤Ç¤¹(¤³¤³)¡£

¤Ê¤ªº£²ó¤Îµ­»ö¤ÏGWT2.1¤ÎMVP¤¬Ê¬¤«¤Ã¤Æ¤¤¤ëÁ°Äó¤Ç½ñ¤¯¤Î¤Ç¤¢¤·¤«¤é¤º¡£
¤ï¤«¤é¤Ê¤¤Êý¤ÏÁ°²ó¤Îµ­»ö¤òÆÉ¤à¤³¤È¤ò¤ª¤¹¤¹¤á¤·¤Þ¤¹¡£

¤Þ¤º¤ÏDI¤ÎÀßÄê Module¥¯¥é¥¹

¤Þ¤º¤ÏDI¤ÎÀßÄê¤ò¹Ô¤¤¤Þ¤¹¡£Guice¤Ç¤ÏÁ°½Ò¤Î¤È¤ª¤ê¡¢Java¤ÇÀßÄê¤ò½ñ¤­¤Þ¤¹¡ÊModule¥¯¥é¥¹¤È¤¤¤¤¤Þ¤¹¡Ë¡£GIN¤Ç¤âƱÍͤËAbstractGinModule¤ò·Ñ¾µ¤·¤¿¡¢¥¯¥é¥¹¤ËÀßÄê¤òµ­ºÜ¤·¤Æ¤­¤Þ¤¹¡£
¤¹¤Ù¤Æ¤ÎÀßÄê¤ò1¥¯¥é¥¹¤Ëµ­½Ò¤·¤Æ¤·¤Þ¤¦¤È´ÉÍý¤¬¤á¤ó¤É¤¯¤µ¤¤¤Î¤Ç
Guice(GIN)¤Ç¤Ï¤³¤ÎModule¥¯¥é¥¹¤òʬ¤±¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£
¤Ê¤Î¤ÇMVP¤ÎÀßÄê¥â¥¸¥å¡¼¥ë¤òºîÀ®¤·¤Þ¤¹¡£


package stk.client.inject;

¢¨import

public class MvpModule extends AbstractGinModule {

	@Override
	protected void configure() {
	}

	@Provides
	@Singleton
	public EventBus eventBus() {
		return new SimpleEventBus();
	}

	@Provides
	@Singleton
	@Named("contents")
	public SimplePanel contentsPanel() {
		SimplePanel simplePanel = new SimplePanel();
		simplePanel.addStyleName(Resources.INSTANCE.site().contentsPanel());
		return simplePanel;
	}

	@Provides
	@Singleton
	public PlaceController placeController(EventBus eventBus) {
		return new PlaceController(eventBus);
	}

	@Provides
	@Singleton
	public ActivityMapper activityMapper() {
		return new AppActivityMapper();
	}

	@Provides
	@Singleton
	public ActivityManager activityManager(	ActivityMapper mapper,EventBus eventBus,@Named("contents") SimplePanel contentsPanel) {
		ActivityManager activityManager = new ActivityManager(mapper, eventBus);
		activityManager.setDisplay(contentsPanel);
		return activityManager;
	}

	@Provides
	@Singleton
	public PlaceHistoryHandler placeHistoryHandler(	AppPlaceHistoryMapper mapper,PlaceController placeController,EventBus eventBus,TopPlace defaultPlace,MyInjector injector) {

		mapper.setFactory(injector);

		PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(mapper);

		historyHandler.register(placeController,eventBus,defaultPlace);

		return historyHandler;
	}
}

º£²ó¤ÎMvpModule¥¯¥é¥¹¤Ç¤Ï@Provides¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤òÍøÍѤ·¤¿ÊýË¡¤ÇÀßÄê¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
¤³¤ÎÊýË¡¤Ï¤¢¤ëDI¤ÎÀßÄê¤ò¹Ô¤¤¤¿¤¤¥¯¥é¥¹¤Ë½é´ü²½½èÍý¤òÆþ¤ì¤¿¤¤¾ì¹ç¤Ê¤É¤ËÈó¾ï¤ËÊØÍø¤Ç¤¹¡£
¤½¤ì¤Ç¤Ï³Æ¥á¥½¥Ã¥É¤Ë¤Ä¤¤¤Æ¤ß¤Æ¤¤¤­¤Þ¤¹¡£

configure¥á¥½¥Ã¥É

configure¥á¥½¥Ã¥É¤ÏDI¤ÎÀßÄê¤ò³Æ¥á¥½¥Ã¥É¤Ç¤¹¡£Ä̾ï¤Ï¤³¤³¤Ë¤É¤Î¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤Ë¤É¤Î¥¯¥é¥¹¤òDI¤µ¤»¤ë¤«¤Ê¤É¤òµ­ºÜ¤·¤Æ¤¤¤­¤Þ¤¹¡£
¤Þ¤¿¸åµ­¤·¤Þ¤¹¤¬¡¢Â¾¤ÎModuleÆÉ¤ß¹þ¤ß¤âconfigure¥á¥½¥Ã¥ÉÆâ¤Çµ­ºÜ¤·¤Þ¤¹¡£
¤¿¤È¤¨¤Ð¤³¤Î¥¯¥é¥¹Æâ¤ÎeventBus¥á¥½¥Ã¥É¤òconfigure¥á¥½¥Ã¥ÉÆâ¤ÇƱ¤¸ÀßÄê¤Çµ­ºÜ¤¹¤ë¤È°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£

	@Override
	protected void configure() {
		bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class);
	}

¤³¤Î¤è¤¦¤ËModule¥¯¥é¥¹¤Ç¤Ï¤¤¤í¤¤¤í¤ÊÀßÄê¤Î½ñ¤­Êý¤¬¤¢¤ê¤Þ¤¹¡£
¤Á¤Ê¤ß¤Ëº£²ó¤ï¤¶¤ï¤¶eventBus¥á¥½¥Ã¥É¤ËÀÚ¤ê½Ð¤·¤Æ¤¤¤ë¤Î¤Ï¤Ê¤ó¤È¤Ê¤¯¡Ê¤È¤¤¤¦¤è¤ê²£Ê¤Ӵ¶¡Ë¤Ê¤Î¤Çµ¤¤Ë¤·¤Ê¤¤¤Ç¤¯¤À¤µ¤¤¡£
¤Þ¤¿Guice¤òÍøÍѤ·¤¿¤³¤È¤¬¤¢¤ëÊý¸þ¤±¤Ç¤¹¤¬¡¢GIN¤Ç¤Ïbind().toInstance()¤¬¤Ê¤¤¤Î¤Ç¡¢toInstance¤òÍøÍѤ¹¤ë¤è¤¦¤Ê¥±¡¼¥¹¤â@Provided¤Çµ­ºÜ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£

eventBus¥á¥½¥Ã¥É

eventBus¥á¥½¥Ã¥É¤Ï¡¢Activity + Place¤ÇÍøÍѤ¹¤ëEventBus¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ÎÀßÄê¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
@Singleton¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤òµ­½Ò¤¹¤ë¤³¤È¤Ç¡¢EventBus¤òSingleton¤È¤·¤ÆÀßÄê¤Ç¤­¤Þ¤¹¡£
¤Þ¤¿@Provides¥á¥½¥Ã¥É¤òModuleÆâ¤Çµ­½Ò¤¹¤ë¤³¤È¤Ë¤è¤ê¾¤Î¥¯¥é¥¹¤ÇDI¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£

contentsPanel¥á¥½¥Ã¥É

contentsPanel¥á¥½¥Ã¥É¤Ç¤ÏView¤òÁÞÆþ¤¹¤ë¤¿¤á¤ÎSimplePanel¤ÎÀßÄê¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
@Named¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤ò»ØÄꤹ¤ë¤³¤È¤Ë¤è¤ê"̾Á°ÉÕ"¤ò¹Ô¤¤¡¢¸åµ­¤ÎactivityManager¤Î¤è¤¦¤Ë
DI¤ò¹Ô¤¦ºÝ¡¢Æ±ÍͤΥ¢¥Î¥Æ¡¼¥·¥ç¥ó¤òÍøÍѤ¹¤ë¤³¤È¤Ç¡¢
¤³¤Î̾Á°¤ÎÉÕ¤¤¤¿SimplePanel(¤Ä¤Þ¤ê¤³¤³¤ÇºîÀ®¤µ¤ì¤Æ¤¤¤ë¥¤¥ó¥¹¥¿¥ó¥¹¡Ë¤òÍøÍѽÐÍè¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£

placeController¥á¥½¥Ã¥É¡¢activityMapper¥á¥½¥Ã¥É

eventBus¤ÈƱ¤¸¤Ç¤¹¡£placeController¤Ç¤ÏEventBus¤òModuleÆâ¤Ç¥á¥½¥Ã¥É¥¤¥ó¥¸¥§¥¯¥·¥ç¥ó¤¹¤ë¤³¤È¤Ë¤è¤ê¡¢
eventBus¥á¥½¥Ã¥É¤ÇºîÀ®¤·¤¿EventBus¤òÍøÍѤ·¤Æ¤¤¤Þ¤¹¡£

activityManager¥á¥½¥Ã¥É

activityManager¥á¥½¥Ã¥É¤Ç¤Ï¡¢°ú¿ô¤Ë@Named("contents")¤òÀßÄꤹ¤ë¤³¤È¤Ç¡¢contentsPanel¥á¥½¥Ã¥É¤ÇºîÀ®¤·¤¿SimplePanel¤òDI¤µ¤»¡¢acitivityManger¤ËÀßÄꤷ¤Æ¤¤¤Þ¤¹¡£
¤³¤ì¤Ë¤è¤êPlace¤¬Êѹ¹¤µ¤ìActivity¤¬¸Æ¤Ó½Ð¤µ¤ì¤ëºÝ¤Ë¤³¤ÎcontentsPanel¤¬ÍøÍѤµ¤ì¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£

placeHistoryHandler¥á¥½¥Ã¥É

placeHistoryHandler¤Ç¤Ï¡¢¤Ä¤¤¤Ç¤ËAppPlaceHistoryMapper¤ÎÀßÄê¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
AppPlaceHistoryMapper¤Ë´Ø¤·¤Æ¤Ï¸å¤Û¤ÉºÙ¤«¤¯½ñ¤­¤Þ¤¹¤¬¡¢Place¤ÎFactory¤È¤·¤ÆInjector¤ò»ØÄꤷ¤Æ¤¤¤Þ¤¹¡£
¤Þ¤¿¥Ç¥Õ¥©¥ë¥È¡Ê½é´ü²èÌÌɽ¼¨¤Ê¤É¡ËÍѤÎTopPlace¤Ê¤É¤ÎÀßÄê¤â¤³¤³¤Ç¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£

MvpModule¤ÎÆÉ¤ß¹þ¤ß MyModule

¼¡¤Ë¾åµ­¤ÇºîÀ®¤·¤¿¡¢MvpModule¤òÆÉ¤ß¹þ¤ß¤¹¤ë¿Æ¤ÎModule¤òºîÀ®¤·¤Þ¤¹¡£

package stk.client.inject;

 ~ import 

public class MyModule extends AbstractGinModule {

	@Override
	protected void configure() {

		install(new MvpModule());

		//bind displays
		bind(TopDisplay.class).to(TopView.class).in(Singleton.class);

	}

	@Provides
	@Singleton
	public LoginInfo loginInfo(){
		return new LoginInfo();
	}

}
<||

><p>configure¥á¥½¥Ã¥É¤Ë¤Æinstall¥á¥½¥Ã¥É¤òÍøÍѤ·¡¢MvpModule¤òÆÉ¤ß¹þ¤ó¤Ç¤¤¤Þ¤¹¡£<br>
¤Þ¤¿MyModule¤Ç¤Ï¥í¥°¥¤¥ó¾ðÊó¤òÊÝ»ý¤¹¤ë¤¿¤á¤ÎLoginInfo¤ÎÀßÄê¤â¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£<br>
¥í¥°¥¤¥ó¾ðÊó¤ò@Singleton¤ÇÀë¸À¤·¤Æ¤¤¤ë¤ÈÉԻ׵Ĥ˴¶¤¸¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¤¬¡¢<br>
GWT¤Ç¤¤¤¦Singleton¤Ï³Æ¥¯¥é¥¤¥¢¥ó¥È¤´¤È¤ÎSingleton¤Î°ÙÌäÂꤢ¤ê¤Þ¤»¤ó¡£</p><

** Injector¤ÈModule¤ÎɳÉÕ¤±
><p>Injector¤ÏGIN¤ÇÀßÄꤷ¤¿³Æ¥¤¥ó¥¹¥¿¥ó¥¹¤ò¼èÆÀ¤¹¤ë¤¿¤á¤Î¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤Ç¤¹¡£<br>
»ä¤Î´¶³Ð¤Ç¤¹¤¬¡¢Seasar¤Ç¸À¤¦¤È¤³¤í¤ÎS2SingletonContainer¤ß¤¿¤¤¤Ê¤â¤Î¤Ç¤¹¤¬¡¢<br>
Ä̾ï¤ÎDI¥³¥ó¥Æ¥Ê¤È°Û¤Ê¤ê¡¢Injector¤«¤é¥¤¥ó¥¹¥¿¥ó¥¹¤ò¼èÆÀ¤¹¤ë¤¿¤á¤Ë¤Ï<br>
Injector¤Ë¥á¥½¥Ã¥É¤òÄêµÁ¤·¤Æ¤¤¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡£<br>
Gin¤Ç¤Ï¤³¤ÎInjector¤òºîÀ®¤¹¤ë¤Ë¤Ï¡¢GinInjector¤ò·Ñ¾µ¤·¤¿¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤òºîÀ®¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£</p><

>|java|
package stk.client.inject;

 ~ import 

@GinModules(MyModule.class)
public interface MyInjector extends Ginjector {

	LoginInfo getLoginInfo();

	PlaceController getPlaceController();

	ActivityManager getActivityManager();

	EventBus getEventBus();

	GwtAuthServiceAsync getAuthService();

	TopPlace getTopPlace();

	TopPlace.Tokenizer getTopTokenizer();

	PlaceHistoryHandler getHistoryHandler();

	MainView getMainView();

	@Named("contents") SimplePanel getContentsPanel();

	TopDisplay getTopDisplay();
}

@GinModules¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤òÍøÍѤ·¤Æ¡¢¾åµ­¤ÎMyModule¤ÈInjector¤òɳÉÕ¤±¤Æ¤¤¤Þ¤¹¡£
InjectorÆâ¤Ç¤Ï¡¢³ÆÍøÍѤ¹¤ë¥¯¥é¥¹¤ÎGetter¤òµ­½Ò¤·¡¢¤¢¤È¤¢¤ÈÍøÍѽÐÍè¤ë¤è¤¦¤Ë¤·¤Æ¤¤¤Þ¤¹¡£
¤³¤ì¤ÇGIN¦¤ÎÀßÄê¤Ï´°Î»¤Ç¤¹¡£¤³¤ó¤É¤ÏMVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤ò¤è¤ê´Êñ¤Ë¤¹¤ë¤¿¤á¤Ë¡¢Place¥¯¥é¥¹¤Ê¤É¤òºîÀ®¤·¤Þ¤¹¡£

Activity¤ÈPlace¤òɳÉÕ¤±¤¹¤ëActivityPlace¤ÎºîÀ®

Á°²ó½ñ¤¤¤¿MVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Ç¤Ï¡¢AppActivityMapper¤Ë¤Æinstanceof¤òÍøÍѤ¹¤ë¤³¤È¤Ë¤è¤ê¡¢
Place¤ÈActivity¤Î´ØÏ¢ÉÕ¤±¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤·¤¿¡£
º£²ó¤ÏPlace¤ÈActivity¤ò»öÁ°¤Ë¤Ò¤â¤Å¤±¤ë¤³¤È¤Ë¤è¤êinstanceof¤ò¤Û¤È¤ó¤ÉÍøÍѤ»¤º¡¢
AppActivityMapper¤òµ­½Ò¤Ç¤­¤ë¤è¤¦¤Ë¤·¤Þ¤¹¡£
¤½¤Î¤¿¤á¤Ë¤ÏPlace¥¯¥é¥¹¤ò³ÈÄ¥¤·¤¿Ãê¾Ý¥¯¥é¥¹¡¢ActivityPlace¥¯¥é¥¹¤òºîÀ®¤·¤Þ¤¹¡£


package stk.client.framework;

 ~ import

public abstract class ActivityPlace<T extends Activity> extends Place {

	@Inject
	Provider<T> provider;
	protected String token = "";

	public void init(String token){
		this.token = token;
	}

	public String getToken(){
		return this.token;
	}

	public T getActivity(){

		return provider.get();
	}

	abstract public static class Tokenizer<E extends ActivityPlace<?>> implements PlaceTokenizer<E>{

		@Inject
		Provider<E> provider;

		@Override
		public E getPlace(String token) {
			E place = provider.get();
			place.init(token);
			return place;
		}

		@Override
		public String getToken(E place) {
			return place.getToken();
		}

	}
}

¤Þ¤ºActivityPlace¥¯¥é¥¹¤Ç¤Ï¡¢Generics¤òÍøÍѤ·Place¤ÈActivity¤òɳÉÕ¤±¤Æ¤¤¤Þ¤¹¡£
provider¥Õ¥£¡¼¥ë¥É¤Ë@Inject»ØÄꤷ¡¢Provider¥¯¥é¥¹¤ò¥Õ¥£¡¼¥ë¥É¥¤¥ó¥¸¥§¥¯¥·¥ç¥ó¤·¤Æ¤¤¤Þ¤¹¡£
Provider¥¯¥é¥¹¤Ï¥¯¥é¥¹¤òÀ¸À®¤¹¤ë¤¿¤á¤Î¥¯¥é¥¹¤Ç¡¢provider.get()¥á¥½¥Ã¥É¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤ê¡¢
Generics¤Ë¤è¤ê»ØÄꤵ¤ì¤¿¥¯¥é¥¹¤òÀ¸À®¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£
º£²ó¤ÏActivity¤ò·Ñ¾µ¤·¤¿T¡ÊT¤ÏActivityPlace¤ò·Ñ¾µ¤·¤¿¥¯¥é¥¹¤ÇǤ°Õ¤ËÀßÄꤷ¤Þ¤¹¡£¡Ë¥¯¥é¥¹¤òÀ¸À®¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£
getActivity()¥á¥½¥Ã¥É¤Ç¤Ï¤³¤Îprovider¤òÍøÍѤ·¡¢T¤òÀ¸À®¡¦ÊֵѤ¹¤ë¤³¤È¤Ç¡¢Place¤«¤éActivity¤ÎÀ¸À®¤ò²Äǽ¤Ë¤·¤Æ¤¤¤Þ¤¹¡£

ActivityPlaceÆâ¤ÇÀë¸À¤µ¤ì¤¿¡¢Tokenizer¤Ç¤Ï¤³¤ÎActivityPlace¤ÎÀ¸À®¤ò¹Ô¤¤¤Þ¤¹¡£
Á°½Ò¤ÎMyInjectorÆâ¤Ë¤Æ¸Æ¤Ó½Ð¤·¥á¥½¥Ã¥É¡ÊÎ㤨¤ÐgetTopPlaceTokenizer)¤òºîÀ®¤·¡¢
AppPlaceHistoryMapper¤Ë¤ÆMyInjectorÆâ¤ÎTokenizerºîÀ®¥á¥½¥Ã¥É¤ò¸Æ¤Ö¤³¤È¤Ç¡¢
Tokenizer¤¬ºîÀ®¡¢¤µ¤é¤Ë¤ÏTokenizer¤«¤é¤³¤ÎActivityPlace¤¬ºîÀ®¤µ¤ì¤Þ¤¹¡£

Î㤨¤Ð²¼µ­¤Î¤è¤¦¤ÊActivityPlace¤ò·Ñ¾µ¤·¤¿¡¢¥¯¥é¥¹¤òºîÀ®¤·¤Þ¤¹¡£

package stk.client.place;

 ~ import

public class TopPlace extends ActivityPlace<TopActivity> {

	@Override
	public String getToken() {
		return "";
	}

	@Override
	public void init(String token) {
	}

	@Prefix("!top")
	public static class Tokenizer extends ActivityPlace.Tokenizer<TopPlace> implements PlaceTokenizer<TopPlace> {}

}

Place¤«¤éActivity¤ÎºîÀ®¤ò¹Ô¤¦

º£ÅÙ¤ÏPlace¤«¤éActivity¤ÎºîÀ®¤ò¹Ô¤¦ActivityMapper¤ÎºîÀ®¤ò¤·¤Þ¤¹¡£

package stk.client.framework;

~ import

public class AppActivityMapper implements ActivityMapper {

	@Inject
	public AppActivityMapper() {
		super();
	}

	@Override
	public Activity getActivity(Place place) {
		if (!(place instanceof ActivityPlace<?>)) {
			return null;
		}

		ActivityPlace<?> activityPlace = (ActivityPlace<?>)place;

		return activityPlace.getActivity();
	}


}

¤É¤ª¤Ç¤·¤ç¤¦¤«¡¢Á°²ó¤ÎAppActivityMapper¤Ë¤¯¤é¤Ùinstanceof¤Îµ­½Ò¤¬¤Û¤Ü¤Ê¤¯¤Ê¤ê¡¢
Èó¾ï¤Ë¤¹¤Ã¤­¤ê¤·¤¿¤Î¤Ç¤Ï¤Ê¤¤¤Ç¤·¤ç¤¦¤«¡©
Á°²ó¤ÎAppActivityMapper¤Ç¤ÏPlace¤¬Áý¤¨¤ë¤¿¤Ó¤ËAppActivityMapper¤ò½ñ¤­´¹¤¨¤ëɬÍפ¬¤¢¤ê¤Þ¤·¤¿¤¬¡¢
GIN¤òÍøÍѤ·¤¿¤³¤È¤Ë¤è¤ê¡¢¤½¤Î°Í¸¤¬¾Ã¤¨AppActivityMapper¤òÊѹ¹¤¹¤ëɬÍפ¬¤Ê¡¡¤¯¤Ê¤ê¤Þ¤·¤¿¡£

¼¡¤ËHistory Token ¤È Place¤ÎɳÉÕ¤±¤ò¹Ô¤¦¡¢AppPlaceHistoryMapper

Á°²ó¤ÎAppPlaceHistoryMapper¤Ç¤Ï@WithTokenizers¤òÍøÍѤ¹¤ë¤³¤È¤Ë¤è¤ê¡¢History Token¤ÈTokenizer¤ÎɳÉÕ¤±¤ò»ØÄꤷ¤Æ¤¤¤Þ¤·¤¿¡£
º£²ó¤ÏTokenizer¤¬GIN¤Ë¤è¤êºîÀ®¤µ¤ì¤ëɬÍפ¬¤¢¤ë¤¿¤á¡¢WithTokenizers¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤òÍøÍѤǤ­¤Þ¤»¤ó¡£
¤½¤Î¤¿¤á¡¢Á°²óAppPlaceHistoryMapper¤òºîÀ®¤¹¤ë¤¿¤á¤Ë·Ñ¾µ¤·¤¿¡¢PlaceHistoryMapper¤òÍøÍѤ¹¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢
Tokenizer¤ÎFactory¤ò»ØÄê¤Ç¤­¤ë¡¢PlaceHistoryMapperWithFactory¤ò·Ñ¾µ¤·¤Þ¤¹¡£

package stk.client.framework;

 ~ import 

public interface AppPlaceHistoryMapper extends PlaceHistoryMapperWithFactory<MyInjector> {
}

PlaceHistoryMapperWithFacotry¤Îgenerics¤È¤·¤Æ¡¢MyInjector¤ò»ØÄꤷ¤Æ¤¤¤Þ¤¹¡£
¤³¤ì¤Ë¤è¤êGWT 2.1¤ÎMVP¥Õ¥ì¡¼¥ï¡¼¥¯¤¬Factory¤È¤·¤Æ»ØÄꤵ¤ì¤¿MyInjector¤è¤ê¡¢
PlaceTokenizer¤ò·Ñ¾µ¤·¤¿¥¯¥é¥¹¤òÊֵѤ¹¤ë¥á¥½¥Ã¥É¤òõ¤·½Ð¤·¡¢Tokenizer¤òÀ¸À®¤¹¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£
;Ã̤Ǥ¹¤¬¡¢¤³¤Îgenerics¤Ë¤·¤Æ¤¹¤ëFacotry¤ÏÆÃ¤Ë»ØÄꤵ¤ì¤¿¥¯¥é¥¹¤ò·Ñ¾µ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤»¤ó¡£
PlaceHistoryMapperWithFactory¤Ë¤Ï¤³¤ÎFactory¤ÎGetter¤â¤Ê¤¤¤¿¤á¡¢¤â¤Î¤¹¤´¤¯ÉԻ׵Ĥʴ¶¤¸¤¬¤·¤Þ¤¹¡£¡£¡£
ºÙ¤«¤Ê»ÅÁȤߤϤ³¤³¤Ç¤Ï½ñ¤­¤Þ¤»¤ó¤¬¡¢¤³¤Î¤Ø¤ó¤¬GWT¤ÎÎ¥¤ì¶È¤Ê¤ó¤Ç¤·¤ç¤¦¤Í¡£

¤¢¤È¤ÏŬÅö¤ËActivity¤ÈPlace¤òºîÀ®

¤¢¤È¤Ï¼ÂºÝ¤ËÍøÍѤ¹¤ë¡¢Activity¤ÈPlace¤òºîÀ®¤·¤Þ¤¹¡£

package stk.client.presenter;

~ import

public class TopActivity extends AbstractActivity {

	private final MyInjector injector;

	@Inject
	public TopActivity(MyInjector injector){
		this.injector = injector;
	}

	@Override
	public void start(AcceptsOneWidget panel, EventBus eventBus) {
		TopDisplay topDisplay = injector.getTopDisplay();
		panel.setWidget(topDisplay);
	}

}
package stk.client.place;

 ~ import

public class TopPlace extends ActivityPlace<TopActivity> {

	@Override
	public String getToken() {
		return "";
	}

	@Override
	public void init(String token) {
	}

	@Prefix("!top")
	public static class Tokenizer extends ActivityPlace.Tokenizer<TopPlace> implements PlaceTokenizer<TopPlace> {}

}

¤ÇºÇ¸å¤Ë¸Æ¤Ó½Ð¤·

¤µ¤¤¤´¤Ë¤³¤ì¤é¤Î¥¯¥é¥¹¤Î¸Æ¤Ó½Ð¤·¤ò¹Ô¤¤¤Þ¤¹¡£
¤Þ¤ºgwt.xml¤Ë¤ÆGIN¤Î¸Æ¤Ó½Ð¤·¤ò¹Ô¤¤¤Þ¤¹¡£

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.0.3//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.0.3/distro-source/core/src/gwt-module.dtd">
<module>
	<inherits name="com.google.gwt.user.User" />
	<inherits name='com.google.gwt.user.theme.standard.Standard' />
	<inherits name='org.slim3.gwt.emul.S3Emulation' />
	<inherits name="com.google.gwt.activity.Activity"/>
	<inherits name="com.google.gwt.inject.Inject"/>
	<inherits name="com.google.gwt.logging.Logging" />
	<inherits name="com.google.common.collect.Collect"/>
	<set-property name="gwt.logging.popupHandler" value="DISABLED"/>
	<script src="/js/jquery-1.4.2.min.js"/>
	<script src="/js/jquery-ui-1.8.1.custom.min.js"/>
	<source path="client">
			<exclude name="**/*Test.java"/>
	</source>
	<source path="shared">
			<exclude name="**/*Test.java"/>
	</source>
	<entry-point class="stk.client.Index"></entry-point>
</module>

¤Á¤Ê¤ß¤Ëcom.google.gwt.inject.Inject¤¬GIN¤ÎÀßÄêÉôʬ¤Ç¤¹¡£

¼¡¤ËGWT¤Î¥â¥¸¥å¡¼¥ë¥¯¥é¥¹¤òµ­½Ò¤·¤Þ¤¹¡£

package stk.client;

~ import

public class Index implements EntryPoint {

	Logger logger = Logger.getLogger(Index.class.getName());

	@Override
	public void onModuleLoad() {

		final MyInjector injector = GWT.create(MyInjector.class);

		injector.getActivityManager();
		Resources.INSTANCE.site().ensureInjected();

		injector.getAuthService().loginAuth(GWT.getHostPageBaseURL(),
				new AsyncCallback<LoginInfo>() {

					@Override
					public void onSuccess(LoginInfo result) {
						LoginInfo loginInfo = injector.getLoginInfo();
						loginInfo.email = result.email;
						loginInfo.loggedIn = result.loggedIn;
						loginInfo.logoutUrl = result.logoutUrl;
						loginInfo.nickName = result.nickName;
						loginInfo.loginUrl = result.loginUrl;

						RootPanel.get("msg").setVisible(false);
						RootPanel.get("contents").add(injector.getContentsPanel());

						injector.getHistoryHandler().handleCurrentHistory();
					}

					@Override
					public void onFailure(Throwable caught) {

					}
				});

	}
}

º£²ó¤ÎÎã¤Ç¤Ï¥í¥°¥¤¥ó½èÍý¤È¤«¤âÆþ¤Ã¤Æ¤¤¤Þ¤¹¤¬¡¢ÃíÌܤ·¤Æ¤¤¤¿¤À¤­¤¿¤¤¤Î¤Ï¡¢
ºÇ½é¤ËGWT.create¤ÇMyInjector¤òÀ¸À®¤·¤Æ¤¤¤ëÉôʬ¤Ç¤¹¡£
¤³¤ì¤Ë¤è¤êMyInjector¤¬½é´ü²½¤µ¤ìMyModule¤Ê¤É¤¬¸Æ¤Ó½Ð¤µ¤ì¡¢¤¹¤Ù¤Æ¤ÎDIÀßÄ꤬¹Ô¤ï¤ì¤Þ¤¹¡£
¤Á¤Ê¤ß¤Ëinjector.getActivityManager();¤ò¼¡¤Ë¸Æ¤Ó½Ð¤·¤Æ¤¤¤ë¤Î¤Ï¡¢@Singleton¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤Ç¤Ï¡¢
½é´üºîÀ®¤Ç¤Ï¤Ê¤¯¸Æ¤Ó½Ð¤·»þ¤Ë½é¤á¤ÆSingleton¥¤¥ó¥¹¥¿¥ó¥¹¤¬ºîÀ®¤µ¤ì¤ë¤¿¤á¡¢°ìÅٸƤӽФ·¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
¿ʬ¤â¤Ã¤È¥¹¥Þ¡¼¥È¤Ë¤Ç¤­¤ëµ¤¤¬¤·¤Þ¤¹¤¬¡£¡£¡£
¤Þ¤¿RootPanel.get("contents").add(injector.getContentsPanel());¤ÇRootPanel¤Ë¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤ÇÍøÍѤ¹¤ë
ContentsPanel(@Named("contents")¤ò»ØÄꤷ¤¿SimplePanel)¤òÀßÄꤷ¤Æ¤¤¤Þ¤¹¡£

¤Þ¤È¤á

Èó¾ï¤Ë¥¯¥é¥¹¿ô¤¬Â¿¤¤¤¿¤á¡¢¤á¤ó¤É¤¯¤µ¤¯´¶¤¸¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¤¬¡¢°ìÅÙºî¤Ã¤Æ¤·¤Þ¤¨¤Ð¡¢
Á°²ó¤Îµ­»ö¤ËÈæ¤Ù¤Û¤È¤ó¤ÉÊѹ¹¤ÏÍפé¤Ê¤¯¤Ê¤ê¤Þ¤¹¡£
²èÌ̤òÁý¤ä¤¹¾ì¹ç¤ÏPlace¤ÈActivity¤òºîÀ®¤·injector¤ËTokenizer¥á¥½¥Ã¥É¤òÁý¤ä¤¹¤À¤±¤Ç¤è¤¯¤Ê¤ê¤Þ¤¹¡£

¼ÂºÝ¤ËMVP + GIN¤ò»È¤Ã¤Æ¤¤¤ë¥µ¥¤¥È¤È¤·¤Æ¡¢
»ä¤¬¥³¥ß¥Ã¥¿¡¼¤ò¤ä¤é¤µ¤»¤Æ¤¤¤¿¤À¤¤¤Æ¤¤¤ë¡¢id:coolstyle ¤µ¤ó(@yusuke_kokubo)¤Îskillmaps¤¬¤¢¤ê¤Þ¤¹¡£
¥½¡¼¥¹¥³¡¼¥É¤âgithub¤Ç¸ø³«¤µ¤ì¤Æ¤¤¤Þ¤¹¤Î¤Ç*4¡¢À§Èó¤´Í÷¤Ë¤Ê¤Ã¤Æ¤ß¤Æ¤¯¤À¤µ¤¤¡£

¼¡²óͽ¹ð

¼¡²ó¤Ï¡¢MVP¤ÎÏäǤʤ¯¤Æ¡¢GWT 2.1¤ÇÄɲ䵤줿CellView¤¢¤¿¤ê¤ÎÏäò½ñ¤³¤¦¤«¤È»×¤¤¤Þ¤¹¡£¤¿¤Ö¤ó¤¤¤Ä¤«
¤¢¤È¤Ï¡¢MVP + GWT¤Ç¤ÎGWT.runAsync¤Î¤¦¤Þ¤¤¤ä¤ê¤«¤¿¤ò½ñ¤³¤¦¤«¤È ¤¿¤Ö¤ó¤¤¤Ä¤«

ÄÉ¿­

ʸ¾Ï¤¬¥Ø¥¿¥¯¥½¤Ç¿½¤·Ìõ¤´¤¶¤¤¤Þ¤»¤ó¡£¡£¡£

*1¡§GIN http://code.google.com/p/google-gin/

*2¡§¥³¥ó¥Æ¥Ê¤Ã¤Æ¸À¤Ã¤Æ¤¤¤¤¤Î¤«Èù̯¤Ç¤¹¤¬

*3¡§¤Ã¤È¤¤¤Ã¤Æ¤âspin upŪ¤Ë¤Á¤ç¤¤¤È¿É¤¤¤Ç¤¹¤¬¡£¡£¡£

*4¡§https://github.com/YusukeKokubo/SkillMaps

2010-10-13

GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã + EventBus + History ¤½¤Î2(History¤âAppController¤â¤µ¤è¤¦¤Ê¤é¡Ë

| 17:02 | GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã + EventBus + History ¤½¤Î2(History¤âAppController¤â¤µ¤è¤¦¤Ê¤é¡Ë¤ò´Þ¤à¥Ö¥Ã¥¯¥Þ¡¼¥¯ GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã + EventBus + History ¤½¤Î2(History¤âAppController¤â¤µ¤è¤¦¤Ê¤é¡Ë¤Î¥Ö¥Ã¥¯¥Þ¡¼¥¯¥³¥á¥ó¥È

¤Á¤ç¤¦¤ÉºòÆü´èÄ¥¤Ã¤ÆHisotry¤ÈEventBus¡¢AppController¤ÎÏäò½ñ¤¤¤¿¤Î¤Ë

º£Æüµ¤¤¬¤Ä¤¤¤¿¤éGWT2.1.0-RC1¤¬Íè¤Æ¤¤¤Æ¡¢AppController¤âHistory¤âEventBus¤â¤¤¤é¤Ê¤¯¤Ê¤Ã¤¿¤è

޵ŽÜŽÀ ¡À(¡°o¡°)¡¿ŽµŽÜŽÀ ¡À(¡°o¡°)¡¿ŽµŽÜŽÀ ¡À(¡°o¡°)¡¿ŽµŽÜŽÀ ¡À(¡°o¡°)¡¿ŽµŽÜŽÀ ¡À(¡°o¡°)¡¿

¤Ï¤¤¡¢°ÕÌ£¥Ê¥Ã¥·¥ó¥°¤Ç¤¹¡£

¤Ç¤â¤¤¤é¤Ê¤¯¤Ê¤Ã¤¿¤Î¤ÏɬÍפʤ¯¤Ê¤Ã¤¿¤Î¤Ç¤Ï¤Ê¤¯¡¢ºî¤é¤Ê¤¯¤Æ¤è¤¯¤Ê¤Ã¤¿¤À¤±¤Ê¤Î¤Ç¡¢

ºòÆü½Ð¤ÆÂ®¹¶¤ÇGWT2.1.0-RC1ÈÇMVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯Âбþ¤ò¹Ô¤Ã¤Æ¤ß¤Þ¤·¤¿¡£

¤À¤Ã¤ÆÃˤλҤÀ¤â¤ó

¤Æ¤³¤È¤ÇºòÆü¤ÈƱ¤¸´¶¤¸¤ÇÁ°Ä󤫤é

»ä¤Ï±Ñ¸ìÎϤâÆüËܸìÎϤâ¤Ê¤¤¤Î¤Ç¡¢

¤ï¤«¤ê¤Ë¤¯¤¤¡¢²ò¼á¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¸Ä½ê¤Ï¿ʬ¤Ë¤¢¤ë¤«¤È»×¤¤¤Þ¤¹¡£

¤½¤¦¤¤¤Ã¤¿¾ì¹ç¤Ï¤ä¤µ¤·¤¯¸«¼é¤Ã¤Æ¤¯¤À¤µ¤¤¡£

º£²óMVP Framework¤òºî¤ë¾å¤Ç»²¹Í¤Ë¤·¤¿¤Î¤ÏGWT¤Î¸ø¼°¥µ¥¤¥È¤Ç¤¹¡£

Google¤µ¤óº£²ó¤ÏÈó¾ï¤Ëʬ¤«¤ê¤ä¤¹¤«¤Ã¤¿¤Ç¤¹¡£

¥µ¥ó¥×¥ë¤Î¥½¡¼¥¹¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¸Ä½ê¤¬¾¯¡¹¤¢¤ê¤Þ¤·¤¿¤¬¡£¡£¡£

¤ÇÃæ¿È¤Ï¤Û¤Ü¼Ì·Ð¤·¤Þ¤·¤¿¡Ê¤á¤ó¤É¤¤¤È¤³¤í¤Ï¥³¥Ô¥Ú¤·¤Þ¤·¤¿¡Ë¡£

¥³¡¼¥É¤Ï¤³¤Á¤é¤Ç¤¹¡£

Á´ÂÎÁü¤Ê¤É¤Ê¤É

ºòÆü¤Îµ­»ö¤ò¸«¤Æ²¼¤µ¤¤¡£

¤â¤¦°ì²ó½ñ¤¯¤È¢­¤Î¤è¤¦¤Ê²èÌÌÁ«°Ü¤Ç¤¹¡£

https://cacoo.com/diagrams/UmEpII6zMLeG4bRm

¤è¤¯¤¢¤ë

¡Ö°ìÍ÷¡×¢ª¡Ö¿·ºîÀ®ÆþÎϡעª¡Ö°ìÍ÷¡×

¡Ö°ìÍ÷¡×¢ª¡Ö½¤ÀµÆþÎϡעª¡Ö°ìÍ÷¡×

¤Î¤è¤¦¤ÊÁ«°Ü¤Î¥â¥¸¥å¡¼¥ë¤òºîÀ®¤·¤Æ¤¤¤Þ¤¹¡£

º£²ó¤Ï¤³¤ì¤òGWT¤ÇMVP²½¤¹¤ë¤È¤É¤¦¤Ê¤ë¤«¤ò½ñ¤­¤Þ¤¹¡£

Ãí°ÕÅÀ

GWT¤Î¥µ¥¤¥È¤À¤È½ñ¤¤¤Æ¤¤¤Þ¤»¤ó¤¬¡¢

Activity¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤òÍøÍѤ¹¤ë¾ì¹ç¤Ï¡¢

gwt.xml¤Ë

<inherits name="com.google.gwt.activity.Activity" />

¤òµ­½Ò¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£



Åоì¿Íʪ

Activity

Activity¤ÏMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤Ç¸À¤¦¤È¤³¤í¤ÎPresenter¤ÎÌò³ä¤ò»ý¤Á¤Þ¤¹¡£

¤Ä¤Þ¤êÀÕ̳¤Ï

¤Ç¤¹¡£

GWT MVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Ç¤Ï

Activity¡ÊMVP¤ÎPresenter)¤È¤Ê¤ë¥¯¥é¥¹¤ÏAbstractActivity¤ò·Ñ¾µ¤·¤Þ¤¹¡£

¤½¤·¤Æstart()¥á¥½¥Ã¥É¤Ç¡¢Ã´Åö¤¹¤ëView¤ËÂФ·¤Æ¡¢¥Ç¡¼¥¿¥Ð¥¤¥ó¥É¤ò¹Ô¤¤¤Þ¤¹¡£

¥³¥ó¥¹¥È¥é¥¯¥¿¤Ç½Ð¤Æ¤¯¤ëPlace¤Ï¸å¤Ç²òÀ⤷¤Þ¤¹¡£

ClientFactory¤Ïñ½ã¤ÊFactory¤Ç¤¹¡£

³ÆgetHoge¤Ë¤Æ¥¤¥ó¥¹¥¿¥ó¥¹¤òºîÀ®¤·¡¢ÊֵѤ·¤Þ¤¹¡£


ListPresenter(Activity)

package com.google.code.stk.client.ui.presenter;

import java.util.List;

import com.google.appengine.api.datastore.Key;
import com.google.code.stk.client.ClientFactory;
import com.google.code.stk.client.service.TwitterServiceAsync;
import com.google.code.stk.client.ui.display.ListDisplay;
import com.google.code.stk.client.ui.place.EditPlace;
import com.google.code.stk.client.ui.place.ListPlace;
import com.google.code.stk.client.ui.place.NewPlace;
import com.google.code.stk.shared.model.AutoTweet;
import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;

public class ListPresenter extends AbstractActivity implements ListDisplay.Presenter{

	private final TwitterServiceAsync service;
	private final ClientFactory clientFactory;
	private final ListPlace place;
	private ListDisplay display;

	public ListPresenter(ListPlace place , ClientFactory clientFactory) {
		super();
		this.place = place;
		this.clientFactory = clientFactory;
		this.service = this.clientFactory.getTwitterService();
	}


	@Override
	public void clickNewButton() {
		clientFactory.getPlaceController().goTo(new NewPlace());
	}

	@Override
	public void clickDeleteAnchor(final Key key) {
		service.delete(key, new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void arg0) {

				clientFactory.getPlaceController().goTo(new ListPlace("delete" , key.getId()));
			}

			@Override
			public void onFailure(Throwable throwable) {

			}
		});
	}

	@Override
	public void clickEditAnchor(Key key) {
		clientFactory.getPlaceController().goTo(new EditPlace(key.getId()));
	}

	@Override
	public void savePinCode(String value) {
		service.registAccessToken(value, new AsyncCallback<Void>() {

			@Override
			public void onFailure(Throwable arg0) {

			}

			@Override
			public void onSuccess(Void arg0) {
				display.getPinCodeInputPanel().setVisible(false);
				display.getSavePinCodeButton().setEnabled(true);
				Window.alert("¥Ô¥ó¥³¡¼¥É¤òÊݸ¤·¤Þ¤·¤¿¡£");
			}
		});
	}

	@Override
	public void start(final AcceptsOneWidget panel, EventBus eventBus) {
		display = clientFactory.getListDisplay();
		display.setPresenter(this);
		panel.setWidget(display);
		service.findAll(new AsyncCallback<List<AutoTweet>>() {

			@Override
			public void onSuccess(List<AutoTweet> arg0) {
				display.drowTable(arg0);
			}

			@Override
			public void onFailure(Throwable arg0) {
				Window.alert(arg0.getMessage());
			}
		});

	}

}


ClientFactory(Factory)


ClientFactory¤ÏDeferred Binding¤òÍøÍѤ·GWT.create¤Ë¤ÆºîÀ®¤·¤Þ¤¹¡£

¤³¤ì¤Ë¤è¤ê¤´¤Ã¤½¤êView¤Ê¤É¤ò¥â¥Ã¥¯¤ËÊѹ¹¤¹¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡£

FactoryÃæ¤ÎEventBus¤ÏºòÆüÀâÌÀ¤·¤¿EventBus¤È¤Û¤ÜƱ¤¸¤Ã¤Ý¤¤¤Ç¤¹¡£

¤Ä¤Þ¤êÆÈ¼«Event¤ò½èÍý¤·¤Þ¤¹¡£

PlaceController¤Ï¸å¤Û¤ÉÀâÌÀ¤·¤Þ¤¹¡£

package com.google.code.stk.client;

import com.google.code.stk.client.service.TwitterService;
import com.google.code.stk.client.service.TwitterServiceAsync;
import com.google.code.stk.client.ui.display.AutoTweetDisplay;
import com.google.code.stk.client.ui.display.AutoTweetView;
import com.google.code.stk.client.ui.display.ListDisplay;
import com.google.code.stk.client.ui.display.ListView;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.place.shared.PlaceController;

public class ClientFactoryImpl implements ClientFactory {

	private ListDisplay listDisplay = null;

	private PlaceController placeController = null;

	private SimpleEventBus eventBus;

	private TwitterServiceAsync twitterService;

	@Override
	public AutoTweetDisplay getAutoTweetDisplay() {

		return new AutoTweetView();
	}

	@Override
	public EventBus getEventBus() {
		if(eventBus == null){
			eventBus = new SimpleEventBus();
		}
		return eventBus;
	}

	@Override
	public ListDisplay getListDisplay() {
		if(listDisplay == null){
			listDisplay = new ListView();
		}
		return listDisplay;
	}

	@Override
	public PlaceController getPlaceController() {
		if(placeController == null){
			placeController = new PlaceController(getEventBus());
		}
		return placeController;
	}

	@Override
	public TwitterServiceAsync getTwitterService() {
		if(twitterService == null){
			twitterService = GWT.create(TwitterService.class);
		}
		return twitterService;
	}

}
Display(IsWidget)

MVP¤ÎDisplay¤Ïñ½ã¤ÊView¥¯¥é¥¹¤Ê¤Î¤ÇWidget¤äUiBinder¤¢¤¿¤ê¤Çºî¤ì¤ÐÌäÂꤢ¤ê¤Þ¤»¤ó¤¬¡¢

Activity¤ÇÍøÍѤ¹¤ë¾ì¹ç¤ÏIsWidget¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ò·Ñ¾µ¤·¤Æ¤ª¤¯¤È¡¢¤è¤¤¤Ç¤¹¡£


Display¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ÎÃæ¤ËPresenter¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ò»ý¤Ã¤Æ¤¤¤Þ¤¹¡£

¤³¤ì¤Ï¥Ó¥¸¥Í¥¹¥í¥¸¥Ã¥¯¤òPresenter¤Ë°Ñ¾ù¤µ¤»¤ë¤¿¤á¤Ë¡¢

Display¤Ë¤È¤Ã¤Æ½èÍý¤·¤Æ¤Û¤·¤¤¤³¤È¤òPresenter¤ËÀÚ¤ê½Ð¤·¡¢

¤½¤ÎPresenter¤ò·Ñ¾µ¤·¤Æ¤¤¤ë¥¯¥é¥¹¤òsetPresenter¤Ë¤ÆÅÐÏ¿¤µ¤»¡¢

¤¹¤Ù¤Æ¤Î¥Ó¥¸¥Í¥¹¥í¥¸¥Ã¥¯¤òPresenter¤Ë¤â¤¿¤»¤Þ¤¹¡£

¤³¤ì¤Ë¤è¤ê¡¢¥Ó¥¸¥Í¥¹¥í¥¸¥Ã¥¯¤È¡¢²èÌ̤¬ÀÚ¤êÎ¥¤µ¤ì¡¢

¥Ç¥¹¥¯¥È¥Ã¥×¥¢¥×¥ê¤Ç¤¢¤ê¤¬¤Á¤Ê¡¢BigView¤òËɤ®¤Þ¤¹¡£

¤Þ¤¿¤½¤ì¤¾¤ì¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤È¤·¤Æ¡¢Àë¸À¤µ¤»¡¢

¤½¤ì¤¾¤ì¤Î¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ò·Ñ¾µ¤µ¤»¤ë¤³¤È¤Ë¤è¤Ã¤Æ¡¢

Presenter¤ÈDisplay¤Î°Í¸ÅÙ¤¬²¼¤¬¤ê¥Æ¥¹¥È¤Î¤·¤ä¤¹¤µ¤¬¤Þ¤·¤Þ¤¹¡£

º£²ó¤ÎListView¤Ë¤È¤Ã¤Æ¤ÎPresenter¤ÏListPresetner¤Ç¤¹¡£

¤Ê¤Î¤ÇListPresenter¤ÏListDislay.Presenter¤ò·Ñ¾µ¤·¡¢

start¥á¥½¥Ã¥ÉÆâ¤Ç¡¢display.setPresenter(this)¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£

¤½¤·¤ÆListViewÆâ¤Î³Æ@UiHander¤Î¤Ä¤¤¤¿¥á¥½¥Ã¥É¤Ç¥Ó¥¸¥Í¥¹¥í¥¸¥Ã¥¯¡Ê¥Ç¡¼¥¿ÅÐÏ¿¤Ê¤É¡Ë¤ò

Presenter¤Ë°Ñ¾ù¤·¤Æ¤¤¤Þ¤¹¡£

¤Á¤Ê¤ß¤ËMVP¤Î¾ì¹ç¤Ï²èÌÌÁ«°Ü¤âPresenter¦¤Î»Å»ö¤Ê¤Î¤ÇPresenter¤ËǤ¤»¤Æ¤¤¤Þ¤¹¡£

View¤¬¹Ô¤¦¤Î¤Ï¼«¿È¤Î¤â¤ÄWidget¤Î´ÉÍý¤Î¤ß¤Ç¤¹¡£



ListDisplay

package com.google.code.stk.client.ui.display;

import java.util.List;

import com.google.appengine.api.datastore.Key;
import com.google.code.stk.shared.model.AutoTweet;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.IsWidget;

public interface ListDisplay extends IsWidget{

	void drowTable(List<AutoTweet> tweetList);

	public interface Presenter{

		void clickNewButton();

		void clickDeleteAnchor(Key key);

		void clickEditAnchor(Key key);

		void savePinCode(String value);
	}

	public void setPresenter(Presenter presenter);

	FlowPanel getPinCodeInputPanel();

	Button getSavePinCodeButton();

}

ListView

package com.google.code.stk.client.ui.display;

import java.util.List;

import com.google.code.stk.shared.model.AutoTweet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class ListView extends Composite implements ListDisplay {

	@UiField
	Button newButton;

	@UiField
	InlineLabel sizeLabel;

	@UiField
	FlexTable table;

	@UiField
	Anchor pinCodeLink;

	@UiField
	FlowPanel pinCodeInputPanel;

	@UiField
	TextBox pinCode;

	@UiField
	Button savePinCode;

	private static ListViewUiBinder uiBinder = GWT
			.create(ListViewUiBinder.class);

	private Presenter presenter;

	interface ListViewUiBinder extends UiBinder<Widget, ListView>{
	}

	@Override
	public void drowTable(List<AutoTweet> tweetList) {
		table.removeAllRows();
		if (tweetList == null || tweetList.isEmpty()) {
			table.setText(0, 0, "tweet¤Ê¤·");
			return;
		}

		table.setText(0, 0, "ID");
		table.setText(0, 1, "ÂоÝ");
		table.setText(0, 2, "ÆâÍÆ");
		table.setText(0, 3, "»þ´Ö");
		table.setText(0, 4, "´Ö³Ö");
		table.setText(0, 5, "¥Ö¥ì");
		table.setText(0, 6, "´ü´Ö");
		table.setText(0, 7, "ºÇ½ªTweetÆü");
		table.setText(0, 8, "½¤Àµ");
		table.setText(0, 9, "ºï½ü");

		int row = 1;
		for (final AutoTweet autoTweet : tweetList) {
			table.getColumnFormatter().setWidth(1, "140em");
			table.getColumnFormatter().setWidth(3, "6em");
			table.getColumnFormatter().setWidth(4, "8em");
			table.setCellPadding(10);
			table.setCellSpacing(10);
			table.setText(row, 0, String.valueOf(autoTweet.getKey().getId()));
			table.setText(row, 1, autoTweet.getScreenName());
			table.setText(row, 2, autoTweet.getTweet());
			table.setText(row, 3, autoTweet.getTweetHour() + "»þ");
			table.setText(row, 4, autoTweet.getCycle().name());
			table.setText(row, 5, autoTweet.getBure().name());
			table.setText(row, 6, autoTweet.getStartMMdd() + " ¡Á " + autoTweet.getEndMMdd());
			table.setText(row, 7, autoTweet.getLastTweetAt());
			Anchor syusei = new Anchor("½¤Àµ");
			syusei.addClickHandler(new ClickHandler() {

				@Override
				public void onClick(ClickEvent arg0) {
					presenter.clickEditAnchor(autoTweet.getKey());
				}
			});

			table.setWidget(row, 8, syusei);
			Anchor sakujo = new Anchor("ºï½ü");

			sakujo.addClickHandler(new ClickHandler() {

				@Override
				public void onClick(ClickEvent arg0) {
					presenter.clickDeleteAnchor(autoTweet.getKey());
				}
			});

			table.setWidget(row, 9, sakujo);
			row++;
		}
	}

	@Override
	public Widget asWidget() {
		return this;
	}

	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
	}

	@Override
	public FlowPanel getPinCodeInputPanel(){
		return pinCodeInputPanel;
	}

	@UiHandler("newButton")
	void onClickNewButton(ClickEvent e){
		presenter.clickNewButton();
	}

	@UiHandler("pinCodeLink")
	public void onClickPinCodeLink(ClickEvent e){
		pinCodeInputPanel.setVisible(true);
	}

	@UiHandler("savePinCode")
	public void onClickSavePinCode(ClickEvent e){
		savePinCode.setEnabled(false);
		presenter.savePinCode(pinCode.getValue());
	}

	public ListView() {
		initWidget(uiBinder.createAndBindUi(this));
	}

	@Override
	public Button getSavePinCodeButton() {
		return savePinCode;
	}
}
Place

Place¤Ï²èÌ̤ä¾õÂÖ¤òɽ¤·¤Þ¤¹¡£

ºòÆüAppController¤ÈEventBus¡¢History¤Ë¤Æ¥Ò¥¹¥È¥ê¡¼Ãæ¿´¤Î²èÌÌÁ«°Ü¤òÀâÌÀ¤·¤Þ¤·¤¿¡£

AppController¤ÈEventBus¡¢History¤Î¤ä¤ë¤³¤È¤ò¤è¤ê¡¢¤ï¤«¤ê¤ä¤¹¤¯¡¢¤½¤·¤ÆÀÕ̳¤ò²èÌÌÁ«°Ü¡¢¾õÂÖÊÝ»ý¤Ë

ÆÃ²½¤µ¤»¤¿¤Î¤¬Place¤Ç¤¹¡£¡Ê¥¿¥Ö¥ó¡Ë

GWT¤Ç¤ÎPlace¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Ï²èÌ̤ä¾õÂÖ¤òɽ¤¹Place¥¯¥é¥¹¤È¡¢

¤½¤ì¤é¤òÍøÍѤ·¤ÆHistory¥¤¥Ù¥ó¥È¤òȯ²Ð¤¹¤ëPlaceController¡¢

Place¤ÈHistory¤ò¥Þ¥Ã¥Ô¥ó¥°¤µ¤»¤ëPlaceHistoryMapper¡¢

¤½¤·¤ÆPlace¤ÈActivity¤ò¤Ò¤â¤Å¤±¤ë¡¢ActivityMapper¤òÍøÍѤ·¤Æ¼Â¸½¤·¤Þ¤¹¡£

¤Þ¤º²èÌ̤ä¾õÂÖ¤òɽ¤¹¡¢Place¥¯¥é¥¹¤Î»Ò¥¯¥é¥¹¤«¤é

ListPlace

ListPlace¤Ï°ìÍ÷²èÌ̤òɽ¤¹Place¥¯¥é¥¹¤Î»Ò¥¯¥é¥¹¤Ç¤¹¡£

id¤ästate¤ò»ý¤Ã¤Æ¤¤¤ë¤Î¤Ïºï½ü½èÍý¤«¤é¤â¤É¤Ã¤¿¡¢

½¤Àµ½èÍý¤«¤éÌá¤Ã¤¿¡¢

¿·µ¬ºîÀ®¤«¤éÌá¤Ã¤¿¤Ê¤É¤ò´ÉÍý¤¹¤ë¤¿¤á¤Ç¤¹¡£

ListPlace¤Ë¤ÏListPlace¤Î¾ðÊ󤫤éToken¤òƳ¤­½Ð¤¹¡¢

Tokenizer¤ò»ý¤Ã¤Æ¤¤¤Þ¤¹¡£

Tokenizer¤ÏListPlace¤ÎºîÀ®¤È¡¢ListPlace¤«¤étoken¤ÎºîÀ®¤ò¹Ô¤¤¤Þ¤¹¡£


package com.google.code.stk.client.ui.place;

import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceTokenizer;

public class ListPlace extends Place {

	private final String state;
	private final Long id;

	public ListPlace(){
		this(null , null);
	}

	public ListPlace(String state, Long id) {
		this.state = state;
		this.id = id;
	}

	public ListPlace(String state) {
		this(state, null);
	}

	public Long getId() {
		return id;
	}

	public String getStringId(){
		return id == null?"":id.toString();
	}

	public String getState() {
		return state == null ? "" :state;
	}
	public static class Tokenizer implements PlaceTokenizer<ListPlace>{

		@Override
		public ListPlace getPlace(String token) {

			if(token.contains("delete")){
				return new ListPlace("delete" , Long.parseLong(token.replace("delete/", "")));
			}

			if(token.contains("edit")){
				return new ListPlace("edit" , Long.parseLong(token.replace("edit/", "")));
			}

			if(token.contains("new")){
				return new ListPlace("new");
			}

			return new ListPlace();
		}

		@Override
		public String getToken(ListPlace place) {
			return place.getState() + "/" + place.getStringId();
		}

	}
}
PlaceController

PlaceController¤ÏPlace¤òÍøÍѤ·¤Æ¡¢PlaceHistoryChangeEvent¤òȯ²Ð¤·Á«°Ü¤ò¼Â¸½¤·¤Þ¤¹¡£

¤¿¤È¤¨¤ÐListPresenter¤Î²¼µ­¥á¥½¥Ã¥É¤Ï½¤Àµ¥¢¥ó¥«¡¼²¡²¼»þ¤Ë¡¢

½¤Àµ²èÌ̤ØÁ«°Ü¤µ¤»¤Þ¤¹¡£

ListPresenter

ListPresetner.java
	@Override
	public void clickEditAnchor(Key key) {
		clientFactory.getPlaceController().goTo(new EditPlace(key.getId()));
	}
PlaceHistoryMapper

PlaceHistoryMapper¤Ï³ÆPlace¤ÎTokenizer¤òÍøÍѤ·¤Æ¡¢HistoryToken¤ÈPlace¤Î¥Þ¥Ã¥Ô¥ó¥°¤ò¹Ô¤¤¤Þ¤¹¡£

@WithTokenizers¥¢¥Î¥Æ¡¼¥·¥ç¥ó¤ËTokenizer¤ò»ØÄꤹ¤ë¤À¤±¤Ç¥Þ¥Ã¥Ô¥ó¥°¤·¤Æ¤¯¤ì¤Þ¤¹¡£

¤Á¤Ê¤ß¤Ëȯ¹Ô¤µ¤ì¤ëHistoryToken¤Ï {Placeû½Ì¥¯¥é¥¹Ì¾}:{Tokenizer.getToken()}¤Î·Á¤Ë¤Ê¤ê¤Þ¤¹¡£¡£¡£

Placeû½Ì¥¯¥é¥¹Ì¾¤¬¥À¥µ¤¤¤Î¤Ç¡¢¼£¤¹ÊýË¡¤¬ÃΤꤿ¤¤¸Â¤ê¤Ç¤¹¡£¡£¡£

package com.google.code.stk.client;

import com.google.code.stk.client.ui.place.EditPlace;
import com.google.code.stk.client.ui.place.ListPlace;
import com.google.code.stk.client.ui.place.NewPlace;
import com.google.gwt.place.shared.PlaceHistoryMapper;
import com.google.gwt.place.shared.WithTokenizers;

@WithTokenizers({ListPlace.Tokenizer.class , EditPlace.Tokenizer.class , NewPlace.Tokenizer.class})
public interface AppPlaceHistoryMapper extends PlaceHistoryMapper {

}
ActivityMapper

ActivityMapper¤ÏPlace¤ÈActivity¤ò¤Ò¤â¤Å¤±¤Þ¤¹¡£

¤Ò¤â¤Å¤±¤Ï´èÄ¥¤ê¤Þ¤¹¡£¡£¡£

instanceof¤¬Èù̯¤Ê¤Î¤Ç¤¹¤¬¡¢¡¢¡¢

¤É¤¦¤Ë¤«¤·¤¿¤¤¤Ç¤¹¤Í¡£¡£¡£

package com.google.code.stk.client;

import com.google.code.stk.client.ui.place.EditPlace;
import com.google.code.stk.client.ui.place.ListPlace;
import com.google.code.stk.client.ui.place.NewPlace;
import com.google.code.stk.client.ui.presenter.EditPresenter;
import com.google.code.stk.client.ui.presenter.ListPresenter;
import com.google.code.stk.client.ui.presenter.NewPresenter;
import com.google.gwt.activity.shared.Activity;
import com.google.gwt.activity.shared.ActivityMapper;
import com.google.gwt.place.shared.Place;

public class AppActivityMapper implements ActivityMapper {

	private ClientFactory clientFactory;

	public AppActivityMapper(ClientFactory clientFactory) {
		super();
		this.clientFactory = clientFactory;
	}

	@Override
	public Activity getActivity(Place place) {
		if(place instanceof ListPlace){
			return new ListPresenter((ListPlace)place, clientFactory);
		}

		if(place instanceof NewPlace){
			return new NewPresenter((NewPlace)place ,  clientFactory);
		}

		if(place instanceof EditPlace){
			return new EditPresenter((EditPlace)place, clientFactory);
		}

		return null;
	}

}
Activity¡¢Place¤Þ¤È¤á

°Ê¾å¤¬Activity¡¢Place¤Î´ØÏ¢¥¯¥é¥¹¤È¤½¤Î¼ÂÁõ¤Ç¤¹¡£

²èÌÌÁ«°Ü¤òHistoryÃæ¿´¤Ç¹Ô¤¦¤³¤È¤¬½ÐÍè¡¢¥Ö¥é¥¦¥¶Back¡¢Ajax¤Ë¤Ä¤è¤ê¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤¬ºîÀ®¤Ç¤­¤Þ¤¹¡£

ºòÆü½ñ¤¤¤¿¡¢AppController¤ä¡¢History¤Ï¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤ÎÃæ¤Ë±£¤ì¤¿¾õÂ֤ˤʤäƤ¤¤Þ¤¹¡£

¡Ê¤Þ¤¿¤Ï³ÆMapper¤äPlace¤Ëʬ»¶¤µ¤ì¤Æ¤¤¤ë¡Ë

¾åµ­¤Î³ÆMapper¥¯¥é¥¹¤ÏEntryPoint¤¢¤¿¤ê¤Ç³ÆManeger¥¯¥é¥¹¤ËÅÐÏ¿¤·¤Æ¤ª¤­¤Þ¤¹

		ClientFactory clientFactory = GWT.create(ClientFactory.class);
		EventBus eventBus = clientFactory.getEventBus();
		PlaceController placeController = clientFactory.getPlaceController();

		// Start ActivityManager for the main widget with our ActivityMapper
		ActivityMapper activityMapper = new AppActivityMapper(clientFactory);
		ActivityManager activityManager = new ActivityManager(activityMapper,eventBus);
		activityManager.setDisplay(appWidget);

		// Start PlaceHistoryHandler with our PlaceHistoryMapper
		AppPlaceHistoryMapper historyMapper = GWT
				.create(AppPlaceHistoryMapper.class);
		PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);
		historyHandler.register(placeController, eventBus, defaultPlace);

¤â¤¦¥Á¥ç¥¤ºÙ¤«¤¤Æ°¤­¤Ï¤Þ¤¿º£ÅÙÄɤ¤¤Þ¤¹¡£


¤¢¤È¤¬¤­

º£²ó¤Î¤âÁ°²ó¤Î¤âÁ´¤¯MVP¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤Î¥Ç¥¶¥¤¥ó¥Ñ¥¿¡¼¥ó¤òÀâÌÀ¤·¤Æ¤Ê¤¤¡£¡£¡£

¤Ê¤ó¤ÇHogeDisplay¤¬Presetner»ý¤Ã¤Æ¤ë¤Î¤È¤«ÀâÌÀ¤·¤Ê¤¤¤È¤Ç¤¹¤Í¡£¡£¡£

¤Ç¤âAcitivity¤ÈPlace¤¬½Ð¤Á¤ã¤Ã¤¿¤ó¤À¤â¤ó¡£¡£¡£

¤¦¤ó¡¢Îɤ«¤Ã¤¿¤È»×¤Ã¤Æ¤ë¤è¡£¡£¡£

Data Presenter¤â½ñ¤­¤¿¤¤¤Ç¤¹¤Í¡£

2010-10-10

GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã + EventBus + History ¤½¤Î1(History¤ÈAppController¡Ë

| 23:45 | GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã + EventBus + History ¤½¤Î1(History¤ÈAppController¡Ë¤ò´Þ¤à¥Ö¥Ã¥¯¥Þ¡¼¥¯ GWT¤ÇMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã + EventBus + History ¤½¤Î1(History¤ÈAppController¡Ë¤Î¥Ö¥Ã¥¯¥Þ¡¼¥¯¥³¥á¥ó¥È

µ×¤·¤Ö¤ê¤Ë½ñ¤­¤Þ¤¹¡£

ºÇ¶á¤Ï¤â¤Ã¤Ñ¤éGWT¤ò°·¤Ã¤Æ¤Þ¤¹¡£

Ⱦǯ¤°¤é¤¤¿¨¤Ã¤Æ¤ß¤Æ¡¢¤ä¤Ï¤êGWT¤Ç¤ÏMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤¬Âç»ö¤Ë¤Ê¤Ã¤Æ¤¯¤ë¤Ê¤È»×¤Ã¤¿¤ê¤·¤Þ¤·¤¿¡£

ËͤâºÇ½é¤Ï¤Þ¤Ã¤¿¤¯Ê¬¤«¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¤Î¤Ç¤¹¤¬¡¢id:k2junior¤µ¤ó¤Î¤³¤Á¤é¤ÎÆüµ­¤ò¤ß¤Æ·ë¹½Íý²ò¤¬¤Ç¤­¤Þ¤·¤¿¡£

¤½¤Î¤¢¤ÈGWT¤ÎÂ絬Ìϳ«È¯¤ÎÀâÌÀʸ(?)¤Ë¤ª¤¤¤Æ¤¢¤ë¡¢

¥µ¥ó¥×¥ë¥×¥í¥¸¥§¥¯¥È¤ò¤ß¤Æ²¿¤È¤Ê¤¯Íý²ò¤·¤Æ¡¢

¼«Ê¬¤Ê¤ê¤Ë½ñ¤±¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤­¤¿¤Î¤ÇMVP + EventBus¥Ñ¥¿¡¼¥ó¤Ë¤Ä¤¤¤Æ½ñ¤¤¤Æ¤ß¤Þ¤¹¡£

¤Ê¤ª±Ñ¸ì¤ÏÆÉ¤á¤Ê¤¤¡¢Ê¹¤±¤Ê¤¤¤Ê¤Î¤Ç¡¢

Googlge IO 2009¤ÎGoogle Web Toolkit Architecture: Best Practices for Architecting Your GWT App¤ä

GWT¤ÎÂ絬Ìϳ«È¯¤ÎÀâÌÀʸ(?)¤Ï¤Ê¤ó¤È¤Ê¡Á¤¯¤·¤«¤ï¤«¤Ã¤Æ¤¤¤Þ¤»¤ó¡£

¤Ê¤Î¤Ç²ò¼á¤ä¡¢»È¤¤Êý¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¾ì½ê¤Ï¿¡¹¤¢¤ë¤È»×¤¤¤Þ¤¹¤Î¤Ç¡¢

¤´»ØÅ¦¤ò¤ª´ê¤¤¤¤¤¿¤·¤Þ¤¹¡£

¤Á¤Ê¤ß¤Ë¥µ¥ó¥×¥ë¤È¤·¤Æ¤ÏGAE¾å¤Ë¾è¤Ã¤±¤Æ¤¤¤ëTwitter¤ÎBot¡Ê¤Î¥Ç¡¼¥¿ÆþÎϲèÌ̡ˤò»È¤¤¤Þ¤¹¡£

¥³¡¼¥É¡§http://goo.gl/7xPh (Google Code¤Ç¤¹¡£)

ºî¤Ã¤Æ¤¤¤ë¤â¤Î¤ÎÁ´ÂÎÁü¡Ê²èÌÌÁ«°Ü¡Ë

º£²ó¤Ä¤¯¤Ã¤Æ¤¤¤ë²èÌÌÁ«°Ü¤Ï°Ê²¼¤Î¤è¤¦¤Ê´¶¤¸¤Ç¤¹¡£

https://cacoo.com/diagrams/UmEpII6zMLeG4bRm

¤è¤¯¤¢¤ë

¡Ö°ìÍ÷¡×¢ª¡Ö¿·ºîÀ®ÆþÎϡעª¡Ö°ìÍ÷¡×

¡Ö°ìÍ÷¡×¢ª¡Ö½¤ÀµÆþÎϡעª¡Ö°ìÍ÷¡×

¤Î¤è¤¦¤ÊÁ«°Ü¤Î¥â¥¸¥å¡¼¥ë¤òºîÀ®¤·¤Æ¤¤¤Þ¤¹¡£

º£²ó¤Ï¤³¤ì¤òGWT¤ÇMVP²½¤¹¤ë¤È¤É¤¦¤Ê¤ë¤«¤ò½ñ¤­¤Þ¤¹¡£

Åоì¿Íʪ

MVP + EventBus¥Ñ¥¿¡¼¥ó¤Ç¤Ï°Ê²¼¤Î¤è¤¦¤ÊÅоì¿Íʪ¤¬¤¤¤Þ¤¹¡£

Model ¥Ñ¥Ã¥±¡¼¥¸¡§com.google.code.stk.share.model

MVC¤ÎModel

¡Ê¥â¥Ç¥ë¤Î²ò¼á¤¬¤¤¤í¤¤¤í¤¢¤ë¤Î¤Ç¾ÜºÙ¤Ï½ü¤­¤Þ¤¹¡£¡Ë

»ä¤Î¾ì¹ç¤Ïappengine¤ÎEntity¤¬¤½¤Î¤Þ¤ÞModel¤È¤·¤Æ¤¤¤Þ¤¹¡£

package com.google.code.stk.shared.model;

import java.io.Serializable;

import com.google.appengine.api.datastore.Key;
import com.google.code.stk.shared.Enums;

import org.slim3.datastore.Attribute;
import org.slim3.datastore.Model;

@Model(schemaVersion = 1)
public class AutoTweet implements Serializable {

	private static final long serialVersionUID = 1L;

	@Attribute(primaryKey = true)
	private Key key;

	@Attribute(version = true)
	private Long version;

	/** tweet */
	@Attribute(unindexed = true)
	private String tweet;

	/** bure */
	@Attribute(unindexed = true)
	private Enums.Bure bure;

	/** cycle */
	@Attribute(unindexed = true)
	private Enums.Cycle cycle;

	/** startMMdd */
	private String startMMdd;

	/** endMMdd */
	private String endMMdd;

	/** tweetTime(hh) */
	@Attribute
	private String tweetHour;

	@Attribute(unindexed = true)
	private String lastTweetAt;

	private String screenName;

	/**
	 * key¤ò¼èÆÀ¤·¤Þ¤¹¡£
	 * @return key
	 */
	public Key getKey() {
		return key;
	}

	/**
	 * key¤òÀßÄꤷ¤Þ¤¹¡£
	 * @param key key
	 */
	public void setKey(Key key) {
		this.key = key;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((key == null) ? 0 : key.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		AutoTweet other = (AutoTweet) obj;
		if (key == null) {
			if (other.key != null) {
				return false;
			}
		} else if (!key.equals(other.key)) {
			return false;
		}
		return true;
	}

	/**
	 * version¤ò¼èÆÀ¤·¤Þ¤¹¡£
	 * @return version
	 */
	public Long getVersion() {
		return version;
	}

	/**
	 * version¤òÀßÄꤷ¤Þ¤¹¡£
	 * @param version version
	 */
	public void setVersion(Long version) {
		this.version = version;
	}

	/**
	 * tweet¤ò¼èÆÀ¤·¤Þ¤¹¡£
	 * @return tweet
	 */
	public String getTweet() {
	    return tweet;
	}

	/**
	 * tweet¤òÀßÄꤷ¤Þ¤¹¡£
	 * @param tweet tweet
	 */
	public void setTweet(String tweet) {
	    this.tweet = tweet;
	}

	/**
	 * cycle¤ò¼èÆÀ¤·¤Þ¤¹¡£
	 * @return cycle
	 */
	public Enums.Cycle getCycle() {
	    return cycle;
	}

	/**
	 * cycle¤òÀßÄꤷ¤Þ¤¹¡£
	 * @param cycle cycle
	 */
	public void setCycle(Enums.Cycle cycle) {
	    this.cycle = cycle;
	}

	/**
	 * startMMdd¤ò¼èÆÀ¤·¤Þ¤¹¡£
	 * @return startMMdd
	 */
	public String getStartMMdd() {
	    return startMMdd;
	}

	/**
	 * startMMdd¤òÀßÄꤷ¤Þ¤¹¡£
	 * @param startMMdd startMMdd
	 */
	public void setStartMMdd(String startMMdd) {
	    this.startMMdd = startMMdd;
	}

	/**
	 * endMMdd¤ò¼èÆÀ¤·¤Þ¤¹¡£
	 * @return endMMdd
	 */
	public String getEndMMdd() {
	    return endMMdd;
	}

	/**
	 * endMMdd¤òÀßÄꤷ¤Þ¤¹¡£
	 * @param endMMdd endMMdd
	 */
	public void setEndMMdd(String endMMdd) {
	    this.endMMdd = endMMdd;
	}

	/**
	 * tweetTime(hhmm)¤ò¼èÆÀ¤·¤Þ¤¹¡£
	 * @return tweetTime(hhmm)
	 */
	public String getTweetHour() {
	    return tweetHour;
	}

	/**
	 * tweetTime(hhmm)¤òÀßÄꤷ¤Þ¤¹¡£
	 * @param tweetTime tweetTime(hhmm)
	 */
	public void setTweetHour(String tweetTime) {
	    this.tweetHour = tweetTime;
	}

	public void setBure(Enums.Bure bure) {
		this.bure = bure;
	}

	public Enums.Bure getBure() {
		return bure;
	}

	public String getLastTweetAt() {
		return lastTweetAt;
	}

	public void setLastTweetAt(String lastTweetAt) {
		this.lastTweetAt = lastTweetAt;
	}

	public String getScreenName() {
		return screenName;
	}

	public void setScreenName(String value) {
		this.screenName = value;
	}
}
Display ¥Ñ¥Ã¥±¡¼¥¸:com.google.code.stk.client.ui.display

MVP¤ÎView¤Ë¤¢¤¿¤ë¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¡£

¼ÂºÝ¤ÎView¥¯¥é¥¹¡ÊWidgets¤äUiBinder¡Ë¤Î³Æ¹àÌܤò¥á¥½¥Ã¥É¤Ë»ý¤Á¤Þ¤¹¡£

package com.google.code.stk.client.ui.display;

import java.util.List;

import com.google.appengine.api.datastore.Key;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasValue;

public interface AutoTweetDisplay extends Display {
	HasValue<String> getKeyId();

	HasValue<String> getTweet();

	HasValue<String> getBure();

	HasValue<String> getCycle();

	HasValue<String> getEndMMdd();

	HasValue<String> getStartMMdd();

	HasValue<String> getTweetHour();

	void setPresenter(Presenter presenter);

	public interface Presenter{
		public void regist();
	}

	Button getRegistButton();

	void setScreenNames(List<Key> arg0);

	HasValue<String> getScreenName();
}

Display¤ÏPresenter¤ÈView¤ò¤½·ë¹ç¤Ë¤·¡¢

ºÆÍøÍÑÀ­¤È¥Æ¥¹¥È¤ò¤·¤ä¤¹¤¯¤·¤Æ¤¤¤Þ¤¹¡£

¤Û¤È¤ó¤É¤Î¥á¥½¥Ã¥É¤¬Has¡Á¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹¤ÇÀë¸À¤µ¤ì¤Æ¤¤¤ë¤Î¤Ï¡¢

¥Æ¥¹¥È»þ¤Ê¤É¤Ë¥â¥Ã¥¯¤òÆþ¤ì¤ä¤¹¤¯¤¹¤ë¤¿¤á¤Ç¤¹¡£

View ¥Ñ¥Ã¥±¡¼¥¸:com.google.code.stk.client.ui.display

View¥¯¥é¥¹¤ÏUiBinder¤äWidgets¤ÇºîÀ®¤µ¤ì¤¿¡¢¡Ö²èÌ̡פò»ý¤Ä¥¯¥é¥¹¤Ç¤¹¡£

View¤ÏDisplay¤ò¼ÂÁõ¤·¡¢²èÌ̤òºîÀ®¤·¤Þ¤¹¡£

package com.google.code.stk.client.ui.display;

import java.util.List;

import com.google.appengine.api.datastore.Key;
import com.google.code.stk.client.ui.base.ValueListBox;
import com.google.code.stk.shared.Enums.Bure;
import com.google.code.stk.shared.Enums.Cycle;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class AutoTweetView extends Composite implements AutoTweetDisplay{

	@UiField
	TextBox tweet;

	@UiField
	TextBox startMMdd;

	@UiField
	TextBox endMMdd;

	@UiField
	ValueListBox cycle;

	@UiField
	ValueListBox tweetHour;

	@UiField
	ValueListBox bure;

	@UiField
	TextBox keyId;

	@UiField
	Button registButton;

	@UiField
	ValueListBox screenName;

	private static AutoTweetViewUiBinder uiBinder = GWT
			.create(AutoTweetViewUiBinder.class);

	private Presenter presenter;

	private List<Key> arg0;

	interface AutoTweetViewUiBinder extends UiBinder<Widget, AutoTweetView> {
	}

	public AutoTweetView() {
		initWidget(uiBinder.createAndBindUi(this));
		initDisplay();
	}

	private void initDisplay() {
		for (Bure b : Bure.values()) {
			bure.addItem(b.name());
		}

		for(Cycle c : Cycle.values()){
			cycle.addItem(c.name());
		}

		for(int i = 0; i < 24 ; i++){
			String hour = String.valueOf(i);

			if(hour.length() < 2){
				hour = 0 + hour;
			}
			tweetHour.addItem(hour +"»þ" , hour);
		}
	}

	@UiHandler("registButton")
	public void onRegistButtonClick(ClickEvent e){
		registButton.setEnabled(false);
		presenter.regist();
	}

	@Override
	public Button getRegistButton(){
		return registButton;
	}

	@Override
	public HasValue<String> getBure() {
		return bure;
	}

	@Override
	public HasValue<String> getCycle() {
		return cycle;
	}

	@Override
	public HasValue<String> getEndMMdd() {
		return endMMdd;
	}

	@Override
	public HasValue<String> getKeyId() {
		return keyId;
	}

	@Override
	public HasValue<String> getStartMMdd() {
		return startMMdd;
	}

	@Override
	public HasValue<String> getTweetHour() {
		return tweetHour;
	}

	@Override
	public Widget asWidget() {
		return this;
	}

	@Override
	public HasValue<String> getTweet() {
		return tweet;
	}

	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
	}

	@Override
	public void setScreenNames(List<Key> arg0) {
		this.arg0 = arg0;
		for (Key key : this.arg0) {
			screenName.addItem(key.getName());
		}
	}

	@Override
	public HasValue<String> getScreenName() {
		return screenName;
	}

}
Presenter

MVP¤ÎP¤Ç¡Öµ¡Ç½Ä󶡼ԡפÎÌò³ä¤ò»ý¤Á¤Þ¤¹¡£

¤ä¤ë¤³¤È¤Ï

  • ¥¤¥Ù¥ó¥È¤Î½èÍý
  • ¥Ç¡¼¥¿¥Ð¥¤¥ó¥É¡ÊView¤ØÅϤ¹¡Ë

¤Ç¤¹¡£

package com.google.code.stk.client.ui.presenter;

import java.util.List;

import com.google.appengine.api.datastore.Key;
import com.google.code.stk.client.event.NewTweetCreatedEvent;
import com.google.code.stk.client.service.TwitterServiceAsync;
import com.google.code.stk.client.ui.display.AutoTweetDisplay;
import com.google.code.stk.client.ui.display.AutoTweetDisplay.Presenter;
import com.google.code.stk.shared.Enums.Bure;
import com.google.code.stk.shared.Enums.Cycle;
import com.google.code.stk.shared.model.AutoTweet;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class NewPresenter extends AbstractPresenter<AutoTweetDisplay> implements Presenter {

	private final TwitterServiceAsync service;

	public NewPresenter(AutoTweetDisplay display, HandlerManager eventBus , TwitterServiceAsync service) {
		super(display, eventBus);
		this.service = service;
		display.setPresenter(this);
	}

	@Override
	public void regist() {
		display.getRegistButton().setEnabled(false);

		AutoTweet data = new AutoTweet();
		data.setBure(Bure.valueOf(display.getBure().getValue()));
		data.setCycle(Cycle.valueOf(display.getCycle().getValue()));
		data.setStartMMdd(display.getStartMMdd().getValue());
		data.setEndMMdd(display.getEndMMdd().getValue());
		data.setTweet(display.getTweet().getValue());
		data.setTweetHour(display.getTweetHour().getValue());
		data.setScreenName(display.getScreenName().getValue());


		service.regist(data, new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void arg0) {
				display.getRegistButton().setEnabled(true);
				eventBus.fireEvent(new NewTweetCreatedEvent());
			}

			@Override
			public void onFailure(Throwable throwable) {

			}
		});
	}

	@Override
	protected void initView() {
		container.clear();
		service.findAllAccessToeknOnlyKey(new AsyncCallback<List<Key>>() {

			@Override
			public void onFailure(Throwable arg0) {

			}

			@Override
			public void onSuccess(List<Key> arg0) {
				display.setScreenNames(arg0);
				container.add(display.asWidget());
			}
		});
	}

}
AppController

AppController¤Ï³ÆPresenter¤ÈDisplay¤Î´ÉÍý¡¢

ÆÈ¼«Event¤Î½èÍý¤ò¹Ô¤¤¤Þ¤¹¡£

¤Þ¤¿ValueChangeHandler¤ò¼ÂÁõ¤¹¤ë¤³¤È¤Ç¡¢

Presenter¤ÈHistory¤ò´ÉÍý¤¹¤ë¤³¤È¤Ë¤è¤ê¡¢

²èÌÌÁ«°Ü¤ò¥³¥ó¥È¥í¡¼¥ë¤·¤Æ¤¤¤Þ¤¹¡£

package com.google.code.stk.client;

import com.google.code.stk.client.event.DeleteTweetClickEvent;
import com.google.code.stk.client.event.DeleteTweetClickHandler;
import com.google.code.stk.client.event.EditTweetClickEvent;
import com.google.code.stk.client.event.EditTweetClickHandler;
import com.google.code.stk.client.event.NewTweetClickEvent;
import com.google.code.stk.client.event.NewTweetClickHandler;
import com.google.code.stk.client.event.NewTweetCreatedEvent;
import com.google.code.stk.client.event.NewTweetCreatedHandler;
import com.google.code.stk.client.service.TwitterService;
import com.google.code.stk.client.service.TwitterServiceAsync;
import com.google.code.stk.client.ui.display.AutoTweetDisplay;
import com.google.code.stk.client.ui.display.AutoTweetView;
import com.google.code.stk.client.ui.display.ListDisplay;
import com.google.code.stk.client.ui.display.ListView;
import com.google.code.stk.client.ui.presenter.AbstractPresenter;
import com.google.code.stk.client.ui.presenter.EditPresenter;
import com.google.code.stk.client.ui.presenter.ListPresenter;
import com.google.code.stk.client.ui.presenter.NewPresenter;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.HasWidgets;

public class AppController implements ValueChangeHandler<String> {

	private final HandlerManager eventBus;

	private HasWidgets container;

	private TwitterServiceAsync service = GWT.create(TwitterService.class);

	public AppController(HandlerManager eventBus) {
		super();
		this.eventBus = eventBus;
		bind();
	}

	public void go(HasWidgets container){
		this.container = container;

		if(History.getToken() == null || History.getToken().equals("")){
			History.newItem("list");
		}else{
			History.fireCurrentHistoryState();
		}
	}

	private void bind() {
		History.addValueChangeHandler(this);

		eventBus.addHandler(NewTweetClickEvent.TYPE, new NewTweetClickHandler() {
			@Override
			public void onClick(NewTweetClickEvent e) {
				History.newItem("new");
			}
		});

		eventBus.addHandler(EditTweetClickEvent.TYPE, new EditTweetClickHandler() {

			@Override
			public void onClick(EditTweetClickEvent e) {
				History.newItem("edit/" + String.valueOf(e.getKey()));
			}
		});

		eventBus.addHandler(DeleteTweetClickEvent.TYPE, new DeleteTweetClickHandler() {

			@Override
			public void onClick(DeleteTweetClickEvent e) {
				History.newItem("list/deleteComplete/" + String.valueOf(e.getKey()));
			}
		});

		eventBus.addHandler(NewTweetCreatedEvent.TYPE, new NewTweetCreatedHandler() {

			@Override
			public void onCreated(NewTweetCreatedEvent e) {
				History.newItem("list/newComplete");
			}
		});

	}

	@Override
	public void onValueChange(ValueChangeEvent<String> arg0) {
		String token = History.getToken();

		if(token == null || token.startsWith("list") || token.equals("")){
			ListDisplay display = new ListView();

			AbstractPresenter<ListDisplay> presenter = new ListPresenter(display , eventBus , service);

			presenter.go(container);
			return;
		}

		if(token.equals("new")){
			AutoTweetView display = new AutoTweetView();

			AbstractPresenter<AutoTweetDisplay> presenter = new NewPresenter(display, eventBus, service);


			presenter.go(container);
			return;
		}

		if(token.startsWith("edit/")){
			long id = Long.parseLong(token.replace("edit/", ""));

			AutoTweetView display = new AutoTweetView();

			AbstractPresenter<AutoTweetDisplay> presenter = new EditPresenter(display, eventBus, service, id);

			presenter.go(container);
		}

	}

}
EventBus (HandlerManager)

EventBus(HandlerManager)¤ÏÆÈ¼«ºîÀ®Event¤Î´ÉÍý¤ò¹Ô¤¤¤Þ¤¹¡£

¤³¤ÎEventBus¤ËÆÈ¼«Event¤òÅÐÏ¿¤·¡¢Handler¤Î½èÍý¤òÄêµÁ¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£


ư¤­¤Îή¤ì

­¡ »Ï¤Þ¤ê¡ÊEntryPoint ¢ª AppController¡Ë

¤Þ¤ºEntryPoint¤Ç¤ÏEventBus¤ÎºîÀ®¤È¡¢AppController¤ÎºîÀ®¤ò¤ª¤³¤Ê¤¤¤Þ¤¹¡£

¤Þ¤¿AppController¤Ëɽ¼¨¤Îµ¯ÅÀ¡Êcontainer)¤òÄÌÃΤ·¤Þ¤¹¡£


package com.google.code.stk.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.ui.RootPanel;

public class Index implements EntryPoint {

	@Override
	public void onModuleLoad() {

		HandlerManager eventBus = new HandlerManager(null);

		AppController appController = new AppController(eventBus);

		appController.go(RootPanel.get("contents"));

		RootPanel.get("msg").setVisible(false);
	}

}

AppController¤¬new¤µ¤ì¤ë¥¿¥¤¥ß¥ó¥°¤Ç¥³¥ó¥¹¥È¥é¥¯¥¿¤Ë¤Æ¡¢EventBus¤ò¼õ¤±¼è¤ê¡¢

ÆÈ¼«¥¤¥Ù¥ó¥È¤ÎÅÐÏ¿¤ò¹Ô¤¤¤Þ¤¹¡£(bind()¥á¥½¥Ã¥É)

ÆÈ¼«Event¤ÎºîÀ®point¤Ï²èÌÌÁ«°Ü¤¬¹Ô¤ï¤ì¤ë¸Ä½ê¤Ç¤¹¡£

¤Þ¤¿ÆÈ¼«Event¤Î½èÍý¤â²èÌÌÁ«°Ü¤¬¹Ô¤ï¤ì¤¿¤³¤È¤òµ­Ï¿¤¹¤ë¤¿¤á

History¤ÎÅÐÏ¿¤Î¤ß¤ª¤³¤Ê¤¤¤Þ¤¹¡£

¤Þ¤¿¤³¤Î»þ¡¢AppController¼«¿®¤òHistory¤ÎValueChangeEventHandler¤È¤·¤ÆÅÐÏ¿¤·¤Þ¤¹¡£

@AppController¤Î¥³¥ó¥¹¥È¥é¥¯¥¿

	public AppController(HandlerManager eventBus) {
		super();
		this.eventBus = eventBus;
		bind();
	}

	private void bind() {
		History.addValueChangeHandler(this);

		eventBus.addHandler(NewTweetClickEvent.TYPE, new NewTweetClickHandler() {
			@Override
			public void onClick(NewTweetClickEvent e) {
				History.newItem("new");
			}
		});

		eventBus.addHandler(EditTweetClickEvent.TYPE, new EditTweetClickHandler() {

			@Override
			public void onClick(EditTweetClickEvent e) {
				History.newItem("edit/" + String.valueOf(e.getKey()));
			}
		});

		eventBus.addHandler(DeleteTweetClickEvent.TYPE, new DeleteTweetClickHandler() {

			@Override
			public void onClick(DeleteTweetClickEvent e) {
				History.newItem("list/deleteComplete/" + String.valueOf(e.getKey()));
			}
		});

		eventBus.addHandler(NewTweetCreatedEvent.TYPE, new NewTweetCreatedHandler() {

			@Override
			public void onCreated(NewTweetCreatedEvent e) {
				History.newItem("list/newComplete");
			}
		});

	}

EntryPoint¤ÇAppController¤ÎºîÀ®¤¬´°Î»¤·¤¿¤é¡¢AppController#go¤ò¸Æ¤Ó½Ð¤·¡¢

½é´ü²èÌ̤òɽ¼¨¤·¤Þ¤¹¡£

go¥á¥½¥Ã¥É¤Ç¤Ï¡¢½é´üɽ¼¨¤ò¹Ô¤¦¿ÆWidgets¤ò¼õ¤±¼è¤ê¡¢Êݸ¤·¤Þ¤¹¡£

¤½¤·¤Æ¡¢History¤Ë¤Ê¤Ë¤âÀÑ¤Þ¤ì¤Æ¤Ê¤±¤ì¤Ð¡¢½é´ü²èÌ̤òɽ¼¨¤¹¤ë¤¿¤áHistory¤Ëtoken¤òÊݸ¤·¤Þ¤¹¡£

´û¤Ë¡¢History¤Ë²¿¤«¤¢¤Ã¤¿¾ì¹ç¡ÊÄ̾ï¤ÏF5¤Ê¤É¤Ç²èÌ̤ò¹¹¿·¤·¤¿¤Ê¤É¡Ë¤Ï¸½¹Ô¤ÎToken¤Î¾õÂÖ¤ÇValueChangeEvent¤òȯÀ¸¤µ¤»¤Þ¤¹¡£

	public void go(HasWidgets container){
		this.container = container;

		if(History.getToken() == null || History.getToken().equals("")){
			History.newItem("list");
		}else{
			History.fireCurrentHistoryState();
		}
	}

go¥á¥½¥Ã¥É¤Ë¤Æ¡¢È¯¹Ô¤µ¤ì¤¿HistoryToken¤Ë¤è¤ê¡¢ValueChangeEvent¤¬È¯À¸¤·¤Þ¤¹¡£

AppController¤Î¥³¥ó¥¹¥È¥é¥¯¥¿¤Ë¤Æ¡¢AppController¼«¿®¤¬History¤ÎValueChangeHandler¤È¤·¤Æ

ÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë¤¿¤á¡¢AppController¤ÎonValueChange¥á¥½¥Ã¥É¤¬¸Æ¤Ó½Ð¤µ¤ì¤Þ¤¹¡£

onValueChange¥á¥½¥Ã¥É¤Ç¤ÏHistoryToken¤ò¤â¤È¤Ë¤É¤Î²èÌ̤òɽ¼¨¤¹¤ë¤«¡ÊDisplay¤ÈPresenter¤ò»È¤¦¤«¡Ë¤ò

ȽÄꤷ¤Þ¤¹¡£

½é´ü½èÍý¤Î¾ì¹ç¤Ï¡¢token¤¬"list"¤È¤Ê¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢ListDisplay¤ÈListPresenter¤¬ÍøÍѤµ¤ì¤Þ¤¹¡£

	@Override
	public void onValueChange(ValueChangeEvent<String> arg0) {
		String token = History.getToken();

		if(token == null || token.startsWith("list") || token.equals("")){
			ListDisplay display = new ListView();

			AbstractPresenter<ListDisplay> presenter = new ListPresenter(display , eventBus , service);

			presenter.go(container);
			return;
		}

		if(token.equals("new")){
			AutoTweetView display = new AutoTweetView();

			AbstractPresenter<AutoTweetDisplay> presenter = new NewPresenter(display, eventBus, service);

			presenter.go(container);
			return;
		}

		if(token.startsWith("edit/")){
			long id = Long.parseLong(token.replace("edit/", ""));

			AutoTweetView display = new AutoTweetView();

			AbstractPresenter<AutoTweetDisplay> presenter = new EditPresenter(display, eventBus, service, id);

			presenter.go(container);
		}

	}

°Ê¾å¤Ë¤Æ¡¢EntryPoint¤«¤éAppController¤Þ¤Ç¤Î½èÍý¤Ï´°Î»¤Ç¤¹¡£

AppController¤¬History¤Ë¤è¤ê²èÌÌÁ«°Ü¤òÀ©¸æ¤¹¤ë¤³¤È¤Ç¡¢

²èÌÌÁ«°Ü=History¤Ø¤ÎÅÐÏ¿¤È¤¤¤¦¾õÂÖ¤¬½ÐÍè¤Þ¤¹¡£

¤³¤ì¤Ë¤è¤êF5¤ä¥Ö¥é¥¦¥¶¥Ð¥Ã¥¯¤Ë¶¯¤¤¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤¬ºîÀ®¤Ç¤­¤Þ¤¹¡£

¤¿¤È¤¨¤Ð¾åµ­¤Ë¤Æ°ìÍ÷²èÌ̤¬É½¼¨¤µ¤ì¤¿¸å¡¢¿·µ¬ºîÀ®²èÌ̤òɽ¼¨¤¹¤ë¾ì¹ç¤Ï¡¢

ListPresenter¤Ë¤ÆNewTweetClickEvent¤òEventBus·Ðͳ¤Çȯ²Ð¤¹¤ë¤³¤È¤Ë¤è¤ê¡¢

ºÆ¤ÓAppController¤Ø½èÍý¤¬Ìá¤ê¡¢History¤¬"new"¤ÇÀѤޤ졢

AppController¤ÎonValueChange¥á¥½¥Ã¥É¤¬¸Æ¤Ð¤ì

NewPresetner¤ÈNewDisplay¤¬Áª¤Ð¤ì¤Æ²èÌ̤¬É½¼¨¤µ¤ì¤Þ¤¹¡£

Â絬ÌϤʳ«È¯¤Î¾ì¹ç¤Ï¤³¤ÎAppController¤òÊ£¿ôºîÀ®¤·¡¢Event½èÍý¤òʬ³ä¤¹¤ë¤³¤È¤â²Äǽ¤Ç¤¹¡£

¤Þ¤¿onValueChange¤´¤È¤Ç¡¢¥³¡¼¥Éʬ³ä(GWT.runAsync)¤ò¹Ô¤Ã¤Æ²èÌ̤´¤È¤Ë¥³¡¼¥É¤òʬ³ä¤¹¤ë¤³¤È¤â²Äǽ¤Ç¤¹¡£

History¤ò»È¤Ã¤¿²èÌÌÁ«°Ü¤Ï´ÉÍý¤â¤·¤ä¤¹¤¯¡¢ÃͲèÌÌÁ«°Ü¤Ë¥Ñ¥é¥á¡¼¥¿¤òɬÍפȤ¹¤ë¾ì¹ç¤â¡¢#hoge/value¤Ê¤É¤È¤·¤Æ¤¦¤Þ¤¯¼èÆÀ¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡£

¢¨¥¿¥Ö¥óGmail¤È¤«¤â¤½¤ó¤Ê´¶¤¸¡©

AppController¤òÍøÍѤ¹¤ë¤³¤È¤Ç¡¢¸«¤ä¤¹¤¤²èÌÌÁ«°Ü¤ÎÀ©¸æ¤òºî¤ë¤³¤È¤¬½Ð¤­¤Þ¤¹¡£

¤¢¤È¤¬¤­

ʸºÍ¤¬¤Ê¤¤¡£¡£¡£¡£

¼¡²ó¤ÏMVP¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤òºÙ¤«¤¯½ñ¤­¤Þ¤¹¡£

¥¿¥Ö¥ó¡¢¥½¥Î¥¦¥Á¡¢¥¤¥Ä¥«¥«¥­¥Þ¥¹

2010-03-21

Navigation¤ò³ÈÄ¥¤·¤Æ¤ß¤ë¡£

| 16:21 | Navigation¤ò³ÈÄ¥¤·¤Æ¤ß¤ë¡£¤ò´Þ¤à¥Ö¥Ã¥¯¥Þ¡¼¥¯ Navigation¤ò³ÈÄ¥¤·¤Æ¤ß¤ë¡£¤Î¥Ö¥Ã¥¯¥Þ¡¼¥¯¥³¥á¥ó¥È

T2Framework¤ÎÈó¾ï¤Ë»È¤¤¤ä¤¹¤¤¤È¤³¤í¤Î°ì¤Ä¤Ë³ÈÄ¥À­¤Î¹â¤µ¤¬¤¢¤ë¤È»×¤¤¤Þ¤¹¡£¤È¤¤¤¦¤³¤È¤Çº£²ó¤ÏNavigation¤ò³ÈÄ¥¤·¤Æ¤ß¤Þ¤¹¡£

¤³¤È¤Îȯü

¸½ºßT2 + Guice + GAE + mobylet + Slim3¤ò»È¤Ã¤Æ²èÁüupload¥µ¥¤¥È¤òºî¤Ã¤Æ¤Þ¤¹¡£

¤Ç¤½¤Î¤Ê¤«¤ÇGAE¤ÏfileSystem¤ò°·¤¨¤Ê¤¤¤¿¤á¡¢Datastore¤ËFile¥Ç¡¼¥¿¤òÆþ¤ì¤ÆÃÖ¤«¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¾õÂ֤Ǥ·¤¿¡£

¤Ä¤Þ¤ê²èÁü¤òUp¤·¤¿¤é¡¢¤½¤ì¤ò¸«¤ë¤Ë¤ÏDatastore¤«¤é°ì²ó°ú¤ÃÄ¥¤ê½Ð¤·¤ÆResponse¥Ü¥Ç¥£¡¼¤Ë½ñ¤­½Ð¤¹Åª¤Ê¤³¤È¤ò¤·¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡£

T2Framework¤Î¾ì¹ç

T2Framework¤Î¾ì¹çľÀÜResponse¤Ë½ñ¤­½Ð¤¹¤Ë¤Ï¡¢Direct¥Ê¥Ó¥²¡¼¥·¥ç¥ó¤òÍøÍѤ·¤Þ¤¹¡£

¤¿¤À¤³¤Î¥¯¥é¥¹¤òÍøÍѤ¹¤ë¾ì¹ç¤ÏHTTP¤ÎContentsType¤ÏPage¦¤Ç»ØÄꤷ¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡£

¤Ä¤Þ¤ê¤³¤ó¤Ê´¶¤¸

    res.setContentType("image/jpeg");
    return Direct.from(img.getData());

¤Ç³ÈÄ¥¤·¤è¤¦

contentType¤°¤é¤¤¼«Á°¤Ç´èÄ¥¤ì¤Ð¡©¤È¸À¤ï¤ì¤½¤¦¤Ç¤¹¤¬¡¢¤Þ¤¡¤ä¤Ã¤Æ¤ß¤¿¤¤¤ó¤Ç¤¹¡£Navigation¤Î³ÈÄ¥

¤À¤Ã¤ÆÃˤλҤÀ¤â¤ó¡£¡£¡£

¤È¤¤¤¦¤³¤È¤ÇNavigation¤ò³ÈÄ¥¤·¤Þ¤·¤¿¡£

´ðËÜŪ¤Ë¤ÏDirect¤ò·Ñ¾µ¤·¤Æ¡¢ContentsType¤òȽÄê¤Ç¤­¤ë¤è¤¦¤Ë¤·¤è¤¦¤È¹Í¤¨¤Æ¤³¤ó¤Ê´¶¤¸¤Çºî¤Ã¤Æ¤ß¤Þ¤·¤¿¡£

package com.google.code.stk.t2gae.commons.navigation;

import java.io.File;
import java.io.InputStream;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.t2framework.commons.util.Assertion;
import org.t2framework.commons.util.FileUtil;
import org.t2framework.commons.util.StreamUtil;
import org.t2framework.t2.contexts.WebContext;
import org.t2framework.t2.navigation.StreamNavigation;
import org.t2framework.t2.spi.Navigation;

public class Img extends StreamNavigation {

	private String contentType;

	public Img(byte[] bytes) {
		super(bytes);
		ImgCodec codec = ImgCodec.getInstance(bytes);
		Assertion.notNull(codec);
		contentType = codec.contentType;
	}

	public Img(File file) {
		super(file);
		ImgCodec codec = ImgCodec.getInstance(FileUtil.getBytes(file));
		Assertion.notNull(codec);
		contentType = codec.contentType;
	}

	public Img(InputStream is) {
		super(is);
		ImgCodec codec = ImgCodec.getInstance(StreamUtil.getBytes(is));
		contentType = codec.contentType;
	}

	public Img(byte[] bytes , ImgCodec codec) {
		super(bytes);
		Assertion.notNull(codec);
		contentType = codec.contentType;
	}

	public Img(File file , ImgCodec codec) {
		super(file);
		Assertion.notNull(codec);
		contentType = codec.contentType;
	}

	public Img(InputStream is , ImgCodec codec) {
		super(is);
		Assertion.notNull(codec);
		contentType = codec.contentType;
	}

	public static Navigation jpg(byte[] bytes){
		return new Img(bytes , ImgCodec.JPG);
	}

	public static Navigation gif(byte[] bytes){
		return new Img(bytes , ImgCodec.GIF);
	}

	public static Navigation png(byte[] bytes){
		return new Img(bytes , ImgCodec.PNG);
	}

	public static Navigation jpg(File file){
		return new Img(file , ImgCodec.JPG);
	}

	public static Navigation gif(File file){
		return new Img(file , ImgCodec.GIF);
	}

	public static Navigation png(File file){
		return new Img(file , ImgCodec.PNG);
	}

	public static Navigation jpg(InputStream is){
		return new Img(is , ImgCodec.JPG);
	}

	public static Navigation gif(InputStream is){
		return new Img(is , ImgCodec.GIF);
	}

	public static Navigation png(InputStream is){
		return new Img(is , ImgCodec.PNG);
	}

	public static Navigation from(byte[] bytes){
		return new Img(bytes);
	}

	public static Navigation from(File file){
		return new Img(file);
	}

	public static Navigation from(InputStream is){
		return new Img(is);
	}

	@Override
	public void execute(WebContext context) throws Exception {
		final HttpServletResponse res = context.getResponse().getNativeResource();
		res.setContentType(contentType);
		ServletOutputStream sos = res.getOutputStream();
		super.writeTo(res, sos);
		sos.flush();
	}

	public enum ImgCodec{
		GIF("image/gif"),

		PNG("image/gif"),

		JPG("image/jpg");

		private String contentType;

		private ImgCodec(String contentType){
			this.contentType = contentType;
		}

		public String getContentType(){
			return this.contentType;
		}

		public static ImgCodec getInstance(byte[] bytes){
			if (bytes != null &&
					bytes.length >= 2) {
				int b1 = bytes[0] & 0xFF;
				int b2 = bytes[1] & 0xFF;
				if (b1 == 0xFF && b2 == 0xD8) {
					return ImgCodec.JPG;
				} else if (b1 == 0x47 && b2 == 0x49) {
					return ImgCodec.GIF;
				} else if (b1 == 0x89 && b2 == 0x50) {
					return ImgCodec.PNG;
				}
			}
			return null;
		}
	}
}

¤Á¤Ê¤ß¤ËImage¤ÎȽÄê½èÍý¤Ïmobylet¤ò»²¹Í¤Ë¤µ¤»¤Æ¤¤¤¿¤À¤­¤Þ¤·¤¿¡£

¤Ç¤¢¤È¤ÏImage¥Ç¡¼¥¿¤òFile or Stream or byte ¤Ç¼è¤Ã¤Æ¤³¤ÎImg.from()¤È¤«¸Æ¤Ù¤ÐOK¤Ç¤¹¡£

byte[]¤Î½ñ¤­½Ð¤·¤Î¤È¤³¤í¡¢BufferedOutputStream¤È¤«¤Ä¤«¤Ã¤¿¤Û¤¦¤¬¤¤¤¤¤Î¤«¤Ê¡©

¤Á¤Ê¤ß¤Ëgoogle code ¤Ë¸ø³«¤·¤¿¤Î¤Ç¡¢¤´ÍøÍѤÎÊý¤Ï¤É¤¦¤¾¡ª

http://code.google.com/p/project-stk/source/browse/trunk/stk-t2-gae-commons/src/main/java/com/google/code/stk/t2gae/commons/navigation/Img.java

JavaDoc¤Ï¤Þ¤¡¤½¤Î¤¦¤Á¡£¡£¡£

T2¤ÇSlim3¤Î¥Ð¥ê¥Ç¡¼¥·¥ç¥ó¤ò»È¤¤¤¿¤¤

| 16:48 | T2¤ÇSlim3¤Î¥Ð¥ê¥Ç¡¼¥·¥ç¥ó¤ò»È¤¤¤¿¤¤¤ò´Þ¤à¥Ö¥Ã¥¯¥Þ¡¼¥¯ T2¤ÇSlim3¤Î¥Ð¥ê¥Ç¡¼¥·¥ç¥ó¤ò»È¤¤¤¿¤¤¤Î¥Ö¥Ã¥¯¥Þ¡¼¥¯¥³¥á¥ó¥È

¸½ºßºî¤Ã¤Æ¤¤¤ë¥µ¥¤¥È¤ÏWeb·Ï¤ÎÉôʬ¤Ït2¡¢±Ê³²½¼þ¤ê¤Ïslim3-datastore¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡£

¤¿¤Àt2¤Ë¤ÏValidation¤Ï¤Ê¤¤¤Î¤Ç(t2¤Ë¤Ï¤Ê¤¯¤Æ¤¤¤¤¤È»×¤¤¤Þ¤¹ ¤½¤ÎÇö¤µ¤¬¤È¤Æ¤âÁÇŨ¤Ê¤Î¤Ç¡£)¤É¤¦¤·¤è¤¦¤«¤Ê¤È»×¤Ã¤Æ¤¤¤¿¤Î¤Ç¤¹¤¬¡¢

¤¢¤ë¤¸¤ã¤Ê¤¤¤Ç¤¹¤«Slim3¤Ë¡ªvalidators¤¬¡ª

¤Ã¤Æ¤³¤È¤Çslim3¤ÎValidators¤òT2¤Ç»È¤¨¤Ê¤¤¤«¤ä¤Ã¤Æ¤ß¤Þ¤·¤¿¡£

¤È¤ê¤¢¤¨¤º¤Ê¤ó¤â¹Í¤¨¤Ê¤¤¤Ç¤Ä¤«¤Ã¤Æ¤ß¤¿¡£¡£¡£

¤È¤ê¤¢¤¨¤º²¿¤â¹Í¤¨¤Ê¤¤¤Ç¡¢»È¤Ã¤Æ¤ß¤Þ¤·¤¿¡£

	/**
	 * ¥¤¥á¡¼¥¸¥Ç¡¼¥¿¤òÊݸ¤·¤Þ¤¹¡£
	 * @param context context
	 * @param request request
	 * @param file ¥¢¥Ã¥×¥í¡¼¥É¥Õ¥¡¥¤¥ë
	 * @param title ¥¿¥¤¥È¥ë
	 * @param updaterComment Åê¹Æ¼Ô¥³¥á¥ó¥È
	 * @return À®¸ù»þ´°Î»²èÌÌ
	 */
	@POST
	@ActionParam("store")
	public Navigation store( WebContext context
							,HttpServletRequest request
							,UploadFile file
							,@RequestParam("title") String title
							,@RequestParam("updaterComment") String updaterComment
							){
		//¤³¤³¤«¤éValidation
		Validators v = new Validators(request);
		v.add(ImageMeta.get().title, v.required());
		v.add("img", v.byteType());
		v.add(ImageMeta.get().updaterComment , v.maxlength(500));
		if(v.validate() == false){
			//v.validate()¤¬false¤Ê¤é½ªÎ»
			return index(context);
		}

		if(file.get().length > StkConst.MAX_IMAGE_BYTES){
			return index(context);
		}

		if(!ArrayUtil.contains(StkConst.getSupportedExtensions() , FilenameUtils.getExtension(file.getName()).toLowerCase())){
			return index(context);
		}

		Image image = new Image();
		GlobalTransaction tx =Datastore.beginGlobalTransaction();
		try{
			image.setKey(Datastore.allocateId(Image.class));
			image.getUpdaterRef().setModel((Member)context.getSession().getAttribute(StkConst.SESSION_KEY_MEMBER));
			image.setTitle(title);
			image.setUpdaterComment(updaterComment);
			image.setCreateDate(new Date());
			image.setFileName(file.getName());
			List<ImgUnit> imgUnits = image.setImage(file.get());
			tx.put(imgUnits);
			tx.put(image);
			tx.commit();
		}catch (Exception e){
			tx.rollback();
			v.getErrors().put("put", e.getMessage());
		}
		return Redirect.to("/top");
	}

¤Ç¼Â¹Ô¤¹¤ë¤È¡¢²¼µ­¤Î¤è¤¦¤ÊException

Caused by: java.lang.NullPointerException

at org.slim3.jsp.Functions.errors(Functions.java:403)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at org.apache.commons.el.FunctionInvocation.evaluate(FunctionInvocation.java:172)

at org.apache.commons.el.ExpressionEvaluatorImpl.evaluate(ExpressionEvaluatorImpl.java:263)

at org.apache.commons.el.ExpressionEvaluatorImpl.evaluate(ExpressionEvaluatorImpl.java:190)

at org.apache.jasper.runtime.PageContextImpl$13.run(PageContextImpl.java:884)

at java.security.AccessController.doPrivileged(Native Method)

at org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:880)

at org.apache.jsp.upload.index_jsp._jspx_meth_c_forEach_0(index_jsp.java:153)

at org.apache.jsp.upload.index_jsp._jspService(index_jsp.java:86)

... 66 more

¤Ê¤ó¤«É¬Íפ餷¤¤¡£¡£¡£

¤Ç³ºÅö¤Î¾ì½ê¤ò¤ß¤ë¤È

@slim3 Functions

    /**
     * Returns errors iterator.
     * 
     * @return errors iterator
     */
    @SuppressWarnings("unchecked")
    public static Iterator<String> errors() {
        HttpServletRequest request = RequestLocator.get();¢«¤³¤³¤ÇNull¤¬µ¢¤ë¡£
        Map<String, String> errors = ¢«¤³¤³¤ÇNullPointer
            (Map<String, String>) request  
                .getAttribute(ControllerConstants.ERRORS_KEY);
        if (errors != null) {
            return errors.values().iterator();
        }
        return null;
    }

¤³¤ó¤Ê´¶¤¸¤é¤·¤¯¡¢RequestLocator¤Ërequest¤¬Æþ¤Ã¤Æ¤¤¤Ê¤¤¤È¤¤¤±¤Ê¤¤¤é¤·¤¤¡£¡£¡£

¤¢¤ÈÊ·°Ïµ¤Åª¤ËRequest¤Î¤Ê¤«¤ËControllerConstrants.ERRORS_KEY¤Ç¤Ê¤ó¤«¤Ï¤¤¤Ã¤Æ¤ë¤é¤·¤¤¡£


¤Ç¤¤¤í¤¤¤í¸«¤Æ¤Ã¤ÆPlugin¤òºî¤Ã¤Æ¤ß¤¿¡£

¤Ç¤¤¤í¤¤¤í¸«¤Æ¤Ã¤ÆPlugin¤òºî¤Ã¤Æ¤ß¤¿¡£

¤³¤ó¤Ê´¶¤¸¤Ç¤¹¡£

package com.google.code.stk.t2gae.commons.plugin;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slim3.controller.ControllerConstants;
import org.slim3.controller.validator.Errors;
import org.slim3.util.ApplicationMessage;
import org.slim3.util.RequestLocator;
import org.slim3.util.ResponseLocator;
import org.t2framework.t2.plugin.AbstractPlugin;

/**
 * slim3¤Î³Æ¼ïµ¡Ç½¤òÍøÍѤ¹¤ë¤¿¤á¤ÎPlugin
 * @author keisuke.oohashi
 *
 */
public class Slim3Plugin extends AbstractPlugin {

	//TODO 2010/03/21 16:37:53 keisuke.oohashi:ThreadSafe¤¸¤ã¤Ê¤µ¤½¤¦¡£¡£¡£
	/** previousRequest */
	private HttpServletRequest previousRequest;

	/** previousResponse */
	private HttpServletResponse previousResponse;

	/**
	 * slim3¤Î¥³¥ó¥È¥í¡¼¥é¥¯¥é¥¹¤ÎÂå¤ï¤ê¤ËRequest¡¢Response¡¢Errors¤ÎÀßÄê¤ò¹Ô¤¤¤Þ¤¹¡£
	 *
	 * @param request Request
	 * @param response Response
	 *
	 * @see org.slim3.controller.FrontController
	 * @see org.t2framework.t2.plugin.AbstractPlugin#beginRequestProcessing(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 *
	 */
	@Override
	public void beginRequestProcessing(HttpServletRequest request, HttpServletResponse response) {

		previousRequest = RequestLocator.get();

		RequestLocator.set(request);

		previousResponse = ResponseLocator.get();

		ResponseLocator.set(response);

		ApplicationMessage.setBundle(ControllerConstants.DEFAULT_LOCALIZATION_CONTEXT, request.getLocale());

		Errors errors = (Errors) request.getAttribute(ControllerConstants.ERRORS_KEY);

		if (errors == null) {

			errors = new Errors();

			request.setAttribute(ControllerConstants.ERRORS_KEY, errors);
		}

		super.beginRequestProcessing(request, response);
	}

	/**
	 * slim3¤Î¥³¥ó¥È¥í¡¼¥é¥¯¥é¥¹¤ÎÂå¤ï¤ê¤ËRequest¡¢Response¡¢Errors¤Î¥¯¥ê¥¢¤ò¹Ô¤¤¤Þ¤¹¡£
	 *
	 * @param request Request
	 * @param response Response
	 *
	 * @see org.slim3.controller.FrontController
	 * @see org.t2framework.t2.plugin.AbstractPlugin#endRequestProcessing(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	public void endRequestProcessing(HttpServletRequest request, HttpServletResponse response) {

		ApplicationMessage.clearBundle();

		ResponseLocator.set(previousResponse);


		RequestLocator.set(previousRequest);

		super.endRequestProcessing(request, response);
	}
}

¤³¤ó¤Ê´¶¤¸¤Çºî¤Ã¤Æ¤ß¤¿¤Î¤Ç¤¹¤¬¡¢TODO¤Ë¤â½ñ¤¤¤Æ¤ëÄ̤ꡢThreadSafe¤¸¤ã¤Ê¤µ¤½¤¦¡£¡£¡£

Plugin¥¯¥é¥¹¤ÏGuice¤ÎRequestScoped¤ÇÊݸ¤Ç¤­¤Ê¤¤¤Ã¤Ý¤¤¤Î¤Ç¤È¤ê¤¢¤¨¤ºSINGLETON¤Ë¤·¤Æ¤Þ¤¹¡£

¤«¤Ê¤ê²ø¤·¤¤¡£

¤Ç¤¢¤È¤Ï¤³¤Î¥¯¥é¥¹¤òGuice¥â¥¸¥å¡¼¥ë¤ÇÅÐÏ¿¤·¤Æ¤ª¤­¤Þ¤¹¡£

		bind(Plugin.class).annotatedWith(Names.named("slim3Plugin")).to(Slim3Plugin.class).in(Scopes.SINGLETON);

¤³¤ì¤ÇºÇ½é¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ù¤ÐValidator¤¬¼Â»Ü¤µ¤ì¤Þ¤¹¡£

¤Á¤Ê¤ß¤Ë¥½¡¼¥¹¤Ï¤³¤Î¤Ø¤ó¤Ç¤¹¡£

http://code.google.com/p/project-stk/source/browse/trunk/stk-t2-gae-commons/src/main/java/com/google/code/stk/t2gae/commons/plugin/Slim3Plugin.java

Êä­

º£²ó¤Î¤ÏSlim3¤ÎFilter¥¯¥é¥¹(FrontController)¤òÆþ¤ì¤ì¤Ð¤È¤¯¤ËÀßÄꤹ¤ëɬÍפϤ¢¤ê¤Þ¤»¤ó¡£

¤¿¤À»äŪ¤Ë¡¢WebÁؤΥե졼¥à¥ï¡¼¥¯¤¬º®ºß¤¹¤ë¾õ¶·¤Ï¤¢¤Þ¤ê¤è¤¯¤Ê¤¤¤Î¤«¤Ê¤È»×¤Ã¤Æºî¤ê¤Þ¤·¤¿¡£

T2¤ÎÎɤµ¤Ï¤½¤ÎÇö¤µ¤Ë¤¢¤ë¤È»×¤Ã¤Æ¤¤¤Þ¤¹¡£

Çö¤¤¤«¤é¤³¤½¡¢µ¡Ç½³ÈÄ¥À­¤¬¹â¤¯¡¢Â¾¤Î¥Õ¥ì¡¼¥à¥ï¡¼¥¯¤ò¼ÙË⤷¤Þ¤»¤ó¡£¤à¤·¤í°ú¤­Î©¤Æ¤Þ¤¹¡£

T2»È¤Ã¤Æ»Å»ö¤¬½ÐÍ褿¤é¤¹¤Æ¤­¤À¤Ê¤¡¡Á

2010-02-17

T2+GAE+guice ¤ÎPage¥¯¥é¥¹ÍÑGuiceModule¤òAnnotation Processing Tool¤ÇºîÀ®¤·¤Þ¤¹¡£

| 01:09 | T2+GAE+guice ¤ÎPage¥¯¥é¥¹ÍÑGuiceModule¤òAnnotation Processing Tool¤ÇºîÀ®¤·¤Þ¤¹¡£¤ò´Þ¤à¥Ö¥Ã¥¯¥Þ¡¼¥¯ T2+GAE+guice ¤ÎPage¥¯¥é¥¹ÍÑGuiceModule¤òAnnotation Processing Tool¤ÇºîÀ®¤·¤Þ¤¹¡£¤Î¥Ö¥Ã¥¯¥Þ¡¼¥¯¥³¥á¥ó¥È

T2 GuiceÏ¢·È¤À¤ÈPage¥¯¥é¥¹¤òModule¤Ç°ì¤Ä¤º¤ÄÆÉ¤ß¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡£

°Õ³°¤È¤³¤ì¤¬ÌÌÅݤʺî¶È¤Ç¡¢Pageºî¤Ã¤¿¤±¤ÉModule¤Ë½ñ¤­Ëº¤ì¤Æ¤â¤Ã¤«¤¤ApplicationServerºÆµ¯Æ°¤Ê¤ó¤Æ¤³¤È¤Ï¤è¤¯¤¢¤ê¤Þ¤¹¡£

¤Æ¤³¤È¤Ç¤á¤ó¤É¤¯¤µ¤¤ºî¶È¤ÏTool¤òºî¤Ã¤Æ¤·¤Þ¤¨¤È»×¤¤¤Þ¤·¤¿¡£¤½¤³¤ÇºÇ¶á¤è¤¯¸«¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤­¤¿Annotation Processing Tool(°Ê²¼ APT)¤Ç

Page¥¯¥é¥¹ÍÑModule¤òºîÀ®¤·¤Æ¤ß¤Þ¤¹¡£

¤Þ¤ºAnnotation¤ò½èÍý¤¹¤ëProcessor¥¯¥é¥¹

package jp.stk.tools.apt.processor;

import java.util.List;
import java.util.Map;

import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;

import jp.stk.tools.apt.AptConst;
import jp.stk.tools.apt.generator.T2GuiceModuleGenerator;

import org.t2framework.t2.tool.apt.PageMirror;
import org.t2framework.t2.tool.apt.PageSettingsGenerator;
import org.t2framework.t2.tool.apt.PageSettingsProcessor;

/**
 * t2 page module processor
 * <pre>
 * t2¤ÎPage¥¯¥é¥¹ÍÑModule¥¯¥é¥¹¤òºîÀ®¤¹¤ëProcessor¥¯¥é¥¹¤Ç¤¹¡£
 * </pre>
 * @author soundTricker
 *
 */
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("org.t2framework.t2.annotation.core.Page")
@SupportedOptions({AptConst.OPTIONS_GENERATE_MODULE_NAME , AptConst.OPTIONS_OUTPUT_PACKAGE})
public class T2GuiceModuleProcessor extends PageSettingsProcessor {

	/**
	 * GuiceModule¤òºîÀ®¤·¤Þ¤¹¡£
	 * <pre>
	 * Page¥¯¥é¥¹¤Î¥á¥¿¥Ç¡¼¥¿¤è¤ê¡¢GuiceModule¤òºîÀ®¤·¤Þ¤¹¡£
	 * </pre>
	 * @see org.t2framework.t2.tool.apt.PageSettingsProcessor#generate(java.util.Map<java.lang.String,java.util.List<org.t2framework.t2.tool.apt.PageMirror>>, javax.annotation.processing.ProcessingEnvironment)
	 */
	@Override
	protected void generate(Map<String, List<PageMirror>> pageMetaMap,ProcessingEnvironment processingEnv) {

		PageSettingsGenerator generator = new T2GuiceModuleGenerator(pageMetaMap, processingEnv);

		generator.generate();
	}
}

PageSettingsProcessor ¤ÏT2framework 0.6.3-cr1¤ËÆþ¤Ã¤Æ¤¤¤¿page.properties¤òºî¤ëAPT¤ÎProcessor¥¯¥é¥¹¤Ç¤¹¡£

¤Û¤È¤ó¤É¤Î½èÍý¤Ï¤³¤ì¤¬¤ä¤Ã¤Æ¤¯¤ì¤Á¤ã¤Ã¤Æ¤Þ¤¹¤Í¡£¡£¡£

¤Ç¤â¥Ð¡¼¥¸¥ç¥ó¤¬cr¤Ê¤Î¤Ç¤Ê¤¯¤Ê¤Ã¤Á¤ã¤Ã¤¿¤é¤É¤¦¤·¤è¤¦¡£

¼¡¤Ë¼ÂºÝ¤ËGuiceModule¤òºîÀ®¤¹¤ëGenerator¥¯¥é¥¹

package jp.stk.tools.apt.generator;

import java.io.IOException;

/**
 * Page¥¯¥é¥¹ÍѤÎGuiceModule¤òºîÀ®¤¹¤ëGenerator¥¯¥é¥¹¤Ç¤¹¡£
 * @author soundTricker
 *
 */
public class T2GuiceModuleGenerator implements PageSettingsGenerator {
	//======================================================================
	//                                                            ¥×¥í¥Ñ¥Æ¥£
	//======================================================================
	/**
	 * Page¥¯¥é¥¹¤Î¥á¥¿¥Ç¡¼¥¿¥Þ¥Ã¥×
	 * <pre>
	 * key:package̾
	 * value:key¤Î¥Ñ¥Ã¥±¡¼¥¸ÆâPage¥¯¥é¥¹¥á¥¿¥Ç¡¼¥¿¤Î¥ê¥¹¥È
	 */
	protected Map<String, List<PageMirror>> pageMetaMap;

	/** APT¤Î¼Â¹Ô¾ðÊó */
	protected ProcessingEnvironment processingEnv;

	/** writer */
	protected PrintWriter writer;

	/** GuiceModule¤Î½ÐÎÏÀè¥Ñ¥Ã¥±¡¼¥¸ */
	protected String outputPackage = "";

	/** ºîÀ®¤¹¤ëGuiceModule̾ */
	protected String generateModuleName = AptConst.DEFAULT_MODULE_NAME;

	//======================================================================
	//                                                        ¥³¥ó¥¹¥È¥é¥¯¥¿
	//======================================================================
	/**
	 * ¥Ç¥Õ¥©¥ë¥È¥³¥ó¥¹¥È¥é¥¯¥¿
	 * <pre>
	 * writer¤Ê¤É¤ÎÀßÄê¤ò¹Ô¤¤¤Þ¤¹¡£
	 * </pre>
	 * @param pageMetaMap Page¥¯¥é¥¹¤Î¥á¥¿¥Ç¡¼¥¿¥Þ¥Ã¥×
	 * @param processingEnv APT¤Î¼Â¹Ô¾ðÊó
	 */
	public T2GuiceModuleGenerator(Map<String, List<PageMirror>> pageMetaMap,ProcessingEnvironment processingEnv) {

		this.pageMetaMap = pageMetaMap;

		this.processingEnv = processingEnv;

		Filer filer = this.processingEnv.getFiler();

		Map<String , String> options = this.processingEnv.getOptions();

		if(options.containsKey(AptConst.OPTIONS_OUTPUT_PACKAGE)){

			outputPackage = options.get(AptConst.OPTIONS_OUTPUT_PACKAGE);
		}

		if(options.containsKey(AptConst.OPTIONS_GENERATE_MODULE_NAME)){

			generateModuleName = options.get(AptConst.OPTIONS_GENERATE_MODULE_NAME);
		}

		FileObject fileObject = null;
		try {
			fileObject = filer.createSourceFile(outputPackage + AptConst.PACKAGE_SEPARATOR + generateModuleName);

			final Writer filerWriter = FilerUtil.openWriter(fileObject);

			this.writer = WriterUtil.createPrintWriter(filerWriter);

		} catch (IOException e) {

			CloseableUtil.close(this.writer);

			throw new IORuntimeException(e);
		}
	}

	//======================================================================
	//                                                                ¥á¥¤¥ó
	//======================================================================
	/**
	 * ¥½¡¼¥¹¤òºîÀ®¤·¤Þ¤¹¡£
	 * @see org.t2framework.t2.tool.apt.PageSettingsGenerator#generate()
	 */
	@Override
	public void generate() {
		try{
			makeClassDefinition();

			makeConfigureMethodDefinition();

			for (Entry<String, List<PageMirror>> pageMetaEntry : pageMetaMap.entrySet()) {
				for (PageMirror pageMirror : pageMetaEntry.getValue()) {
					makeBindLogic(pageMirror);
				}
			}
			makeConfigureMethodFutter();

			makeClassFutter();

			FlushableUtil.flush(writer);
		}finally{
			CloseableUtil.close(writer);
		}

	}

	//======================================================================
	//                                                                ²¼ÀÁ¤±
	//======================================================================
	/**
	 * ¥¯¥é¥¹ÄêµÁ¤òºîÀ®¤·¤Þ¤¹¡£
	 */
	private void makeClassDefinition() {
		writer.format("package %s;\n" , outputPackage);

		writer.format("public class %s extends %s {\n", generateModuleName , AbstractModule.class.getName());

	}

	/**
	 * ¥á¥½¥Ã¥ÉÄêµÁ¤òºîÀ®¤·¤Þ¤¹¡£
	 */
	private void makeConfigureMethodDefinition(){
		writer.format("	@Override\n");

		writer.format("	protected void configure() {\n");
	}

	/**
	 * Page¥¯¥é¥¹¤Î¥á¥¿¥Ç¡¼¥¿¤è¤êbind¥í¥¸¥Ã¥¯¤òºîÀ®¤·¤Þ¤¹¡£
	 * @param pageMirror
	 */
	private void makeBindLogic(PageMirror pageMirror) {
		writer.format("		bind(%s.%s.class).in(com.google.inject.servlet.ServletScopes.REQUEST);\n" , pageMirror.getPackageName() , pageMirror.getPageClassName());
	}

	/**
	 * ¥á¥½¥Ã¥É¤Î¥Õ¥Ã¥¿¡¼¤òºîÀ®¤·¤Þ¤¹¡£
	 */
	private void makeConfigureMethodFutter() {
		writer.format("	}\n");
	}

	/**
	 * ¥¯¥é¥¹¤Î¥Õ¥Ã¥¿¡¼¤òºîÀ®¤·¤Þ¤¹¡£
	 */
	private void makeClassFutter() {
		writer.format("}\n");
	}

}

¤¢¤ÈÄê¿ôÄêµÁ¥¯¥é¥¹¡£

package jp.stk.tools.apt;

public class AptConst {
	public static final String OPTIONS_GENERATE_MODULE_NAME = "generateModuleName";

	public static final String OPTIONS_OUTPUT_PACKAGE = "outputPackage";

	public static final String DEFAULT_MODULE_NAME = "PageModule";

	public static final String PACKAGE_SEPARATOR = ".";
}

¤¿¤À¥Æ¥¹¥È¤Î»ÅÊý¤¬¤ï¤«¤é¤Ê¤¯¤Æ¡¢

Ä´¤Ù¤Æ¤¤¤¿¤é¡¢Seasar¤Îsandbox¤Ëaptina¤È¤¤¤¦APTÍÑ¤Î¥×¥í¥¸¥§¥¯¥È¤¬¤¢¤ê¤Þ¤·¤¿¤Î¤Ç¡¢

¤³¤Á¤é¤Îhttp://aptina.sandbox.seasar.org/aptina-unit/index.html:Aptina Unit]¤ò»È¤Ã¤Æ¤ß¤Þ¤·¤¿¡£

¤Ç¤³¤ì¤¬Test¥¯¥é¥¹

package jp.stk.tools.apt.processor;

import java.io.IOException;

import javax.tools.ToolProvider;

import jp.stk.tools.apt.AptConst;
import jp.stk.tools.apt.testpage.TestPage;

import org.seasar.aptina.unit.AptinaTestCase;

public class T2GuiceModuleProcessorTest extends AptinaTestCase {

	private static final String OPTION_FORMAT = "-A%s=%s";

	protected void setUp() throws Exception {
		super.setUp();
		addSourcePath("src/test/java");
	}

	public void testProcess() throws IOException {
		ToolProvider.getSystemJavaCompiler().getClass();
		T2GuiceModuleProcessor processor = new T2GuiceModuleProcessor();
		addProcessor(processor);
		setCharset("UTF-8");
		addOption(String.format(OPTION_FORMAT, AptConst.OPTIONS_OUTPUT_PACKAGE , "jp.stk.gae.module"));
		addCompilationUnit(TestPage.class);
		compile();
//TODO ¤á¤ó¤É¤¯¤µ¤¤¤Î¤Çɽ¼¨¤À¤±³Îǧ¡£¡£¡£¤Á¤ã¤ó¤Èºî¤é¤Ê¤¯¤Á¤ã¡£¡£¡£
		System.out.println(getGeneratedSource("jp.stk.gae.module." + AptConst.DEFAULT_MODULE_NAME));
	}

}

¤³¤ì¤Ç¥Æ¥¹¥È¤·¤Þ¤·¤¿¡£

º£²ó¤ÏAPT¤ò¤ä¤Ã¤Æ¤ß¤Þ¤·¤¿¡£

»äŬÅö¤ÊSVN¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¤Î¤Çjar¤ò¸ø³«¤Ç¤­¤Þ¤»¤ó¤¬¡¢

¼ÁÌ䤬¤¢¤ê¤Þ¤·¤¿¤é¤´Ï¢Íí¤¯¤À¤µ¤¤¡£

¤Á¤Ê¤ß¤ËºÇ½éVelocity¤Ç¥½¡¼¥¹¤ò¤Ä¤¯¤ë¤Î¡Ê¥Æ¥ó¥×¥ì¡¼¥È¤ÎÊѹ¹¤â²Äǽ¡Ë¤â½ñ¤¤¤Æ¤¤¤¿¤Î¤Ç¤¹¤¬¡¢

¤ï¤¶¤ï¤¶APT¤Î¤¿¤á¤Ë¥é¥¤¥Ö¥é¥ê¤òÍî¤È¤¹¤Î¤â·ù¤«¤Ê¤È»×¤Ã¤Æ¤Ù¤¿½ñ¤­ÈǤòºÜ¤»¤Þ¤·¤¿¡£

Í×˾¤¬¤¢¤Ã¤¿¤éºÜ¤»¤Þ¤¹¡£


Äɲá§

¤³¤Î¥½¡¼¥¹¤À¤ÈAPT¤Ë°ú¿ô¤òÍ¿¤¨¤Ê¤¤¤È¤³¤±¤Þ¤¹¡£¡£¡£

»þ´Ö¤¬¤¢¤Ã¤¿¤é¼£¤·¤Þ¤¹¡£

shot6shot6 2010/02/18 10:19 ¤¹¤Ð¤é¤·¤¤¡ª¤¢¤È¤Ç»î¤·¤Æ¤ß¤¿¤¤¤È»×¤¤¤Þ¤¹¡£
cr¤È¤Ï¤¤¤¨¡¢»È¤Ã¤Æ¤¯¤ì¤Æ¤ë¿Í¤¬¤¤¤ì¤Ð¾Ã¤¹¤Ê¤ó¤Æ¤³¤È¤·¤Ê¤¤¤Î¤Ç°Â¿´¤·¤Æ¤¯¤À¤µ¤¤¡£

yone098yone098 2010/02/18 10:20 GJ, soundTrick++

yone098yone098 2010/02/18 17:42 t2samples¤Ë¥¢¥«¥¦¥ó¥ÈÄɲä·¤Þ¤¹¤Î¤Ç¡¢yone098¡÷G¥á¡¼¥ë¤Ë¡¢
soundTrick¤µ¤ó¤Îgmail¥¢¥É¥ì¥¹Á÷¤Ã¤Æ¤¤¤¿¤À¤±¤Þ¤¹¤«¡©

soundTricksoundTrick 2010/02/18 18:12 ¡äyone098¤µ¤ó
¤¢¤ê¤¬¤È¤¦¸æºÂ¤¤¤Þ¤¹¡ª
¤¹¤°Á÷¤ê¤Þ¤¹¡ª