<commit_before>/*
 * This file is part of the DITA Open Toolkit project.
 *
 * Copyright 2014 <NAME>
 *
 * See the accompanying LICENSE file for applicable license.
 */
package org.dita.dost.writer;

import org.dita.dost.module.reader.TempFileNameScheme;
import org.dita.dost.util.Job.FileInfo;
import org.dita.dost.util.XMLUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import java.net.URI;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;

import static org.dita.dost.chunk.ChunkModule.isLocalScope;
import static org.dita.dost.util.Constants.*;
import static org.dita.dost.util.FileUtils.getExtension;
import static org.dita.dost.util.FileUtils.replaceExtension;
import static org.dita.dost.util.URLUtils.*;

/**
 * Create copy-to attributes for duplicate topicrefs.
 */
public final class ForceUniqueFilter extends AbstractXMLFilter {

    private final Map<URI, Integer> topicrefCount = new HashMap<>();
    private final Deque<Boolean> ignoreStack = new ArrayDeque<>();
    /**
     * Generated copy-to mappings, key is target topic and value is source topic.
     */
    public final Map<FileInfo, FileInfo> copyToMap = new HashMap<>();
    private TempFileNameScheme tempFileNameScheme;

    /**
     * Stack used to detect the current element type. 
     */
    private final Deque<String> classElementStack = new ArrayDeque<>();
    
    /**
     * Stack used to hold the current topicref parent.
     */
    private Deque<ParentTopicref> topicrefParentsStack = new ArrayDeque<>();
    
    // ContentHandler methods

    @Override
    public void startElement(final String uri, final String localName, final String qName,
                             final Attributes atts) throws SAXException {
        ignoreStack.push(MAP_RELTABLE.matches(atts) ? false : ignoreStack.isEmpty() || ignoreStack.peek());

        final String classValue = atts.getValue(ATTRIBUTE_NAME_CLASS);
        classElementStack.addFirst(classValue);

        Attributes res = atts;
        if (ignoreStack.peek() && MAP_TOPICREF.matches(res)) {
            final URI href = toURI(res.getValue(ATTRIBUTE_NAME_HREF));
            final URI copyTo = toURI(res.getValue(ATTRIBUTE_NAME_COPY_TO));
            final URI source = copyTo != null ? copyTo : href;
            final String scope = res.getValue(ATTRIBUTE_NAME_SCOPE);
            final String format = res.getValue(ATTRIBUTE_NAME_FORMAT);
            // FIXME: handle cascading
            final String processingRole = res.getValue(ATTRIBUTE_NAME_PROCESSING_ROLE);
            FileInfo dstFi = null;
            if (source != null &&
                    isLocalScope(scope) &&
                    (format == null || format.equals(ATTR_FORMAT_VALUE_DITA)) &&
                    (processingRole == null || processingRole.equals(ATTR_PROCESSING_ROLE_VALUE_NORMAL))) {
                final URI file = stripFragment(source);
                Integer count = topicrefCount.getOrDefault(file, 0);
                
                ParentTopicref parentTopicref = topicrefParentsStack.peek();
                boolean parentTopicHasEmbededSubtopcis = false;
                if (parentTopicref != null && parentTopicref.href != null) {
                    URI parentHref = parentTopicref.href;
                    parentHref = stripFragment(parentHref);
                    parentTopicHasEmbededSubtopcis = href != null && parentHref.equals(file) && href.getFragment() != null;
                }
                if (parentTopicHasEmbededSubtopcis) {
                    dstFi = parentTopicref.dstFi;
                } else {
                    count++;
                    topicrefCount.put(file, count);
                }
                
                if (count > 1) { // not only reference to this topic
                    final FileInfo srcFi = job.getFileInfo(currentFile.resolve(stripFragment(source)));
                    if (srcFi != null) {
                        if (dstFi == null) {
                            dstFi = generateCopyToTarget(srcFi, count);
                        }
                        copyToMap.put(dstFi, srcFi);
                        final URI dstTempAbs = job.tempDirURI.resolve(dstFi.uri);
                        final URI targetRel = getRelativePath(currentFile, dstTempAbs);
                        final URI target = setFragment(targetRel, href.getFragment());

                        final AttributesImpl buf = new AttributesImpl(atts);
                        XMLUtils.addOrSetAttribute(buf, ATTRIBUTE_NAME_COPY_TO, target.toString());
                        res = buf;
                    }
                }
            }<commit_msg>Clean code style<commit_after>/*
 * This file is part of the DITA Open Toolkit project.
 *
 * Copyright 2014 <NAME>
 *
 * See the accompanying LICENSE file for applicable license.
 */
package org.dita.dost.writer;

import org.dita.dost.module.reader.TempFileNameScheme;
import org.dita.dost.util.Job.FileInfo;
import org.dita.dost.util.XMLUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import java.net.URI;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;

import static org.dita.dost.chunk.ChunkModule.isLocalScope;
import static org.dita.dost.util.Constants.*;
import static org.dita.dost.util.FileUtils.getExtension;
import static org.dita.dost.util.FileUtils.replaceExtension;
import static org.dita.dost.util.URLUtils.*;

/**
 * Create copy-to attributes for duplicate topicrefs.
 */
public final class ForceUniqueFilter extends AbstractXMLFilter {

    private final Map<URI, Integer> topicrefCount = new HashMap<>();
    private final Deque<Boolean> ignoreStack = new ArrayDeque<>();
    /**
     * Generated copy-to mappings, key is target topic and value is source topic.
     */
    public final Map<FileInfo, FileInfo> copyToMap = new HashMap<>();
    private TempFileNameScheme tempFileNameScheme;

    /**
     * Stack used to detect the current element type. 
     */
    private final Deque<String> classElementStack = new ArrayDeque<>();
    
    /**
     * Stack used to hold the current topicref parent.
     */
    private final Deque<ParentTopicref> topicrefParentsStack = new ArrayDeque<>();
    
    // ContentHandler methods

    @Override
    public void startElement(final String uri, final String localName, final String qName,
                             final Attributes atts) throws SAXException {
        ignoreStack.push(MAP_RELTABLE.matches(atts) ? false : ignoreStack.isEmpty() || ignoreStack.peek());

        final String classValue = atts.getValue(ATTRIBUTE_NAME_CLASS);
        classElementStack.addFirst(classValue);

        Attributes res = atts;
        if (ignoreStack.peek() && MAP_TOPICREF.matches(res)) {
            final URI href = toURI(res.getValue(ATTRIBUTE_NAME_HREF));
            final URI copyTo = toURI(res.getValue(ATTRIBUTE_NAME_COPY_TO));
            final URI source = copyTo != null ? copyTo : href;
            final String scope = res.getValue(ATTRIBUTE_NAME_SCOPE);
            final String format = res.getValue(ATTRIBUTE_NAME_FORMAT);
            // FIXME: handle cascading
            final String processingRole = res.getValue(ATTRIBUTE_NAME_PROCESSING_ROLE);
            FileInfo dstFi = null;
            if (source != null &&
                    isLocalScope(scope) &&
                    (format == null || format.equals(ATTR_FORMAT_VALUE_DITA)) &&
                    (processingRole == null || processingRole.equals(ATTR_PROCESSING_ROLE_VALUE_NORMAL))) {
                final URI file = stripFragment(source);
                Integer count = topicrefCount.getOrDefault(file, 0);
                
                final ParentTopicref parentTopicref = topicrefParentsStack.peek();
                boolean parentTopicHasEmbededSubtopics = false;
                if (parentTopicref != null && parentTopicref.href != null) {
                    final URI parentHref = stripFragment(parentTopicref.href);
                    parentTopicHasEmbededSubtopics = href != null && parentHref.equals(file) && href.getFragment() != null;
                }
                if (parentTopicHasEmbededSubtopics) {
                    dstFi = parentTopicref.dstFi;
                } else {
                    count++;
                    topicrefCount.put(file, count);
                }
                
                if (count > 1) { // not only reference to this topic
                    final FileInfo srcFi = job.getFileInfo(currentFile.resolve(stripFragment(source)));
                    if (srcFi != null) {
                        if (dstFi == null) {
                            dstFi = generateCopyToTarget(srcFi, count);
                        }
                        copyToMap.put(dstFi, srcFi);
                        final URI dstTempAbs = job.tempDirURI.resolve(dstFi.uri);
                        final URI targetRel = getRelativePath(currentFile, dstTempAbs);
                        final URI target = setFragment(targetRel, href.getFragment());

                        final AttributesImpl buf = new AttributesImpl(atts);
                        XMLUtils.addOrSetAttribute(buf, ATTRIBUTE_NAME_COPY_TO, target.toString());
                        res = buf;
                    }
                }
            }
{'fraction_non_alphanumeric': 0.09162082099026661, 'fraction_numerical': 0.0012695725772323319, 'mean_word_length': 2.175344306348673, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6538233', 'n_tokens_mistral': 2566, 'n_tokens_neox': 2452, 'n_words': 599}