/* XOWA: the XOWA Offline Wiki Application Copyright (C) 2012 gnosygnu@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.gfml; import gplx.*; class GfmlPragmaDefault implements GfmlPragma { public String KeyOfPragma() {return "_default";} public void Exec(GfmlBldr bldr, GfmlNde pragmaNde) { List_adp list = Compile(pragmaNde); GfmlDefaultPragma_bgnCmd.ExecList(bldr.TypeMgr().TypeRegy(), bldr.CurNdeFrame().CurDocPos(), list); // bldr.PragmaMgr.EndCmds_add(GfmlDocPos_.up_(bldr.CurNdeFrame.DocPos), GfmlDefaultPragma_endCmd.new_(list)); } @gplx.Internal protected List_adp Compile(GfmlNde pragmaNde) { List_adp list = List_adp_.New(); for (int i = 0; i < pragmaNde.SubHnds().Count(); i++) { GfmlNde subNde = (GfmlNde)pragmaNde.SubHnds().Get_at(i); CompileSubNde(subNde, list); } return list; } @gplx.Internal protected void CompileSubNde(GfmlNde nde, List_adp list) { String typeKey = nde.SubKeys().FetchDataOrNull("typeKey"); if (typeKey == null) throw Err_.new_missing_key("typeKey"); for (int i = 0; i < nde.SubHnds().Count(); i++) { GfmlNde subNde = (GfmlNde)nde.SubHnds().Get_at(i); GfmlDefaultItem item = CompileItem(subNde, typeKey); list.Add(item); } } @gplx.Internal protected GfmlDefaultItem CompileItem(GfmlNde nde, String typeKey) { String key = nde.SubKeys().FetchDataOrFail("key"); GfmlTkn valTkn = nde.SubKeys().FetchDataTknOrNull("val"); return GfmlDefaultItem.new_(typeKey, key, valTkn); } public GfmlType[] MakePragmaTypes(GfmlTypeMakr makr) { makr.MakeSubTypeAsOwner( "_default"); makr.MakeSubTypeAsOwner( "type", "typeKey"); makr.MakeSubTypeAsOwner( "atr", "key", "val"); return makr.Xto_bry(); } public static GfmlPragmaDefault new_() {return new GfmlPragmaDefault();} GfmlPragmaDefault() {} public static final GfmlTkn Default_none = GfmlTkn_.raw_("DEFAULT NONE"); } class GfmlDefaultItem { public String TypeKey() {return typeKey;} private String typeKey; public String Key() {return key;} private String key; public GfmlObj Val() {return val;} GfmlObj val; public GfmlObj ValPrev() {return valPrev;} @gplx.Internal protected GfmlDefaultItem ValPrev_(GfmlObj tkn) {valPrev = tkn; return this;} GfmlObj valPrev; public void Exec_bgn(GfmlType type) { GfmlFld fld = type.SubFlds().Get_by(key); if (fld == null) { // no default defined; create valPrev = GfmlPragmaDefault.Default_none; fld = GfmlFld.new_(true, key, GfmlType_.StringKey).DefaultTkn_(val); type.SubFlds().Add(fld); } else { // default exists; overwrite valPrev = fld.DefaultTkn(); fld.DefaultTkn_(val); } } public void Exec_end(GfmlType type) { GfmlFld fld = type.SubFlds().Get_by(key); if (fld == null) return; // if (fld == null) throw Err_.arg_range_msg_("fatal: could not find fld; typeKey={0} fld={1}", typeKey, key); if (valPrev == GfmlPragmaDefault.Default_none) // drop default; (had been created by pragma) type.SubFlds().Del(fld); else // restore default fld.DefaultTkn_(valPrev); } public static GfmlDefaultItem new_(String typeKey, String key, GfmlTkn val) { GfmlDefaultItem rv = new GfmlDefaultItem(); rv.typeKey = typeKey; rv.key = key; rv.val = val; return rv; } GfmlDefaultItem() {} } class GfmlDefaultPragma_bgnCmd implements GfmlBldrCmd { public String Key() {return "pragma:gfml.default.bgnCmd";} public void Exec(GfmlBldr bldr, GfmlTkn tkn) {ExecList(bldr.TypeMgr().TypeRegy(), bldr.CurNdeFrame().CurDocPos(), list);} @gplx.Internal protected static void ExecList(GfmlTypRegy regy, GfmlDocPos pos, List_adp list) { GfmlType type = GfmlType_.Null; for (Object itemObj : list) { GfmlDefaultItem item = (GfmlDefaultItem)itemObj; if (!String_.Eq(item.TypeKey(), type.Key())) { type = regy.FetchOrNull(item.TypeKey(), pos); if (type == GfmlType_.Null) throw Err_.new_wo_type("default type must exist", "typeKey", item.TypeKey()); } type = type.Clone().DocPos_(pos); regy.Add(type); item.Exec_bgn(type); } } List_adp list; public static GfmlDefaultPragma_bgnCmd new_(List_adp list) { GfmlDefaultPragma_bgnCmd rv = new GfmlDefaultPragma_bgnCmd(); rv.list = list; return rv; } GfmlDefaultPragma_bgnCmd() {} } class GfmlDefaultPragma_endCmd implements GfmlBldrCmd { public String Key() {return "pragma:gfml.default.endCmd";} public void Exec(GfmlBldr bldr, GfmlTkn tkn) {ExecList(bldr.TypeMgr().TypeRegy(), list);} public static void ExecList(GfmlTypRegy regy, List_adp list) { GfmlType type = GfmlType_.Null; for (Object itemObj : list) { GfmlDefaultItem item = (GfmlDefaultItem)itemObj; if (!String_.Eq(item.TypeKey(), type.Key())) { type = regy.FetchOrNull(item.TypeKey()); if (type == GfmlType_.Null) throw Err_.new_wo_type("fatal: default type must exist", "typeKey", item.TypeKey()); } item.Exec_end(type); } } List_adp list; public static GfmlDefaultPragma_endCmd new_(List_adp list) { GfmlDefaultPragma_endCmd rv = new GfmlDefaultPragma_endCmd(); rv.list = list; return rv; } GfmlDefaultPragma_endCmd() {} }