indexing description: "Objects that ..." author: "" date: "$Date$" revision: "$Revision$" class WIKIBOOK_TOOL inherit WIKI_WITH_CHILD KL_SHARED_FILE_SYSTEM create make feature {NONE} -- Initialization make (dn: STRING) local fn: FILE_NAME f: FILE k,v: STRING lst: LIST [WIKIPAGE] use_io: BOOLEAN do root := dn.twin process create max_depth_info print_book (pages) get_book_conflicts if use_io then f := io.output else create fn.make_from_string (root) fn.set_file_name ("book.log") create {RAW_FILE} f.make (fn) f.create_read_write end f.put_string ("== Log for book ==%N") f.put_string ("* source: " + root + "%N") f.put_string ("* pages: " + book_pages.count.out + "%N") f.put_string ("* depth: " + max_depth_info.depth.out + " reached " + max_depth_info.nb.out + " time(s) %N") f.put_string ("* title conflict(s): " + book_conflicts.count.out + "%N") if book_conflicts.count > 0 then from book_conflicts.start until book_conflicts.after loop k := book_conflicts.key_for_iteration f.put_string ("# [" + k + "]%N") lst := book_conflicts.item_for_iteration from lst.start until lst.after loop f.put_string ("#* " + lst.item.src ) f.put_string (" : %"" + lst.item.title + "%"") -- f.put_string (" : %"" + lst.item.title + "%"") f.put_new_line lst.forth end book_conflicts.forth end end f.put_new_line if not use_io then f.close end end new_book_index (i: INTEGER): FILE local fn: FILE_NAME do create fn.make_from_string (root) if i = 0 then fn.set_file_name ("book.index") else fn.set_file_name ("book" + i.out + ".index") end create {RAW_FILE} Result.make (fn) Result.create_read_write end print_book (pge: LIST [WIKIPAGE]) is local d: TUPLE [nb: INTEGER; i: INTEGER; h: LIST [STRING]] cl_output: CELL [FILE] output: FILE do create d d.nb := 0 d.i := 0 d.h := create {ARRAYED_LIST [STRING]}.make (10) create cl_output.put (new_book_index (0)) imp_print_book (cl_output, pge, 0, d) cl_output.item.put_new_line cl_output.item.close end imp_print_book (cl_output: CELL [FILE]; pge: LIST [WIKIPAGE]; dep: INTEGER; prog: TUPLE [nb: INTEGER; i: INTEGER; h: LIST [STRING]]) is local d: INTEGER output: FILE t, o: STRING p: WIKIPAGE i: INTEGER do create o.make_filled (' ', dep) output := cl_output.item if dep = 0 then t := o + "[0:Book] Documentation" t.append_character ('%N') t.append_string (o + " !src=book") t.append_character ('%N') output.put_string (t) end from pge.start i := 0 until pge.after loop output := cl_output.item p := pge.item d := p.depth check same_depth: d = dep end check not p.failed end notify_page (dep, p) prog.nb := prog.nb + 1 if prog.nb \\ 225 = 0 then output.put_new_line output.flush output.close prog.i := prog.i + 1 cl_output.replace (new_book_index (prog.i)) output := cl_output.item from prog.h.start until prog.h.after loop output.put_string ("@") output.put_string (prog.h.item) prog.h.forth end end if d = 0 then d := 1 o.append_character (' ') end t := o + "[" + d.out + ":" + p.base_id + ":" + i.out + "] " + p.title t.append_character ('%N') t.append_string (o + " !src=" + p.src ) t.append_character ('%N') -- t.append_string (o + " !path=" + p.path) -- t.append_character ('%N') output.put_string (t) if p.pages /= Void and then not p.pages.is_empty then prog.h.extend (t) -- notify_page (dep + 1, p.pages.first) imp_print_book (cl_output, p.pages, dep + 1, prog) prog.h.finish; prog.h.remove end i := i + 1 pge.forth end end feature -- Access root: STRING -- Root directory book_conflicts: HASH_TABLE [LIST [WIKIPAGE], STRING] -- indexed by WIKIPAGE.title book_by_titles: HASH_TABLE [LIST [WIKIPAGE], STRING] -- indexed by WIKIPAGE.title book_pages: like pages max_depth_info: TUPLE [depth: INTEGER; path: STRING; nb: INTEGER] feature -- Measurement notify_page (dep: INTEGER; p: WIKIPAGE) require -- same_dep: dep = p.depth do if dep > max_depth_info.depth then max_depth_info.depth := dep max_depth_info.nb := 1 elseif dep = max_depth_info.depth then max_depth_info.nb := max_depth_info.nb + 1 end end get_book_conflicts local do from create book_conflicts.make (100) book_by_titles.start until book_by_titles.after loop if book_by_titles.item_for_iteration.count > 1 then book_conflicts.put (book_by_titles.item_for_iteration.twin, book_by_titles.key_for_iteration) end book_by_titles.forth end end feature -- Basic operations process local do create book_pages.make (1500) create book_by_titles.make (30) book_by_titles.compare_objects get_pages (root, "Book", Current, 1) end add_page_entry (wpg: WIKIPAGE) local t: STRING lst: LIST [WIKIPAGE] do book_pages.extend (wpg) t := wpg.title.as_lower t.left_adjust t.right_adjust if book_by_titles.has_key (t) then lst := book_by_titles.found_item else create {ARRAYED_LIST [WIKIPAGE]} lst.make (3) book_by_titles.put (lst, t) end lst.extend (wpg) end feature {NONE} -- Implementation path_from_root (fn: STRING): STRING require valid_fn: fn.substring (1, root.count).is_case_insensitive_equal (root) do create Result.make_from_string (fn) Result.remove_head (root.count + 1) end get_pages (dn: STRING; a_folder_id: STRING; a_parent: WIKI_WITH_CHILD; dep: INTEGER) require a_parent_attached: a_parent /= Void local d: KL_DIRECTORY fn: FILE_NAME wpg_index: like wikifile_details do create d.make (dn) if d.exists and then d.is_readable then --| First check for the index.xml create fn.make_from_string (dn) fn.set_file_name ("index.wiki") if file_system.file_exists (fn.string) then wpg_index := wikifile_details (fn.string) check wpg_index /= Void and then wpg_index.is_index end wpg_index.depth := dep - 1 wpg_index.force_base_id (a_folder_id) --| Set base_id to folder's id add_page_entry (wpg_index) a_parent.add_page (wpg_index) d.do_all (agent (idn: STRING; ifn: STRING; a_par: WIKI_WITH_CHILD; idep: INTEGER) local l_fn: FILE_NAME wpg: WIKIPAGE do create l_fn.make_from_string (idn) l_fn.set_file_name (ifn) if file_system.is_file_readable (l_fn) then wpg := wikifile_details (l_fn.string) if wpg /= Void and then not wpg.failed and then wpg.title /= Void and then not wpg.is_index --| Already handled by wpg_index then wpg.depth := idep add_page_entry (wpg) a_par.add_page (wpg) end elseif file_system.is_directory_readable (l_fn) then get_pages (l_fn.string, ifn.twin, a_par, idep + 1) end end(dn, ?, wpg_index, dep) ) end end end wikifile_local_id (fn: STRING): STRING is -- Return wikifile_local_id which is the basename, without the extension -- if this is a wikifile do create Result.make_from_string (file_system.basename (fn)) if Result.count > 4 and then Result.substring (Result.count - 4, Result.count).is_equal (once ".wiki") then Result.remove_tail (5) else Result := Void end end wikifile_details (a_fn: STRING): WIKIPAGE local f: PLAIN_TEXT_FILE line: STRING done: BOOLEAN p: INTEGER k,v: STRING do line := wikifile_local_id (a_fn) if line /= Void then create Result.make (line, path_from_root (a_fn)) create f.make (a_fn) if f.exists and then f.is_readable then f.open_read from f.start until done or f.exhausted or f.end_of_file loop f.read_line line := f.last_string if line.count > 1 and then line.item (1) = '#' then p := line.index_of ('=', 2) if p > 0 then k := line.substring (2, p - 1) if k.is_empty or k.has (' ') or k.has ('%T') then k := Void done := True --| We scan a generated file, and we are sure of the format beginning else v := line.substring (p + 1, line.count) end if k /= Void and v /= Void then if k.is_equal (once "src") then Result.src := v elseif k.is_equal (once "title") then Result.title := v elseif k.is_equal (once "tags") then Result.tags := v else print ("Error .. unknown settings [" + k + "=" + v + "] %N") Result.failed := True end end else done := True end else done := True end end f.close else Result.failed := True end end end end