001/*
002 *  Copyright (c) 2023-2026, Agents-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *  <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 *  <p>
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.agentsflex.core.file2text.extractor.impl;
017
018
019import com.agentsflex.core.file2text.extractor.FileExtractor;
020import com.agentsflex.core.file2text.source.DocumentSource;
021import com.agentsflex.core.file2text.util.EncodingDetectUtil;
022
023import java.io.InputStream;
024import java.util.Collections;
025import java.util.HashSet;
026import java.util.Set;
027
028/**
029 * 纯文本文件提取器(支持 UTF-8、GBK、GB2312 编码自动检测)
030 * 支持 .txt, .md, .log, .csv, .json, .xml 等文本格式
031 */
032public class PlainTextExtractor implements FileExtractor {
033
034    private static final Set<String> SUPPORTED_MIME_TYPES;
035    private static final Set<String> SUPPORTED_EXTENSIONS;
036
037    static {
038        Set<String> mimeTypes = new HashSet<>();
039        mimeTypes.add("text/plain");
040        mimeTypes.add("text/markdown");
041        mimeTypes.add("text/csv");
042        mimeTypes.add("application/json");
043        mimeTypes.add("application/xml");
044        SUPPORTED_MIME_TYPES = Collections.unmodifiableSet(mimeTypes);
045
046        Set<String> extensions = new HashSet<>();
047        extensions.add("txt");
048        extensions.add("text");
049        extensions.add("md");
050        extensions.add("markdown");
051        extensions.add("log");
052        extensions.add("csv");
053        extensions.add("json");
054        extensions.add("xml");
055        extensions.add("yml");
056        extensions.add("yaml");
057        extensions.add("properties");
058        extensions.add("conf");
059        SUPPORTED_EXTENSIONS = Collections.unmodifiableSet(extensions);
060    }
061
062    @Override
063    public boolean supports(DocumentSource source) {
064        String mimeType = source.getMimeType();
065        String fileName = source.getFileName();
066
067        if (mimeType != null && (mimeType.startsWith("text/") || SUPPORTED_MIME_TYPES.contains(mimeType))) {
068            return true;
069        }
070
071        if (fileName != null) {
072            String ext = getExtension(fileName);
073            return ext != null && SUPPORTED_EXTENSIONS.contains(ext.toLowerCase());
074        }
075
076        return false;
077    }
078
079    @Override
080    public String extractText(DocumentSource source) {
081        try (InputStream is = source.openStream()) {
082            return EncodingDetectUtil.readToString(is);
083        } catch (Exception e) {
084            throw new RuntimeException(e);
085        }
086    }
087
088
089    @Override
090    public int getOrder() {
091        return 5; // 高优先级
092    }
093
094    private String getExtension(String fileName) {
095        if (fileName == null || !fileName.contains(".")) return null;
096        int lastDot = fileName.lastIndexOf('.');
097        return fileName.substring(lastDot + 1).toLowerCase();
098    }
099}