package nl.knaw.huygens.alexandria.text; /* * #%L * alexandria-main * ======= * Copyright (C) 2015 - 2017 Huygens ING (KNAW) * ======= * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; import nl.knaw.huygens.tei.Element; import nl.knaw.huygens.tei.ElementHandler; import nl.knaw.huygens.tei.Traversal; import nl.knaw.huygens.tei.XmlContext; import nl.knaw.huygens.tei.export.ExportVisitor; import nl.knaw.huygens.tei.handlers.DefaultCommentHandler; import nl.knaw.huygens.tei.handlers.DefaultProcessingInstructionHandler; import nl.knaw.huygens.tei.handlers.RenderElementHandler; import nl.knaw.huygens.tei.handlers.XmlTextHandler; public class AddMissingIdVisitor extends ExportVisitor { private static final String XMLID_MARKER = "-"; private static List<String> existingBaseElementIds; private static final Map<String, AtomicLong> counters = new HashMap<>(); public AddMissingIdVisitor(List<String> existingBaseElementIds, List<String> baseElementNames) { AddMissingIdVisitor.existingBaseElementIds = existingBaseElementIds; setCommentHandler(new DefaultCommentHandler<>()); setTextHandler(new XmlTextHandler<>()); setDefaultElementHandler(new RenderElementHandler()); setProcessingInstructionHandler(new DefaultProcessingInstructionHandler<>()); String[] elementNames = baseElementNames.toArray(new String[baseElementNames.size()]); addElementHandler(new BaseElementHandler(), elementNames); counters.clear(); } static class BaseElementHandler implements ElementHandler<XmlContext> { @Override public Traversal enterElement(Element element, XmlContext context) { if (element.hasChildren()) { if (!element.hasAttribute(TextUtil.XML_ID)) { addId(element); } context.addOpenTag(element); } else { // TODO: should milestone base elements get an xml:id? context.addEmptyElementTag(element); } return Traversal.NEXT; } private void addId(Element baseElement) { String name = baseElement.getName(); String id; counters.putIfAbsent(name, new AtomicLong(0)); do { id = name + XMLID_MARKER + counters.get(name).incrementAndGet(); } while (existingBaseElementIds.contains(id)); baseElement.setAttribute(TextUtil.XML_ID, id); } @Override public Traversal leaveElement(Element element, XmlContext context) { if (element.hasChildren()) { context.addCloseTag(element); } return Traversal.NEXT; } } }