internal void ApplyCacheTemplate(string elemName,
                                         string class_value,
                                         BoxSpec currentBoxSpec,
                                         BoxSpec parentSpec)
        {
            //1. tag name key
            int tagNameKey = ustrTable.AddStringIfNotExist(elemName);
            //2. class name key
            int classNameKey = 0;

            if (class_value != null)
            {
                classNameKey = ustrTable.AddStringIfNotExist(class_value);
            }
            //find cache in the same level
            var templateKey = new CssTemplateKey(tagNameKey, classNameKey);
            //BoxSpec boxTemplate = SearchUpBoxSpec(templateKey);
            BoxSpec boxTemplate = null;

            if (boxTemplate != null)
            {
                BoxSpec.CloneAllStyles(currentBoxSpec, boxTemplate);
            }
            else
            {
                //create template for specific key
                boxTemplate = new BoxSpec();
                //copy current spec to boxTemplate
                BoxSpec.CloneAllStyles(boxTemplate, currentBoxSpec);
                //***
                //----------------------------
                //1. tag name
                CssRuleSetGroup ruleGroup = activeSheet.GetRuleSetForTagName(elemName);
                if (ruleGroup != null)
                {
                    //currentBoxSpec.VersionNumber++;
                    foreach (WebDom.CssPropertyDeclaration decl in ruleGroup.GetPropertyDeclIter())
                    {
                        SpecSetter.AssignPropertyValue(boxTemplate, parentSpec, decl);
                    }
                }
                //----------------------------
                //2. series of class
                if (class_value != null)
                {
                    //currentBoxSpec.VersionNumber++;
                    string[] classNames = class_value.Split(_whiteSplitter, StringSplitOptions.RemoveEmptyEntries);
                    int      j          = classNames.Length;
                    if (j > 0)
                    {
                        for (int i = 0; i < j; ++i)
                        {
                            CssRuleSetGroup ruleSetGroup = activeSheet.GetRuleSetForClassName(classNames[i]);
                            if (ruleSetGroup != null)
                            {
                                foreach (var propDecl in ruleSetGroup.GetPropertyDeclIter())
                                {
                                    SpecSetter.AssignPropertyValue(boxTemplate, parentSpec, propDecl);
                                }
                                //---------------------------------------------------------
                                //find subgroup for more specific conditions
                                int subgroupCount = ruleSetGroup.SubGroupCount;
                                for (int m = 0; m < subgroupCount; ++m)
                                {
                                    //find if selector condition match with this box
                                    CssRuleSetGroup ruleSetSubGroup = ruleSetGroup.GetSubGroup(m);
                                    var             selector        = ruleSetSubGroup.OriginalSelector;
                                }
                            }
                        }
                    }
                }

                boxTemplate.Freeze();
                //this.CacheBoxSpec(templateKey, boxTemplate);
                boxTemplate.IsTemplate = true;
                //copy back from template to currentBoxSpec
                BoxSpec.CloneAllStyles(currentBoxSpec, boxTemplate);
            }
        }