package nl.knaw.huygens.alexandria.endpoint.command; /* * #%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 static java.util.stream.Collectors.toList; import static nl.knaw.huygens.alexandria.text.TextUtil.XML_ID; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; import javax.inject.Inject; import com.google.common.collect.Lists; import nl.knaw.huygens.alexandria.api.model.CommandResponse; import nl.knaw.huygens.alexandria.api.model.Commands; import nl.knaw.huygens.alexandria.service.AlexandriaService; import nl.knaw.huygens.alexandria.textgraph.TextAnnotation; public class AddUniqueIdCommand extends TextAnnotationCommand { private static final String PARAMETER_ELEMENTS = "elements"; private static class Parameters { List<ResourceViewId> resourceViewIds; List<String> elementNames; } private static class Context { private static final String XMLID_MARKER = "-"; private final Map<String, AtomicLong> counters; private List<String> existingIds; private AlexandriaService service; public Context(AlexandriaService service) { this.service = service; this.counters = new HashMap<>(); this.existingIds = Lists.newArrayList(); } public void setXmlId(TextAnnotation textAnnotation) { String name = textAnnotation.getName(); String id; counters.putIfAbsent(name, new AtomicLong(0)); do { id = name + XMLID_MARKER + counters.get(name).incrementAndGet(); } while (existingIds.contains(id)); textAnnotation.getAttributes().put(XML_ID, id); service.updateTextAnnotation(textAnnotation); } } private CommandResponse commandResponse = new CommandResponse(); private AlexandriaService service; @Inject public AddUniqueIdCommand(AlexandriaService service) { this.service = service; } @Override public CommandResponse runWith(Map<String, Object> parameterMap) { Parameters parameters = validateParameters(parameterMap); if (commandResponse.parametersAreValid()) { parameters.resourceViewIds.stream()// .map(ResourceViewId::getResourceId)// .forEach(resourceId -> service.runInTransaction(() -> { Context context = new Context(service); context.existingIds = service.getTextAnnotationStream(resourceId)// .filter(this::hasXmlId)// .map(this::getXmlId)// .collect(toList()); service.getTextAnnotationStream(resourceId)// .filter(ta -> textAnnotationHasRelevantName(parameters, ta))// .filter(ta -> !hasXmlId(ta))// .forEach(context::setXmlId); })); } return commandResponse; } @SuppressWarnings("unchecked") private Parameters validateParameters(Map<String, Object> parameterMap) { final Parameters parameters = new Parameters(); parameters.resourceViewIds = validateResourceViewIds(parameterMap, commandResponse, service); boolean valid = (commandResponse.getErrorLines().isEmpty()); if (!parameterMap.containsKey(PARAMETER_ELEMENTS)) { addElementsError(); valid = false; } else { try { parameters.elementNames = (List<String>) parameterMap.get(PARAMETER_ELEMENTS); } catch (ClassCastException e) { addElementsError(); valid = false; } } if (valid) { commandResponse.setParametersAreValid(true); } return parameters; } private CommandResponse addElementsError() { return commandResponse.addErrorLine("Parameter '" + PARAMETER_ELEMENTS + "' should be list of element names."); } private boolean textAnnotationHasRelevantName(Parameters parameters, TextAnnotation textAnnotation) { return parameters.elementNames.contains(textAnnotation.getName()); } @Override public String getName() { return Commands.ADD_UNIQUE_ID; } }