Example #1
0
 public GfoMsg CloneNew() {
   GfoMsg_base rv = new GfoMsg_base().ctor_(key, parse);
   if (args != null) {
     rv.args = List_adp_.New();
     for (int i = 0; i < args.Count(); i++) rv.args.Add(args.Get_at(i));
   }
   if (subs != null) {
     rv.subs = List_adp_.New();
     for (int i = 0; i < args.Count(); i++) {
       GfoMsg sub = (GfoMsg) args.Get_at(i);
       rv.subs.Add(sub.CloneNew()); // NOTE: recursion
     }
   }
   return rv;
 }
Example #2
0
  public static void Find_pages(List_adp rv, Xowe_wiki wiki, Dpl_itm itm) {
    rv.Clear();
    List_adp includes = itm.Ctg_includes();
    if (includes == null) return;
    int includes_len = includes.Count();
    Ordered_hash old_regy = Ordered_hash_.New(),
        new_regy = Ordered_hash_.New(),
        cur_regy = Ordered_hash_.New();
    Xodb_load_mgr load_mgr = wiki.Db_mgr().Load_mgr();
    Xowd_page_itm tmp_page = new Xowd_page_itm();
    Int_obj_ref tmp_id = Int_obj_ref.New_zero();
    List_adp del_list = List_adp_.New();
    int ns_filter = itm.Ns_filter();
    Ordered_hash exclude_pages = Ordered_hash_.New();
    Find_excludes(exclude_pages, wiki, load_mgr, tmp_page, tmp_id, itm.Ctg_excludes());

    for (int i = 0; i < includes_len; i++) { // loop over includes
      byte[] include = (byte[]) includes.Get_at(i);
      cur_regy.Clear();
      del_list.Clear();
      Find_pages_in_ctg(cur_regy, wiki, load_mgr, tmp_page, tmp_id, include);
      Del_old_pages_not_in_cur(i, tmp_id, old_regy, cur_regy, del_list);
      Add_cur_pages_also_in_old(i, tmp_id, old_regy, cur_regy, new_regy, exclude_pages, ns_filter);
      old_regy = new_regy;
      new_regy = Ordered_hash_.New();
    }
    int pages_len = old_regy.Count();
    for (int i = 0; i < pages_len; i++) { // loop over old and create pages
      Int_obj_ref old_id = (Int_obj_ref) old_regy.Get_at(i);
      rv.Add(new Xowd_page_itm().Id_(old_id.Val()));
    }
    wiki.Db_mgr().Load_mgr().Load_by_ids(Cancelable_.Never, rv, 0, pages_len);
    rv.Sort_by(Xowd_page_itm_sorter.IdAsc);
  }
Example #3
0
 public void Test_search(String search_word_str, int... expd) {
   Xowe_wiki wiki = bldr_fxt.Wiki();
   List_adp rv = List_adp_.new_();
   byte[] search_word_bry = Bry_.new_a7(search_word_str);
   wiki.Db_mgr_as_sql().Load_mgr().Load_search(Cancelable_.Never, rv, search_word_bry, 100);
   Tfds.Eq_ary(expd, Xto_int_ary(rv));
 }
Example #4
0
 public GfoMsg Args_ovr(String k, Object v) {
   if (args == null) args = List_adp_.New();
   for (int i = 0; i < args.Count(); i++) {
     Keyval kv = (Keyval) args.Get_at(i);
     if (String_.Eq(k, kv.Key())) {
       kv.Val_(v);
       return this;
     }
   }
   args.Add(Keyval_.new_(k, v));
   return this;
 }
Example #5
0
 int[] Xto_int_ary(Xoctg_data_ctg ctg) {
   List_adp list = List_adp_.new_();
   byte tid_max = Xoa_ctg_mgr.Tid__max;
   for (byte tid = 0; tid < tid_max; tid++) {
     Xoctg_idx_mgr grp = ctg.Grp_by_tid(tid);
     if (grp == null) continue;
     int len = grp.Itms_len();
     for (int i = 0; i < len; i++) {
       Xoctg_idx_itm itm = grp.Itms_get_at(i);
       list.Add(itm.Id());
     }
   }
   return (int[]) list.To_ary_and_clear(int.class);
 }
Example #6
0
  public static GfoMsg chain_(GfoMsg owner, String key) {
    GfoMsg sub = owner;
    List_adp list = List_adp_.New();
    list.Add(sub.Key());
    while (sub != null) {
      if (sub.Subs_count() == 0) break;
      sub = (GfoMsg) sub.Subs_getAt(0);
      list.Add(sub.Key());
    }
    list.Add(key);

    GfoMsg root = GfoMsg_.new_parse_((String) list.Get_at(0));
    GfoMsg cur = root;
    for (int i = 1; i < list.Count(); i++) {
      String k = (String) list.Get_at(i);
      GfoMsg mm = GfoMsg_.new_parse_(k);
      cur.Subs_add(mm);
      cur = mm;
    }
    return root;
  }
Example #7
0
 public static int[] Ary_get(Xow_domain_itm domain_itm, boolean wmf) {
   if (wmf && domain_itm != null && domain_itm.Domain_type().Tid() != Xow_domain_tid_.Tid__home)
     return Ary_wmf;
   if (Ary_nonwmf == null) {
     List_adp list = List_adp_.New();
     int len = Ary_wmf.length;
     for (int i = 0; i < len; ++i) {
       list.Add(Ary_wmf[i]);
     }
     list.Add_many(
         Xol_kwd_grp_.Id_strx_len,
         Xol_kwd_grp_.Id_strx_pos,
         Xol_kwd_grp_.Id_strx_rpos,
         Xol_kwd_grp_.Id_strx_sub,
         Xol_kwd_grp_.Id_strx_count,
         Xol_kwd_grp_.Id_strx_replace,
         Xol_kwd_grp_.Id_strx_explode,
         Xol_kwd_grp_.Id_strx_urldecode,
         Xol_kwd_grp_.Id_new_window_link);
     Ary_nonwmf = (int[]) list.To_ary_and_clear(int.class);
   }
   return Ary_nonwmf;
 }
Example #8
0
public class Mem_tbl {
  private final List_adp where_rows = List_adp_.New();
  private final Hash_adp autonum_hash = Hash_adp_.New();

  public Mem_tbl(Dbmeta_tbl_itm meta) {
    this.meta = meta;
  }

  public Dbmeta_tbl_itm Meta() {
    return meta;
  }

  private final Dbmeta_tbl_itm meta;
  public final List_adp rows = List_adp_.New();

  public int Insert(Mem_stmt stmt) {
    Mem_row itm = new Mem_row();
    Dbmeta_fld_mgr flds = meta.Flds();
    int len = flds.Len();
    for (int i = 0; i < len; ++i) {
      Dbmeta_fld_itm fld = flds.Get_at(i);
      String fld_name = fld.Name();
      Object val = fld.Autonum() ? Autonum_calc(fld_name) : stmt.Args_get_by(fld_name);
      if (val == null) continue; // NOTE: allow Bulk_insert from test to skip filds
      itm.Set_by(fld_name, val);
    }
    rows.Add(itm);
    return 1;
  }

  private int Autonum_calc(String name) {
    Int_obj_ref autonum_itm = (Int_obj_ref) autonum_hash.Get_by(name);
    if (autonum_itm == null) {
      autonum_itm = Int_obj_ref.New(0);
      autonum_hash.Add(name, autonum_itm);
    }
    return autonum_itm.Val_add();
  }

  public int Update(Mem_stmt stmt) {
    Db_qry_update qry = (Db_qry_update) stmt.Qry();
    Criteria where_crt = qry.Where();
    if (where_crt == null) where_crt = Criteria_.All;
    Mem_stmt_args_.Fill(stmt.Stmt_args(), where_crt);
    Select_rows_where(where_rows, stmt, where_crt);
    int where_rows_len = where_rows.Count();
    String[] update_cols = qry.Cols_for_update();
    int update_cols_len = update_cols.length;
    for (int i = 0; i < where_rows_len; ++i) {
      Mem_row itm = (Mem_row) where_rows.Get_at(i);
      for (int j = 0; j < update_cols_len; ++j) itm.Set_by(update_cols[j], stmt.Args_get_at(j));
    }
    return where_rows_len;
  }

  public int Delete(Mem_stmt stmt) {
    Db_qry_delete qry = (Db_qry_delete) stmt.Qry();
    Mem_stmt_args_.Fill(stmt.Stmt_args(), qry.Where());
    Select_rows_where(where_rows, stmt, qry.Where());
    int where_rows_len = where_rows.Count();
    for (int i = 0; i < where_rows_len; ++i) {
      Mem_row itm = (Mem_row) where_rows.Get_at(i);
      rows.Del(itm);
    }
    return where_rows_len;
  }

  public Db_rdr Select(Mem_stmt stmt) {
    String[] select = null;
    Criteria where = null;
    Db_qry__select_in_tbl qry = Db_qry__select_in_tbl.as_(stmt.Qry());
    if (qry == null) {
      Db_qry__select_cmd qry2 = (Db_qry__select_cmd) stmt.Qry();
      select = To_str_ary(qry2.Cols().Flds);
      where = qry2.Where_itm().Root;
    } else {
      select = qry.Select_flds();
      where = qry.Where();
    }
    Mem_stmt_args_.Fill(stmt.Stmt_args(), where);
    Select_rows_where(where_rows, stmt, where);
    return new Mem_rdr(select, (Mem_row[]) where_rows.To_ary_and_clear(Mem_row.class));
  }

  private String[] To_str_ary(Sql_select_fld_list flds) {
    int len = flds.Len();
    String[] rv = new String[len];
    for (int i = 0; i < len; ++i) rv[i] = flds.Get_at(i).Fld;
    return rv;
  }

  private void Select_rows_where(List_adp rv, Mem_stmt stmt, Criteria crt) {
    rv.Clear();
    int rows_len = rows.Count();
    for (int i = 0; i < rows_len; ++i) {
      Mem_row itm = (Mem_row) rows.Get_at(i);
      if (crt.Matches(itm)) rv.Add(itm);
    }
  }
}
Example #9
0
 @Override
 protected Object ReadOr(String k, Object defaultOr) {
   if (args == null) args = List_adp_.New();
   args.Add(Keyval_.new_(k, defaultOr));
   return defaultOr;
 }
Example #10
0
 public GfoMsg Add(String k, Object v) {
   if (args == null) args = List_adp_.New();
   args.Add(Keyval_.new_(k, v));
   return this;
 }
Example #11
0
 public GfoMsg Subs_add(GfoMsg m) {
   if (subs == null) subs = List_adp_.New();
   subs.Add(m);
   return this;
 }
Example #12
0
class Xow_search_scanner {
  private final List_adp tkns = List_adp_.new_();
  private byte[] src;
  private int src_len, pos, txt_bgn;
  private final Ordered_hash tmp_list = Ordered_hash_.new_();
  private final Bry_bfr tmp_bfr = Bry_bfr.new_();

  public Xow_search_tkn[] Scan(byte[] src) {
    this.src = src;
    this.src_len = src.length;
    tkns.Clear();
    pos = 0;
    txt_bgn = -1;
    while (pos < src_len) {
      byte cur_b = src[pos];
      Object cur_obj = trie.Match_bgn_w_byte(cur_b, src, pos, src_len);
      if (cur_obj == null) { // text character
        if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
        ++pos;
      } else { // AND, OR, (, ), -, \s, "
        int pos_end = trie.Match_pos();
        byte cur_tid = ((Byte_obj_val) cur_obj).Val();
        if (Cur_join_is_word(cur_tid, pos_end))
          continue; // ignore words containing "and", "or"; EX: "random"; "for"
        if (txt_bgn != -1) { // pending word; create
          Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos);
          txt_bgn = -1;
        }
        switch (cur_tid) {
          case Xow_search_tkn.Tid_space: // discard spaces
            pos = Bry_finder.Find_fwd_while(src, pos, src_len, Byte_ascii.Space);
            break;
          case Xow_search_tkn.Tid_quote: // find end quote and add as word
            int quote_bgn = pos + 1;
            int quote_end = Bry_finder.Find_fwd(src, Byte_ascii.Quote, quote_bgn, src_len);
            if (quote_end == Bry_.NotFound)
              throw Err_.new_fmt_("could not find end quote: {0}", String_.new_u8(src));
            Tkns_add_word(Xow_search_tkn.Tid_word_quoted, quote_bgn, quote_end);
            pos = quote_end + 1; // +1 to place after quote
            break;
          case Xow_search_tkn.Tid_not:
            Tkns_add_word(Xow_search_tkn.Tid_not, pos, pos_end);
            pos = pos_end;
            break;
          case Xow_search_tkn.Tid_paren_bgn:
          case Xow_search_tkn.Tid_paren_end:
          case Xow_search_tkn.Tid_and:
          case Xow_search_tkn.Tid_or:
            tkns.Add(new_tkn(cur_tid, pos, pos_end));
            pos = pos_end;
            break;
          default:
            throw Err_.unhandled(cur_tid);
        }
      }
    }
    if (txt_bgn != -1) { // pending word; create
      Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos);
      txt_bgn = -1;
    }
    return (Xow_search_tkn[]) tkns.To_ary_and_clear(Xow_search_tkn.class);
  }

  private boolean Cur_join_is_word(
      byte cur_tid,
      int
          pos_end) { // extra logic to handle and / or occuring in unquoted strings; EX: "random";
                     // "for"
    switch (cur_tid) {
      default:
        return false; // only look at AND, OR, -
      case Xow_search_tkn.Tid_and:
      case Xow_search_tkn.Tid_or:
      case Xow_search_tkn.Tid_not:
        break;
    }
    boolean join_is_word = true;
    if (txt_bgn == -1) { // no pending word;
      if (cur_tid == Xow_search_tkn.Tid_not)
        return false; // NOT is only operator if no pending tkn; EX: -abc -> NOT abc; a-b -> a-b
      byte nxt_b = pos_end < src_len ? src[pos_end] : Byte_ascii.Nil;
      Object nxt_obj = trie.Match_bgn_w_byte(nxt_b, src, pos_end, src_len);
      if (nxt_obj == null) // next tkn is text; join must be word
      join_is_word = true;
      else { // next tkn is tkn
        byte nxt_tid = ((Byte_obj_val) nxt_obj).Val();
        switch (nxt_tid) {
          case Xow_search_tkn.Tid_space:
          case Xow_search_tkn.Tid_quote:
          case Xow_search_tkn.Tid_paren_bgn:
          case Xow_search_tkn.Tid_paren_end:
            join_is_word =
                false; // next tkn is sym; and/or is not word; EX: a AND ; a AND"b"; a AND(b)
            break;
          case Xow_search_tkn.Tid_not:
          case Xow_search_tkn.Tid_and:
          case Xow_search_tkn.Tid_or:
            join_is_word = true; // next tkn is and or not; and/or is word; EX: andor; oror; or-abc;
            break;
          default:
            throw Err_.unhandled(cur_tid);
        }
      }
    } else { // pending word; cur join must be word; EX: "grand": "and" invoked and "gr" pending
      join_is_word = true;
    }
    if (join_is_word) {
      if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
      pos = pos_end;
      return true;
    }
    if (txt_bgn != -1) {
      Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos); // create word
      txt_bgn = -1;
    }
    return false;
  }

  private void Tkns_add_word(byte tid, int src_bgn, int src_end) {
    if (tkns.Count() > 0) { // at least 1 tkn; check for "auto-and"
      Xow_search_tkn last_tkn = (Xow_search_tkn) tkns.Get_at_last();
      if (last_tkn.Tid()
          == Xow_search_tkn.Tid_word) // previous tkn is word; auto "AND" words; EX: A B -> A AND B
      tkns.Add(Xow_search_tkn.new_bry(Xow_search_tkn.Tid_and, Bry_and));
    }
    if (tid
        == Xow_search_tkn
            .Tid_word) { // if word has symbol, convert to quoted; EX: a-b should become "a-b";
                         // otherwise searcher would search for a single word a-b
      byte[] cur_word = Bry_.Mid(src, src_bgn, src_end);
      byte[][] words =
          gplx.xowa.bldrs.cmds.texts.Xob_search_base.Split_ttl_into_words(
              null, tmp_list, tmp_bfr, cur_word);
      int words_len = words.length;
      if (words_len == 1 // only one word
          && !Bry_.Eq(words[0], cur_word) // split word not same as raw
          && Bry_finder.Find_fwd(cur_word, Byte_ascii.Star) == -1 // no asterisk
      ) {
        tkns.Add(Xow_search_tkn.new_bry(tid, words[0]));
        return;
      }
      if (words.length > 1) // multiple words; add as quoted-term; EX: "a-b"
      tid = Xow_search_tkn.Tid_word_quoted;
    }
    tkns.Add(new_tkn(tid, src_bgn, src_end));
  }

  private Xow_search_tkn new_tkn(byte tid, int val_bgn, int val_end) {
    return Xow_search_tkn.new_pos(tid, val_bgn, val_end);
  }

  private static final byte[] Bry_and = Bry_.new_a7("AND");
  private static final Btrie_slim_mgr trie =
      Btrie_slim_mgr.ci_ascii_() // NOTE:ci.ascii:OR / AND only
          .Add_str_byte(" ", Xow_search_tkn.Tid_space)
          .Add_str_byte("\"", Xow_search_tkn.Tid_quote)
          .Add_str_byte("-", Xow_search_tkn.Tid_not)
          .Add_str_byte("(", Xow_search_tkn.Tid_paren_bgn)
          .Add_str_byte(")", Xow_search_tkn.Tid_paren_end)
          .Add_str_byte("or", Xow_search_tkn.Tid_or)
          .Add_str_byte("and", Xow_search_tkn.Tid_and);
}
Example #13
0
	public Bry_fmtr Compile() {
		synchronized (this) {	// THREAD: DATE:2015-04-29
			Bry_bfr lkp_bfr = Bry_bfr.new_(16);
			int fmt_len = fmt.length; int fmt_end = fmt_len - 1; int fmt_pos = 0;
			byte[] trg_bry = new byte[fmt_len]; int trg_pos = 0;
			boolean lkp_is_active = false, lkp_is_numeric = true;
			byte nxt_byte, tmp_byte;
			List_adp list = List_adp_.new_();
			fmt_args_exist = false;
			while (true) {
				if (fmt_pos > fmt_end) break;
				byte cur_byte = fmt[fmt_pos];
				if		(lkp_is_active) {
					if (cur_byte == char_arg_end) {
						if (lkp_is_numeric)
							list.Add(Bry_fmtr_itm.arg_(lkp_bfr.XtoInt(0) - baseInt));
						else {
							byte[] key_fmt = lkp_bfr.Xto_bry();
							Object idx_ref = keys.Get_by(Bry_obj_ref.new_(key_fmt));
							if (idx_ref == null) {
								int lkp_bfr_len = lkp_bfr.Len();
								byte[] lkp_bry = lkp_bfr.Bfr();
								trg_bry[trg_pos++] = char_escape;
								trg_bry[trg_pos++] = char_arg_bgn;
								for (int i = 0; i < lkp_bfr_len; i++)
									trg_bry[trg_pos++] = lkp_bry[i];
								trg_bry[trg_pos++] = char_arg_end;
							}
							else {
								list.Add(Bry_fmtr_itm.arg_(((Int_obj_val)idx_ref).Val() - baseInt));
							}
						}
						lkp_is_active = false;
						lkp_bfr.Clear();
						fmt_args_exist = true;
					}
					else {
						lkp_bfr.Add_byte(cur_byte);
						switch (cur_byte) {
							case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
							case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
								break;
							default:
								lkp_is_numeric = false;
								break;
						}
					}
					fmt_pos += 1;
				}
				else if	(cur_byte == char_escape) {
					if (fmt_pos == fmt_end) {
						if (fail_when_invalid_escapes)
							throw Err_.new_("escape char encountered but no more chars left");
						else {
							trg_bry[trg_pos] = cur_byte;
							break;
						}
					}
					nxt_byte = fmt[fmt_pos + 1];
					if (nxt_byte == char_arg_bgn) {
						if (trg_pos > 0) {list.Add(Bry_fmtr_itm.dat_(trg_bry, trg_pos)); trg_pos = 0;}	// something pending; add it to list
						int eval_lhs_bgn = fmt_pos + 2;
						if (eval_lhs_bgn < fmt_len && fmt[eval_lhs_bgn] == char_eval_bgn) {	// eval found
							fmt_pos = Compile_eval_cmd(fmt, fmt_len, eval_lhs_bgn, list);
							continue;
						}
						else {
							lkp_is_active = true;
							lkp_is_numeric = true;
						}
					}
					else {	// ~{0}; ~~ -> ~; ~n -> newLine; ~t -> tab
						if		(nxt_byte == char_escape)		tmp_byte = char_escape;
						else if	(nxt_byte == char_escape_nl)	tmp_byte = Byte_ascii.Nl;
						else if (nxt_byte == char_escape_tab)	tmp_byte = Byte_ascii.Tab;
						else {
							if (fail_when_invalid_escapes) throw Err_.new_("unknown escape code").Add("code", Char_.XbyInt(nxt_byte)).Add("fmt_pos", fmt_pos + 1);
							else
								tmp_byte = cur_byte;
						}
						trg_bry[trg_pos++] = tmp_byte;
					}
					fmt_pos += 2;
				}
				else {
					trg_bry[trg_pos++] = cur_byte;
					fmt_pos += 1;
				}
			}
			if (lkp_is_active) throw Err_.new_("idx mode not closed");
			if (trg_pos > 0) {list.Add(Bry_fmtr_itm.dat_(trg_bry, trg_pos)); trg_pos = 0;}
			itms = (Bry_fmtr_itm[])list.To_ary(Bry_fmtr_itm.class);
			itms_len = itms.length;
			return this;
		}
	}
Example #14
0
public class Dpl_xnde implements Xox_xnde {
  private Dpl_itm itm = new Dpl_itm();
  private List_adp pages = List_adp_.New();

  public void Xatr__set(
      Xowe_wiki wiki,
      byte[] src,
      Mwh_atr_itm xatr,
      Object xatr_id_obj) {} // NOTE: <dynamicPageList> has no attributes

  public void Xtn_parse(
      Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
    itm.Parse(wiki, ctx, ctx.Page().Ttl().Full_txt_w_ttl_case(), src, xnde);
    Dpl_page_finder.Find_pages(pages, wiki, itm);
    if (itm.Sort_ascending() != Bool_.__byte) pages.Sort_by(new Dpl_page_sorter(itm));
  }

  public void Xtn_write(
      Bry_bfr bfr,
      Xoae_app app,
      Xop_ctx ctx,
      Xoh_html_wtr html_wtr,
      Xoh_wtr_ctx hctx,
      Xoae_page wpg,
      Xop_xnde_tkn xnde,
      byte[] src) {
    Xowe_wiki wiki = ctx.Wiki();
    Dpl_html_data html_mode = Dpl_html_data.new_(Dpl_itm_keys.Key_unordered);
    int itms_len = pages.Count();
    if (itms_len == 0) {
      if (!itm.Suppress_errors()) bfr.Add_str_a7("No pages meet these criteria.");
      return;
    }
    int itms_bgn = 0;
    if (itm.Offset() != Int_.Min_value) {
      itms_bgn = itm.Offset();
    }
    if (itm.Count() != Int_.Min_value && itms_bgn + itm.Count() < itms_len) {
      itms_len = itms_bgn + itm.Count();
    }
    boolean show_ns = itm.Show_ns();
    Bry_bfr tmp_bfr = Bry_bfr_.Get();
    Xop_amp_mgr amp_mgr = wiki.Appe().Parser_amp_mgr();
    try {
      bfr.Add(html_mode.Grp_bgn()).Add_byte_nl();
      for (int i = itms_bgn; i < itms_len; i++) {
        Xowd_page_itm page = (Xowd_page_itm) pages.Get_at(i);
        Xoa_ttl ttl = Xoa_ttl.Parse(wiki, page.Ns_id(), page.Ttl_page_db());
        byte[] ttl_page_txt = show_ns ? ttl.Full_txt_w_ttl_case() : ttl.Page_txt();
        if (ttl_page_txt == null)
          continue; // NOTE: apparently DynamicPageList allows null pages; DATE:2013-07-22
        switch (html_mode.Tid()) {
          case Dpl_html_data.Tid_list_ul:
          case Dpl_html_data.Tid_list_ol:
            bfr.Add(Xoh_consts.Space_2).Add(html_mode.Itm_bgn()).Add(Gfh_bldr_.Bry__a_lhs_w_href);
            bfr.Add_str_a7("/wiki/")
                .Add(Gfo_url_encoder_.Href.Encode(ttl.Full_db()))
                .Add_byte_quote(); // NOTE: Full_db to encode spaces as underscores;
                                   // PAGE:en.q:Wikiquote:Speedy_deletions DATE:2016-01-19
            Gfh_atr_.Add(
                bfr,
                Gfh_atr_.Bry__title,
                Xoh_html_wtr_escaper.Escape(
                    amp_mgr,
                    tmp_bfr,
                    ttl
                        .Full_txt_w_ttl_case())); // NOTE: Full_txt b/c title always includes ns,
                                                  // even if show_ns is off;
                                                  // PAGE:en.b:Wikibooks:WikiProject DATE:2016-01-20
            if (itm.No_follow()) bfr.Add(Bry_nofollow);
            bfr.Add_byte(Byte_ascii.Gt);
            Xoh_html_wtr_escaper.Escape(
                amp_mgr, bfr, ttl_page_txt, 0, ttl_page_txt.length, false, false);
            bfr.Add(Gfh_bldr_.Bry__a_rhs).Add(html_mode.Itm_end()).Add_byte_nl();
            // TODO_OLD:
            // lnki_wtr.Clear().Href_wiki_(ttl).Title_(ttl).Nofollow_().Write_head(bfr).Write_text(bfr).Write_tail(bfr)
            break;
          default:
            break;
        }
      }
      bfr.Add(html_mode.Grp_end()).Add_byte_nl();
    } finally {
      tmp_bfr.Mkr_rls();
    }
  }

  private static byte[] Bry_nofollow = Bry_.new_a7(" rel=\"nofollow\"");
}