1515import com .ericlam .mc .eldgui .view .BukkitRedirectView ;
1616import com .ericlam .mc .eldgui .view .BukkitView ;
1717import com .ericlam .mc .eldgui .view .LoadingView ;
18- import com .ericlam .mc .eldgui .view .View ;
1918import com .google .inject .Injector ;
2019import com .google .inject .TypeLiteral ;
2120import org .bukkit .Bukkit ;
2827import java .lang .annotation .Annotation ;
2928import java .lang .reflect .Method ;
3029import java .lang .reflect .ParameterizedType ;
31- import java .util .Arrays ;
32- import java .util .List ;
33- import java .util .Map ;
34- import java .util .Optional ;
30+ import java .util .*;
3531import java .util .concurrent .ConcurrentHashMap ;
3632import java .util .function .Consumer ;
3733import java .util .function .Function ;
3834import java .util .stream .Collectors ;
3935
4036public final class ELDGUI {
4137
38+ private static final Map <Class <?>, Method []> declaredMethodMap = new ConcurrentHashMap <>();
4239 private static final Logger LOGGER = LoggerFactory .getLogger (ELDGUI .class );
4340
4441
@@ -49,7 +46,6 @@ public final class ELDGUI {
4946 private final LifeCycleManager lifeCycleManager ;
5047
5148 private final Class <?> controllerCls ;
52- private final Object controller ;
5349 private final Injector injector ;
5450 private final UISession session ;
5551 private final Player owner ;
@@ -61,6 +57,7 @@ public final class ELDGUI {
6157 private final Consumer <Player > onDestroy ;
6258 private final ViewJumper goTo ;
6359 private final BukkitView <? extends LoadingView , Void > loadingView ;
60+ private final Method [] declaredMethods ;
6461
6562
6663 private ELDGView <?> currentView ;
@@ -79,7 +76,6 @@ public ELDGUI(
7976 ) {
8077
8178 this .session = session ;
82- this .controller = controller ;
8379 this .injector = injector ;
8480 this .owner = owner ;
8581 this .onDestroy = onDestroy ;
@@ -91,16 +87,22 @@ public ELDGUI(
9187 methodParseManager = managerFactory .buildParseManager (this ::initMethodParseManager );
9288 returnTypeManager = managerFactory .buildReturnTypeManager (this ::initReturnTypeManager );
9389 this .lifeCycleManager = new LifeCycleManager (controller , methodParseManager );
90+ this .controllerCls = controller .getClass ();
91+
92+ if (declaredMethodMap .containsKey (controllerCls )) {
93+ this .declaredMethods = declaredMethodMap .get (controllerCls );
94+ } else {
95+ this .declaredMethods = controllerCls .getDeclaredMethods ();
96+ declaredMethodMap .put (controllerCls , declaredMethods );
97+ }
9498
9599 var customQualifier = eldgmvcInstallation .getQualifierMap ();
96- this .eventHandlerMap .put (InventoryClickEvent .class , new ELDGClickEventHandler (controller , methodParseManager , returnTypeManager , customQualifier ));
97- this .eventHandlerMap .put (InventoryDragEvent .class , new ELDGDragEventHandler (controller , methodParseManager , returnTypeManager , customQualifier ));
100+ this .eventHandlerMap .put (InventoryClickEvent .class , new ELDGClickEventHandler (controller , methodParseManager , returnTypeManager , customQualifier , declaredMethods ));
101+ this .eventHandlerMap .put (InventoryDragEvent .class , new ELDGDragEventHandler (controller , methodParseManager , returnTypeManager , customQualifier , declaredMethods ));
98102 this .itemGetterMap .put (InventoryClickEvent .class .getSimpleName (), e -> ((InventoryClickEvent ) e ).getCurrentItem ());
99103 this .itemGetterMap .put (InventoryDragEvent .class .getSimpleName (), e -> ((InventoryDragEvent ) e ).getOldCursor ());
100104
101105
102- this .controllerCls = controller .getClass ();
103-
104106 this .lifeCycleManager .onLifeCycle (PostConstruct .class );
105107
106108 Optional <Class <? extends LoadingView >> loadingViewOpt = Optional .ofNullable (this .controllerCls .getAnnotation (AsyncLoadingView .class )).map (AsyncLoadingView ::value );
@@ -140,7 +142,7 @@ private synchronized void jumpToController(BukkitRedirectView redirectView) {
140142 public void initIndexView (Object controller ) {
141143 LOGGER .debug ("initializing index view" ); // debug
142144 try {
143- Optional <Method > indexMethod = Arrays .stream (controllerCls . getDeclaredMethods () ).filter (m -> m .getName ().equalsIgnoreCase ("index" )).findAny ();
145+ Optional <Method > indexMethod = Arrays .stream (declaredMethods ).filter (m -> m .getName ().equalsIgnoreCase ("index" )).findAny ();
144146 if (indexMethod .isEmpty ())
145147 throw new IllegalStateException ("cannot find index method from " + controllerCls );
146148 Method index = indexMethod .get ();
@@ -203,7 +205,7 @@ private void initMethodParseManager(MethodParseManager parser) {
203205 FromPattern pattern = (FromPattern ) Arrays .stream (annotations ).filter (a -> a .annotationType () == FromPattern .class ).findAny ().orElseThrow (() -> new IllegalStateException ("cannot find @FromPattern in List<ItemStack> parameters" ));
204206 if (t instanceof ParameterizedType ) {
205207 var parat = (ParameterizedType ) t ;
206- if (parat .getActualTypeArguments ()[0 ] == ItemStack .class && parat .getRawType () == List .class ){
208+ if (parat .getActualTypeArguments ()[0 ] == ItemStack .class && parat .getRawType () == List .class ) {
207209 return this .currentView .getEldgContext ().getItems (pattern .value ());
208210 }
209211 }
@@ -221,48 +223,42 @@ private void initMethodParseManager(MethodParseManager parser) {
221223 parser .registerParser ((t , annos ) -> Arrays .stream (annos ).anyMatch (a -> a .annotationType () == ModelAttribute .class ),
222224 (annotations , type , event ) -> {
223225 ModelAttribute modelAttribute = (ModelAttribute ) Arrays .stream (annotations ).filter (a -> a .annotationType () == ModelAttribute .class ).findAny ().orElseThrow (() -> new IllegalStateException ("cannot find @ModelAttribute" ));
224- var context = this .currentView .getEldgContext ();
225226 if (type instanceof ParameterizedType )
226227 throw new IllegalStateException ("model attribute cannot be generic type" );
227228 var model = ((Class <?>) type );
228-
229- Map <String , Object > fieldMap = context .getItems (modelAttribute .value ())
230- .stream ()
231- .filter (item -> context .getAttribute (item , AttributeController .FIELD_TAG ) != null )
232- .collect (Collectors
233- .toMap (
234- item -> context .getAttribute (item , AttributeController .FIELD_TAG ),
235- item -> Optional .ofNullable (context .getAttribute (item , AttributeController .VALUE_TAG )).orElseThrow (() -> new IllegalStateException ("The value tag of " + item .toString () + " is null." ))
236- )
237- );
229+ var fieldMap = getFieldMap (modelAttribute .value ());
238230 Map <String , Object > toConvert = PersistDataUtils .toNestedMap (fieldMap );
239231 LOGGER .debug ("using " + toConvert + " to create instance of " + model );
240232 return PersistDataUtils .mapToObject (toConvert , model );
241233 });
242234 parser .registerParser ((t , annos ) -> Arrays .stream (annos ).anyMatch (a -> a .annotationType () == MapAttribute .class ),
243235 (annotations , type , event ) -> {
244236 MapAttribute attribute = (MapAttribute ) Arrays .stream (annotations ).filter (a -> a .annotationType () == MapAttribute .class ).findAny ().orElseThrow (() -> new IllegalStateException ("cannot find MapAttribute annotation" ));
245- var context = this .currentView .getEldgContext ();
246237 boolean isMap = false ;
247- if (type instanceof ParameterizedType ){
248- var parat = (ParameterizedType )type ;
238+ if (type instanceof ParameterizedType ) {
239+ var parat = (ParameterizedType ) type ;
249240 isMap = parat .getRawType () == Map .class && parat .getActualTypeArguments ()[0 ] == String .class && parat .getActualTypeArguments ()[1 ] == Object .class ;
250241 }
251242
252243 if (!isMap ) throw new IllegalStateException ("@MapAttribute 必須使用 Map<String, Object> 作為其類型" );
253- Map <String , Object > fieldMap = context .getItems (attribute .value ())
254- .stream ()
255- .filter (item -> context .getAttribute (item , AttributeController .FIELD_TAG ) != null )
256- .collect (Collectors
257- .toMap (
258- item -> context .getAttribute (item , AttributeController .FIELD_TAG ),
259- item -> Optional .ofNullable (context .getAttribute (item , AttributeController .VALUE_TAG )).orElseThrow (() -> new IllegalStateException ("The value tag of " + item .toString () + " is null." ))
260- )
261- );
244+ Map <String , Object > fieldMap = getFieldMap (attribute .value ());
262245 return PersistDataUtils .toNestedMap (fieldMap );
263246 });
264247 }
265248
249+ private Map <String , Object > getFieldMap (char pattern ){
250+ if (this .currentView == null ) throw new IllegalStateException ("currentView is null" );
251+ var context = this .currentView .getEldgContext ();
252+ Map <String , Object > fieldMap = new HashMap <>();
253+ for (ItemStack item : context .getItems (pattern )) {
254+ String field = context .getAttribute (item , AttributeController .FIELD_TAG );
255+ if (field == null ) continue ;
256+ Object value = context .getAttribute (item , AttributeController .VALUE_TAG );
257+ fieldMap .put (field , value );
258+ }
259+ return fieldMap ;
260+ }
261+
266262 private ItemStack getItemByEvent (InventoryEvent e ) {
267263 return Optional .ofNullable (e ).map (ee -> itemGetterMap .get (ee .getEventName ())).map (f -> f .apply (e )).orElseThrow (() -> new IllegalStateException ("no item return by the event or the event is null" ));
268264 }
@@ -315,7 +311,12 @@ private void handleException(Exception ex) {
315311 Class <? extends ExceptionViewHandler > exceptionViewHandler = exceptionViewHandlerOpt .orElseGet (eldgmvcInstallation ::getDefaultExceptionHandler );
316312 ExceptionViewHandler viewHandlerIns = injector .getInstance (exceptionViewHandler );
317313 UIController fromController = controllerCls .getAnnotation (UIController .class );
318- Arrays .stream (exceptionViewHandler .getDeclaredMethods ())
314+ Method [] declaredMethods = Optional .ofNullable (declaredMethodMap .get (exceptionViewHandler )).orElseGet (() -> {
315+ var methods = exceptionViewHandler .getDeclaredMethods ();
316+ declaredMethodMap .put (exceptionViewHandler , methods );
317+ return methods ;
318+ });
319+ Arrays .stream (declaredMethods )
319320 .filter (m -> m .isAnnotationPresent (HandleException .class ))
320321 .filter (m -> Arrays .stream (m .getAnnotation (HandleException .class ).value ()).anyMatch (v -> {
321322 Class <?> superCls = ex .getClass ();
0 commit comments