/** * Selects a delegate template based on the rendering rules, given the delegate template name and * the set of active delegate package names. * * @param delTemplateName The delegate template name to select an implementation for. * @param activeDelPackageNames The set of active delegate package names. * @return The selected delegate template, or null if there are no active implementations. * @throws DelegateTemplateConflictException If there are two or more active implementations with * equal priority (unable to select one over the other). */ public TemplateDelegateNode selectDelegateTemplate( String delTemplateName, Set<String> activeDelPackageNames) throws DelegateTemplateConflictException { List<DelegateTemplateDivision> divisions = delTemplatesMap.get(delTemplateName); if (divisions == null) { return null; } for (DelegateTemplateDivision division : divisions) { TemplateDelegateNode delTemplate = null; for (String delPackageName : division.delPackageNameToDelTemplateMap.keySet()) { if (delPackageName != null && !activeDelPackageNames.contains(delPackageName)) { continue; } if (delTemplate != null) { throw new DelegateTemplateConflictException( String.format( "For delegate template name '%s', found two active implementations with equal" + " priority in delegate packages '%s' and '%s'.", delTemplateName, delTemplate.getDelPackageName(), delPackageName)); } delTemplate = division.delPackageNameToDelTemplateMap.get(delPackageName); } if (delTemplate != null) { return delTemplate; } } return null; }
/** * Constructor. * * @param soyTree The Soy tree from which to build a template registry. */ public TemplateRegistry(SoyFileSetNode soyTree) { // ------ Iterate through all templates to collect data. ------ Map<String, TemplateBasicNode> tempBasicTemplatesMap = Maps.newHashMap(); Map<String, Map<Integer, Map<String, TemplateDelegateNode>>> tempDelTemplatesMap = Maps.newHashMap(); for (SoyFileNode soyFile : soyTree.getChildren()) { for (TemplateNode template : soyFile.getChildren()) { if (template instanceof TemplateBasicNode) { // Case 1: Basic template. tempBasicTemplatesMap.put(template.getTemplateName(), (TemplateBasicNode) template); } else { // Case 2: Delegate template. TemplateDelegateNode delTemplate = (TemplateDelegateNode) template; String delTemplateName = delTemplate.getDelTemplateName(); int delPriority = delTemplate.getDelPriority(); String delPackageName = delTemplate.getDelPackageName(); Map<Integer, Map<String, TemplateDelegateNode>> tempDivisions = tempDelTemplatesMap.get(delTemplateName); if (tempDivisions == null) { tempDivisions = Maps.newHashMap(); tempDelTemplatesMap.put(delTemplateName, tempDivisions); } Map<String, TemplateDelegateNode> tempDivision = tempDivisions.get(delPriority); if (tempDivision == null) { tempDivision = Maps.newHashMap(); tempDivisions.put(delPriority, tempDivision); } if (tempDivision.containsKey(delPackageName)) { TemplateDelegateNode prevTemplate = tempDivision.get(delPackageName); String prevTemplateFilePath = prevTemplate.getNearestAncestor(SoyFileNode.class).getFilePath(); String currTemplateFilePath = delTemplate.getNearestAncestor(SoyFileNode.class).getFilePath(); if (currTemplateFilePath.equals(prevTemplateFilePath)) { throw new SoySyntaxException( String.format( "Found two definitions for delegate template name '%s' in the same delegate" + "package, both in the file %s.", delTemplateName, currTemplateFilePath)); } else { throw new SoySyntaxException( String.format( "Found two definitions for delegate template name '%s' in the same delegate" + "package, in two different files %s and %s.", delTemplateName, prevTemplateFilePath, currTemplateFilePath)); } } tempDivision.put(delPackageName, delTemplate); } } } // ------ Build the final data structures. ------ basicTemplatesMap = Collections.unmodifiableMap(tempBasicTemplatesMap); ImmutableMap.Builder<String, List<DelegateTemplateDivision>> delTemplatesMapBuilder = ImmutableMap.builder(); for (String delTemplateName : tempDelTemplatesMap.keySet()) { Map<Integer, Map<String, TemplateDelegateNode>> tempDivisions = tempDelTemplatesMap.get(delTemplateName); ImmutableList.Builder<DelegateTemplateDivision> divisionsBuilder = ImmutableList.builder(); // Note: List should be in decreasing priority order. for (int priority = TemplateNode.MAX_PRIORITY; priority >= 0; priority--) { if (!tempDivisions.containsKey(priority)) { continue; } Map<String, TemplateDelegateNode> tempDivision = tempDivisions.get(priority); DelegateTemplateDivision division = new DelegateTemplateDivision(priority, tempDivision); divisionsBuilder.add(division); } delTemplatesMapBuilder.put(delTemplateName, divisionsBuilder.build()); } delTemplatesMap = delTemplatesMapBuilder.build(); }