Skip to content

Commit

Permalink
Merge pull request #12 from ELDEpendenci/develop
Browse files Browse the repository at this point in the history
組件現在可以接受 null 數值
  • Loading branch information
eric2788 authored Sep 2, 2021
2 parents fba9697 + 20d0206 commit 676fdee
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
env:
version: 0.1.3 # 你的版本名稱
version: 0.1.3.1 # 你的版本名稱
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
plugin_name: ELDependenci-MVC-plugin

Expand Down
2 changes: 1 addition & 1 deletion ELDependenci-MVC-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>ELDependenci-MVC-plugin</artifactId>
<version>${project.parent.version}</version>
<version>${project.parent.version}.1</version>

<dependencies>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import com.ericlam.mc.eldgui.view.BukkitRedirectView;
import com.ericlam.mc.eldgui.view.BukkitView;
import com.ericlam.mc.eldgui.view.LoadingView;
import com.ericlam.mc.eldgui.view.View;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;
import org.bukkit.Bukkit;
Expand All @@ -28,17 +27,15 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

public final class ELDGUI {

private static final Map<Class<?>, Method[]> declaredMethodMap = new ConcurrentHashMap<>();
private static final Logger LOGGER = LoggerFactory.getLogger(ELDGUI.class);


Expand All @@ -49,7 +46,6 @@ public final class ELDGUI {
private final LifeCycleManager lifeCycleManager;

private final Class<?> controllerCls;
private final Object controller;
private final Injector injector;
private final UISession session;
private final Player owner;
Expand All @@ -61,6 +57,7 @@ public final class ELDGUI {
private final Consumer<Player> onDestroy;
private final ViewJumper goTo;
private final BukkitView<? extends LoadingView, Void> loadingView;
private final Method[] declaredMethods;


private ELDGView<?> currentView;
Expand All @@ -79,7 +76,6 @@ public ELDGUI(
) {

this.session = session;
this.controller = controller;
this.injector = injector;
this.owner = owner;
this.onDestroy = onDestroy;
Expand All @@ -91,16 +87,22 @@ public ELDGUI(
methodParseManager = managerFactory.buildParseManager(this::initMethodParseManager);
returnTypeManager = managerFactory.buildReturnTypeManager(this::initReturnTypeManager);
this.lifeCycleManager = new LifeCycleManager(controller, methodParseManager);
this.controllerCls = controller.getClass();

if (declaredMethodMap.containsKey(controllerCls)) {
this.declaredMethods = declaredMethodMap.get(controllerCls);
} else {
this.declaredMethods = controllerCls.getDeclaredMethods();
declaredMethodMap.put(controllerCls, declaredMethods);
}

var customQualifier = eldgmvcInstallation.getQualifierMap();
this.eventHandlerMap.put(InventoryClickEvent.class, new ELDGClickEventHandler(controller, methodParseManager, returnTypeManager, customQualifier));
this.eventHandlerMap.put(InventoryDragEvent.class, new ELDGDragEventHandler(controller, methodParseManager, returnTypeManager, customQualifier));
this.eventHandlerMap.put(InventoryClickEvent.class, new ELDGClickEventHandler(controller, methodParseManager, returnTypeManager, customQualifier, declaredMethods));
this.eventHandlerMap.put(InventoryDragEvent.class, new ELDGDragEventHandler(controller, methodParseManager, returnTypeManager, customQualifier, declaredMethods));
this.itemGetterMap.put(InventoryClickEvent.class.getSimpleName(), e -> ((InventoryClickEvent) e).getCurrentItem());
this.itemGetterMap.put(InventoryDragEvent.class.getSimpleName(), e -> ((InventoryDragEvent) e).getOldCursor());


this.controllerCls = controller.getClass();

this.lifeCycleManager.onLifeCycle(PostConstruct.class);

Optional<Class<? extends LoadingView>> loadingViewOpt = Optional.ofNullable(this.controllerCls.getAnnotation(AsyncLoadingView.class)).map(AsyncLoadingView::value);
Expand Down Expand Up @@ -140,7 +142,7 @@ private synchronized void jumpToController(BukkitRedirectView redirectView) {
public void initIndexView(Object controller) {
LOGGER.debug("initializing index view"); // debug
try {
Optional<Method> indexMethod = Arrays.stream(controllerCls.getDeclaredMethods()).filter(m -> m.getName().equalsIgnoreCase("index")).findAny();
Optional<Method> indexMethod = Arrays.stream(declaredMethods).filter(m -> m.getName().equalsIgnoreCase("index")).findAny();
if (indexMethod.isEmpty())
throw new IllegalStateException("cannot find index method from " + controllerCls);
Method index = indexMethod.get();
Expand Down Expand Up @@ -203,7 +205,7 @@ private void initMethodParseManager(MethodParseManager parser) {
FromPattern pattern = (FromPattern) Arrays.stream(annotations).filter(a -> a.annotationType() == FromPattern.class).findAny().orElseThrow(() -> new IllegalStateException("cannot find @FromPattern in List<ItemStack> parameters"));
if (t instanceof ParameterizedType) {
var parat = (ParameterizedType) t;
if (parat.getActualTypeArguments()[0] == ItemStack.class && parat.getRawType() == List.class){
if (parat.getActualTypeArguments()[0] == ItemStack.class && parat.getRawType() == List.class) {
return this.currentView.getEldgContext().getItems(pattern.value());
}
}
Expand All @@ -221,48 +223,42 @@ private void initMethodParseManager(MethodParseManager parser) {
parser.registerParser((t, annos) -> Arrays.stream(annos).anyMatch(a -> a.annotationType() == ModelAttribute.class),
(annotations, type, event) -> {
ModelAttribute modelAttribute = (ModelAttribute) Arrays.stream(annotations).filter(a -> a.annotationType() == ModelAttribute.class).findAny().orElseThrow(() -> new IllegalStateException("cannot find @ModelAttribute"));
var context = this.currentView.getEldgContext();
if (type instanceof ParameterizedType)
throw new IllegalStateException("model attribute cannot be generic type");
var model = ((Class<?>) type);

Map<String, Object> fieldMap = context.getItems(modelAttribute.value())
.stream()
.filter(item -> context.getAttribute(item, AttributeController.FIELD_TAG) != null)
.collect(Collectors
.toMap(
item -> context.getAttribute(item, AttributeController.FIELD_TAG),
item -> Optional.ofNullable(context.getAttribute(item, AttributeController.VALUE_TAG)).orElseThrow(() -> new IllegalStateException("The value tag of " + item.toString() + " is null."))
)
);
var fieldMap = getFieldMap(modelAttribute.value());
Map<String, Object> toConvert = PersistDataUtils.toNestedMap(fieldMap);
LOGGER.debug("using " + toConvert + " to create instance of " + model);
return PersistDataUtils.mapToObject(toConvert, model);
});
parser.registerParser((t, annos) -> Arrays.stream(annos).anyMatch(a -> a.annotationType() == MapAttribute.class),
(annotations, type, event) -> {
MapAttribute attribute = (MapAttribute) Arrays.stream(annotations).filter(a -> a.annotationType() == MapAttribute.class).findAny().orElseThrow(() -> new IllegalStateException("cannot find MapAttribute annotation"));
var context = this.currentView.getEldgContext();
boolean isMap = false;
if (type instanceof ParameterizedType){
var parat = (ParameterizedType)type;
if (type instanceof ParameterizedType) {
var parat = (ParameterizedType) type;
isMap = parat.getRawType() == Map.class && parat.getActualTypeArguments()[0] == String.class && parat.getActualTypeArguments()[1] == Object.class;
}

if (!isMap) throw new IllegalStateException("@MapAttribute 必須使用 Map<String, Object> 作為其類型");
Map<String, Object> fieldMap = context.getItems(attribute.value())
.stream()
.filter(item -> context.getAttribute(item, AttributeController.FIELD_TAG) != null)
.collect(Collectors
.toMap(
item -> context.getAttribute(item, AttributeController.FIELD_TAG),
item -> Optional.ofNullable(context.getAttribute(item, AttributeController.VALUE_TAG)).orElseThrow(() -> new IllegalStateException("The value tag of " + item.toString() + " is null."))
)
);
Map<String, Object> fieldMap = getFieldMap(attribute.value());
return PersistDataUtils.toNestedMap(fieldMap);
});
}

private Map<String, Object> getFieldMap(char pattern){
if (this.currentView == null) throw new IllegalStateException("currentView is null");
var context = this.currentView.getEldgContext();
Map<String, Object> fieldMap = new HashMap<>();
for (ItemStack item : context.getItems(pattern)) {
String field = context.getAttribute(item, AttributeController.FIELD_TAG);
if (field == null) continue;
Object value = context.getAttribute(item, AttributeController.VALUE_TAG);
fieldMap.put(field, value);
}
return fieldMap;
}

private ItemStack getItemByEvent(InventoryEvent e) {
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"));
}
Expand Down Expand Up @@ -315,7 +311,12 @@ private void handleException(Exception ex) {
Class<? extends ExceptionViewHandler> exceptionViewHandler = exceptionViewHandlerOpt.orElseGet(eldgmvcInstallation::getDefaultExceptionHandler);
ExceptionViewHandler viewHandlerIns = injector.getInstance(exceptionViewHandler);
UIController fromController = controllerCls.getAnnotation(UIController.class);
Arrays.stream(exceptionViewHandler.getDeclaredMethods())
Method[] declaredMethods = Optional.ofNullable(declaredMethodMap.get(exceptionViewHandler)).orElseGet(() -> {
var methods = exceptionViewHandler.getDeclaredMethods();
declaredMethodMap.put(exceptionViewHandler, methods);
return methods;
});
Arrays.stream(declaredMethods)
.filter(m -> m.isAnnotationPresent(HandleException.class))
.filter(m -> Arrays.stream(m.getAnnotation(HandleException.class).value()).anyMatch(v -> {
Class<?> superCls = ex.getClass();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,15 +333,15 @@ public <C> C getAttributePrimitive(Class<C> type, ItemStack itemStack, String ke

public Map<String, Object> getAsMap(ItemStack item) {
String id = getAttributePrimitive(String.class, item, "id");
return Optional.ofNullable(attributeMap.get(id)).map(ImmutableMap::copyOf).orElseGet(ImmutableMap::of);
return Optional.ofNullable(attributeMap.get(id)).map(HashMap::new).orElseGet(HashMap::new);
}

@Override
public <C> C getAttribute(ItemStack item, String key) {
public synchronized <C> C getAttribute(ItemStack item, String key) {
// instead of using persist data type, use map
//return getObjectAttribute(item, key);
String id = getIdFromItem(item);
attributeMap.putIfAbsent(id, new ConcurrentHashMap<>());
attributeMap.putIfAbsent(id, new HashMap<>());
LOGGER.debug("item (" + item.getType() + ") is now: " + getAsMap(item).toString());
return (C) attributeMap.get(id).get(key);
}
Expand Down Expand Up @@ -393,11 +393,11 @@ public <C> void setAttributePrimitive(Class<C> type, ItemStack itemStack, String
}

@Override
public void setAttribute(ItemStack itemStack, String key, Object value) {
public synchronized void setAttribute(ItemStack itemStack, String key, Object value) {
// instead of using persist data type, use map
//this.setObjectAttribute(itemStack, key, value);
String id = getIdFromItem(itemStack);
this.attributeMap.putIfAbsent(id, new ConcurrentHashMap<>());
this.attributeMap.putIfAbsent(id, new HashMap<>());
this.attributeMap.get(id).put(key, value);

LOGGER.debug("item (" + itemStack.getType() + ") is now: " + getAsMap(itemStack).toString());
Expand All @@ -410,7 +410,7 @@ public <C> void setAttributePrimitive(Class<C> type, char pattern, String key, O


@Override
public void setAttribute(char pattern, String key, Object value) {
public synchronized void setAttribute(char pattern, String key, Object value) {
getItems(pattern).forEach(item -> setAttribute(item, key, value));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
Expand Down Expand Up @@ -146,6 +147,9 @@ public static <T> T mapToObject(Map<String, Object> map, Class<T> beanClass) {
Map<String, Object> m = (Map<String, Object>) value;
value = mapToObject(m, field.getType());
}
if (value == null && field.isAnnotationPresent(Nonnull.class)){
throw new IllegalStateException("property assigned @Nonnull but setting null value.");
}
try {
field.set(obj, value);
}catch (IllegalAccessException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void renderView(Exception ex, UIContext context) {
.components(
button.icon(Material.BARRIER)
.title("&cError: " + ex.getClass().getSimpleName())
.lore("&c".concat(ex.getMessage()))
.lore("&c" + ex.getMessage())
.create()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ public void beforeCreate(Player player){


@ClickMapping(view = TestView.class, pattern = 'A')
public void onClick(@ModelAttribute('Z') TestModel test, Player player, @MapAttribute('Z') Map<String, Object> map){
public BukkitView<?, ?> onClick(@ModelAttribute('Z') TestModel test, Player player, @MapAttribute('Z') Map<String, Object> map){
player.sendMessage(test.toString());
player.sendMessage(map.toString());
return null;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ public class TestModel {

public LocalTime testTime;

// test null
public String txt;

@Override
public String toString() {
return "TestModel{" +
"testColor=" + testColor.toString() +
", testDate=" + testDate.toString() +
", testTime=" + testTime.toString() +
"testColor=" + testColor +
", testDate=" + testDate +
", testTime=" + testTime +
", txt='" + txt + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ericlam.mc.eldgui.demo.test;

import com.ericlam.mc.eldgui.component.AttributeController;
import com.ericlam.mc.eldgui.component.factory.ButtonFactory;
import com.ericlam.mc.eldgui.component.factory.DateSelectorFactory;
import com.ericlam.mc.eldgui.component.factory.RGBSelectorFactory;
Expand Down Expand Up @@ -47,6 +48,11 @@ public void renderView(Void model, UIContext context) {
.bindInput("testTime", LocalTime.now())
.label("&aTime Select: (shift move unit, click to +/-, middle to input)")
.icon(Material.CLOCK)
.create(),
button.icon(Material.PAPER)
.title("test null string")
.bind(AttributeController.FIELD_TAG, "txt")
.bind(AttributeController.VALUE_TAG, null)
.create()
)
.and()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
public final class ELDGClickEventHandler extends ELDGEventHandler<ClickMapping, InventoryClickEvent> {


public ELDGClickEventHandler(Object controller, MethodParseManager parseManager, ReturnTypeManager returnTypeManager, Map<Class<? extends Annotation>, MVCInstallation.QualifierFilter<? extends Annotation>> customQualifier) {
super(controller, parseManager, returnTypeManager, customQualifier);
public ELDGClickEventHandler(Object controller, MethodParseManager parseManager, ReturnTypeManager returnTypeManager, Map<Class<? extends Annotation>, MVCInstallation.QualifierFilter<? extends Annotation>> customQualifier, Method[] declaredMethods) {
super(controller, parseManager, returnTypeManager, customQualifier, declaredMethods);
}

@Override
protected Map<ClickMapping, Method> loadAllHandlers(Object controller) {
return Arrays.stream(controller.getClass().getDeclaredMethods()).parallel()
protected Map<ClickMapping, Method> loadAllHandlers(Method[] declaredMethods) {
return Arrays.stream(declaredMethods).parallel()
.filter(m -> m.isAnnotationPresent(ClickMapping.class))
.collect(Collectors.toMap(m -> m.getAnnotation(ClickMapping.class), m -> m));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
public final class ELDGDragEventHandler extends ELDGEventHandler<DragMapping, InventoryDragEvent> {


public ELDGDragEventHandler(Object controller, MethodParseManager parseManager, ReturnTypeManager returnTypeManager, Map<Class<? extends Annotation>, MVCInstallation.QualifierFilter<? extends Annotation>> customQualifier) {
super(controller, parseManager, returnTypeManager, customQualifier);
public ELDGDragEventHandler(Object controller, MethodParseManager parseManager, ReturnTypeManager returnTypeManager, Map<Class<? extends Annotation>, MVCInstallation.QualifierFilter<? extends Annotation>> customQualifier, Method[] declaredMethods) {
super(controller, parseManager, returnTypeManager, customQualifier, declaredMethods);
}

@Override
protected Map<DragMapping, Method> loadAllHandlers(Object controller) {
return Arrays.stream(controller.getClass().getDeclaredMethods())
protected Map<DragMapping, Method> loadAllHandlers(Method[] declaredMethods) {
return Arrays.stream(declaredMethods)
.parallel()
.filter(m -> m.isAnnotationPresent(DragMapping.class))
.collect(Collectors.toMap(m -> m.getAnnotation(DragMapping.class), m -> m));
Expand Down
Loading

0 comments on commit 676fdee

Please sign in to comment.