private void processPropertyBindings(Component comp, String propName) { final ComponentCtrl compCtrl = (ComponentCtrl) comp; // validator and converter information ValidatorInfo validatorInfo = parseValidator(compCtrl, propName); ConverterInfo converterInfo = parseConverter(compCtrl, propName); // scan init Collection<Annotation> initannos = compCtrl.getAnnotations(propName, INIT_ANNO); if (initannos.size() > 1) { throw new IllegalSyntaxException("Allow only one @init for " + propName + " of " + comp); } else if (initannos.size() == 1) { processPropertyInit(comp, propName, initannos.iterator().next(), converterInfo); } Collection<Annotation> annos = compCtrl.getAnnotations(propName); // init in the annotation with the sequence for (Annotation anno : annos) { if (anno.getName().equals(BIND_ANNO)) { processPropertyPromptBindings(comp, propName, anno, converterInfo, validatorInfo); } else if (anno.getName().equals(LOAD_ANNO)) { processPropertyLoadBindings(comp, propName, anno, converterInfo); } else if (anno.getName().equals(SAVE_ANNO)) { processPropertySaveBindings(comp, propName, anno, converterInfo, validatorInfo); } } }
private void processCommandBinding(Component comp, String propName) { final ComponentCtrl compCtrl = (ComponentCtrl) comp; final Collection<Annotation> anncol = compCtrl.getAnnotations(propName, COMMAND_ANNO); if (anncol.size() == 0) return; if (anncol.size() > 1) { throw new IllegalSyntaxException( "Allow only one command binding for event " + propName + " of " + compCtrl); } final Annotation ann = anncol.iterator().next(); final Map<String, String[]> attrs = ann.getAttributes(); // (tag, tagExpr) Map<String, String[]> args = null; final List<String> cmdExprs = new ArrayList<String>(); for (final Iterator<Entry<String, String[]>> it = attrs.entrySet().iterator(); it.hasNext(); ) { final Entry<String, String[]> entry = it.next(); final String tag = entry.getKey(); final String[] tagExpr = entry.getValue(); if ("value".equals(tag)) { cmdExprs.add(testString(comp, propName, tag, tagExpr)); } else { // other unknown tag, keep as arguments if (args == null) { args = new HashMap<String, String[]>(); } args.put(tag, tagExpr); } } final Map<String, Object> parsedArgs = args == null ? null : parsedArgs(args); for (String cmd : cmdExprs) { _binder.addCommandBinding(comp, propName, cmd, parsedArgs); } }
private void processFormBindings(Component comp) { final ComponentCtrl compCtrl = (ComponentCtrl) comp; final BindEvaluatorX eval = _binder.getEvaluatorX(); // validator information ValidatorInfo validatorInfo = parseValidator(compCtrl, FORM_ATTR); String formId = null; Collection<Annotation> idannos = compCtrl.getAnnotations(FORM_ATTR, ID_ANNO); if (idannos.size() == 0) { throw new IllegalSyntaxException("@id is not found for a form binding of " + compCtrl); } else if (idannos.size() > 1) { throw new IllegalSyntaxException("Allow only one @id for a form binding of " + compCtrl); } final Annotation idanno = idannos.iterator().next(); final String idExpr = idanno.getAttribute("value"); if (idExpr != null) { formId = BindEvaluatorXUtil.eval(eval, comp, idExpr, String.class); } if (formId == null) { throw new UiException( "value of @id is not found for a form binding of " + compCtrl + ", exprssion is " + idExpr); } // scan init first Collection<Annotation> initannos = compCtrl.getAnnotations(FORM_ATTR, INIT_ANNO); if (initannos.size() > 1) { throw new IllegalSyntaxException("Allow only one @init for " + FORM_ATTR + " of " + comp); } else if (initannos.size() == 1) { processFormInit(comp, formId, initannos.iterator().next()); } Collection<Annotation> annos = compCtrl.getAnnotations(FORM_ATTR); // get all annotation in the form with the order. for (Annotation anno : annos) { if (anno.getName().equals(LOAD_ANNO)) { processFormLoadBindings(comp, formId, anno); } else if (anno.getName().equals(SAVE_ANNO)) { processFormSaveBindings(comp, formId, anno, validatorInfo); } } }
/** * Process the event. Note: it doesn't invoke EventThreadInit and EventThreadCleanup. * * <p>This method is to implement {@link org.zkoss.zk.ui.sys.EventProcessingThread}. See also * {@link org.zkoss.zk.ui.util.Configuration#isEventThreadEnabled}. */ public void process() throws Exception { final ExecutionMonitor execmon = _desktop.getWebApp().getConfiguration().getExecutionMonitor(); // Bug 1506712: event listeners might be zscript, so we have to // keep built-in variables as long as possible final Scope scope = Scopes.beforeInterpret(_comp); // we have to push since process0 might invoke methods from zscript class try { Scopes.setImplicit("event", _event); _event = ((DesktopCtrl) _desktop).beforeProcessEvent(_event); if (_event != null) { if (execmon != null) execmon.eventStart(_event); Scopes.setImplicit("event", _event); // _event might change ((ComponentCtrl) _comp).service(_event, scope); ((DesktopCtrl) _desktop).afterProcessEvent(_event); } } finally { final Execution exec = _desktop.getExecution(); if (exec != null) // just in case ((ExecutionCtrl) exec).setExecutionInfo(null); if (execmon != null && _event != null) execmon.eventComplete(_event); Scopes.afterInterpret(); } }
private ValidatorInfo parseValidator(ComponentCtrl compCtrl, String propName) { final Collection<Annotation> annos = compCtrl.getAnnotations(propName, VALIDATOR_ANNO); if (annos.size() == 0) return null; if (annos.size() > 1) { throw new IllegalSyntaxException( "Allow only one validator for " + propName + " of " + compCtrl); } final Annotation anno = annos.iterator().next(); ValidatorInfo info = new ValidatorInfo(); Map<String, String[]> args = null; for (final Iterator<Entry<String, String[]>> it = anno.getAttributes().entrySet().iterator(); it.hasNext(); ) { final Entry<String, String[]> entry = it.next(); final String tag = entry.getKey(); final String[] tagExpr = entry.getValue(); if ("value".equals(tag)) { info.expr = testString(compCtrl, propName, tag, tagExpr); } else { // other unknown tag, keep as arguments if (args == null) { args = new HashMap<String, String[]>(); } args.put(tag, tagExpr); } } if (Strings.isBlank(info.expr)) { throw new IllegalSyntaxException( "Must specify a validator for " + propName + " of " + compCtrl); } info.args = args == null ? null : parsedArgs(args); return info; }
private void processComponentBindings0(Component comp) { final ComponentCtrl compCtrl = (ComponentCtrl) comp; final List<String> props = compCtrl.getAnnotatedProperties(); // look every property has annotation for (final Iterator<?> it = props.iterator(); it.hasNext(); ) { final String propName = (String) it.next(); if (isEventProperty(propName)) { processCommandBinding(comp, propName); } else if (FORM_ATTR.equals(propName)) { processFormBindings(comp); } else if (VIEW_MODEL_ATTR.equals(propName)) { // ignore } else if (BINDER_ATTR.equals(propName)) { // ignore } else { processPropertyBindings(comp, propName); } } }
public void redraw(Writer out) throws java.io.IOException { // Note: _tag == null can NOT be handled specially final Execution exec = Executions.getCurrent(); final boolean root = getParent() == null && (getPage().isComplete() || (exec != null && "complete".equals(ExecutionsCtrl.getPageRedrawControl(exec)))); if (exec == null || exec.isAsyncUpdate(null) || (!root && !HtmlPageRenders.isDirectContent(exec))) { super.redraw(out); // renderProperties (assume in zscript) return; } Writer oldout = null; if (exec != null && !HtmlPageRenders.isZkTagsGenerated(exec) && exec.getAttribute(ATTR_TOP_NATIVE) == null) { // need to check topmost native only String tn; if (root || "html".equals(tn = _tag != null ? _tag.toLowerCase() : "") || "body".equals(tn) || "head".equals(tn)) { exec.setAttribute(ATTR_TOP_NATIVE, Boolean.TRUE); oldout = out; out = new StringWriter(); } } out.write(getPrologHalf()); // children Component child = getFirstChild(); if (child == null) { // need to invoke outStandalone to generate response if any (Bug 3009925) // however, it is not required if not root (since others will invoke) if (root) HtmlPageRenders.outStandalone(exec, null, out); } else { if (root) HtmlPageRenders.setDirectContent(exec, true); do { Component next = child.getNextSibling(); if (child instanceof Native || ((ComponentCtrl) child).getExtraCtrl() instanceof DirectContent) { ((ComponentCtrl) child).redraw(out); } else { HtmlPageRenders.setDirectContent(exec, false); HtmlPageRenders.outStandalone(exec, child, out); HtmlPageRenders.setDirectContent(exec, true); } child = next; } while (child != null); } out.write(getEpilogHalf()); if (oldout != null) { exec.removeAttribute(ATTR_TOP_NATIVE); // order: <html><head><zkhead><body> // 1. replace <zkhead/> if found // 2. insert before </head> if found // 3. insert after <body> if found // 4. insert after <html> if found // 5. insert at the end if none of above found final StringBuffer sb = ((StringWriter) out).getBuffer(); if (!HtmlPageRenders.isZkTagsGenerated(exec)) { int jhead = -1, // anchor of header junav = -1, // anchor of unavailable head = -1, // index of <head> heade = -1, // index of </head> html = -1; // index of <html> for (int j = 0, len = sb.length(); (j = sb.indexOf("<", j)) >= 0; ) { ++j; if (jhead < 0 && startsWith(sb, "zkhead", j)) { int l = Strings.indexOf(sb, '>', j) + 1; sb.delete(jhead = --j, l); // jhead found len = sb.length(); } else if (head < 0 && startsWith(sb, "head", j)) { head = Strings.indexOf(sb, '>', j) + 1; } else if (html < 0 && startsWith(sb, "html", j)) { html = Strings.indexOf(sb, '>', j) + 1; } else if (junav < 0 && startsWith(sb, "body", j)) { junav = Strings.indexOf(sb, '>', j) + 1; // junav found break; // done } else if (sb.charAt(j) == '/' && startsWith(sb, "head", ++j)) { heade = j - 2; } } boolean disableUnavailable = false; if (jhead < 0 && ((jhead = heade) < 0) // use </head> if no <zkhead> && ((jhead = head) < 0) // use <head> if no </head> (though unlikely) && ((jhead = junav) < 0) // use <body> if no <head> && ((jhead = html) < 0)) { // use <html> if no <body> if (_tag != null) { final String tn = _tag.toLowerCase(); if ("div".equals(tn) || "span".equals(tn)) { l_loop: for (int j = 0, len = sb.length(); j < len; ++j) switch (sb.charAt(j)) { case '>': disableUnavailable = true; // make output cleaner jhead = j + 1; // found case '=': // it might have something depends on JS case '"': break l_loop; } } } if (jhead < 0) jhead = 0; // insert at head if not found } final String msg = HtmlPageRenders.outUnavailable(exec); // called if disableUnavailable (so it won't be generated later) if (msg != null && !disableUnavailable) { if (junav < 0) { if (html >= 0) junav = sb.lastIndexOf("</html"); } if (junav >= 0) sb.insert(junav < jhead ? jhead : junav, msg); else sb.append(msg); } final String zktags = HtmlPageRenders.outHeaderZkTags(exec, getPage()); if (zktags != null) sb.insert(jhead, zktags); } oldout.write(sb.toString()); } }