@Override public void generateData(Object itemId, Item item, JsonObject rowData) { HierarchyData hierarchyData = new HierarchyData(); // calculate depth int depth = 0; if (getContainer() instanceof Measurable) { depth = ((Measurable) getContainer()).getDepth(itemId); // Measurable } else { Object id = itemId; while (!getContainer().isRoot(id)) { id = getContainer().getParent(id); depth++; } } hierarchyData.setDepth(depth); // set collapsed state if (getContainer() instanceof Collapsible) { hierarchyData.setCollapsed(((Collapsible) getContainer()).isCollapsed(itemId)); // Collapsible } // set leaf state hierarchyData.setLeaf(!getContainer().hasChildren(itemId)); // Hierarchical // set index of parent node hierarchyData.setParentIndex(getContainer() .indexOfId(getContainer().getParent(itemId))); // Indexed (indexOfId) and Hierarchical (getParent) // add hierarchy information to row as metadata rowData.put(GridState.JSONKEY_ROWDESCRIPTION, JsonCodec.encode(hierarchyData, null, HierarchyData.class, getUI().getConnectorTracker()) .getEncodedValue()); }
@Override public void addEventListener(EventListener listener) { List<Method> listenerMethods = findInterfaceMethods( listener.getClass()); for (Method method : listenerMethods) { if (method.getDeclaringClass() == Object.class) { // Ignore continue; } String name = method.getName(); if (!name.startsWith("on")) { throw new RuntimeException(method.toString()); } name = name.substring(2).toLowerCase(); if (method.getParameterCount() != 1) { throw new RuntimeException(); } if (method.getReturnType() != void.class) { throw new RuntimeException(); } Map<String, Integer> methodOrder = new HashMap<>(); Class<?> eventType = method.getParameterTypes()[0]; Method[] eventGetters = eventType.getDeclaredMethods(); String[] argumentBuilders = new String[eventGetters.length]; for (int i = 0; i < eventGetters.length; i++) { Method getter = eventGetters[i]; if (getter.getParameterCount() != 0) { throw new RuntimeException(getter.toString()); } String paramName = ElementReflectHelper .getPropertyName(getter.getName()); methodOrder.put(getter.getName(), Integer.valueOf(i)); argumentBuilders[i] = "event." + paramName; } addEventListener(name, new JavaScriptFunction() { @Override public void call(final JsonArray arguments) { InvocationHandler invocationHandler = (proxy, calledMethod, args) -> { if (calledMethod.getDeclaringClass() == Object.class) { // Standard object methods return calledMethod.invoke(proxy, args); } else { String methodName = calledMethod.getName(); int indexOf = methodOrder.get(methodName) .intValue(); return JsonCodec.decodeInternalOrCustomType( calledMethod.getGenericReturnType(), arguments.get(indexOf), null); } }; Object event = Proxy.newProxyInstance( eventType.getClassLoader(), new Class[] { eventType }, invocationHandler); try { method.invoke(listener, event); } catch (Exception e) { throw new RuntimeException(e); } } }, argumentBuilders); } }
void eval(ElementImpl element, String script, Object[] arguments) { // Param values JsonArray params = Json.createArray(); // Array of param indices that should be treated as callbacks JsonArray callbacks = Json.createArray(); for (int i = 0; i < arguments.length; i++) { Object value = arguments[i]; Class<? extends Object> type = value.getClass(); if (JavaScriptFunction.class.isAssignableFrom(type)) { // TODO keep sequence per element instead of "global" int cid = callbackIdSequence++; element.setCallback(cid, (JavaScriptFunction) value); value = Integer.valueOf(cid); type = Integer.class; callbacks.set(callbacks.length(), i); } EncodeResult encodeResult = JsonCodec.encode(value, null, type, null); params.set(i, encodeResult.getEncodedValue()); } addCommand("eval", element, Json.create(script), params, callbacks); }