001package com.credibledoc.substitution.doc.module.substitution.activity.modules; 002 003import com.credibledoc.combiner.log.buffered.LogBufferedReader; 004import com.credibledoc.combiner.log.reader.ReaderService; 005import com.credibledoc.plantuml.svggenerator.SvgGeneratorService; 006import com.credibledoc.substitution.content.generator.jar.LocalJarNameContentGenerator; 007import com.credibledoc.substitution.core.resource.ResourceService; 008import com.credibledoc.substitution.doc.SubstitutionDocMain; 009import com.credibledoc.enricher.deriving.Deriving; 010import com.credibledoc.substitution.doc.module.substitution.exception.SubstitutionDocRuntimeException; 011import com.credibledoc.substitution.doc.module.substitution.logmessage.LogMessageService; 012import com.credibledoc.enricher.transformer.Transformer; 013import com.credibledoc.substitution.reporting.report.ReportService; 014import lombok.NonNull; 015import lombok.RequiredArgsConstructor; 016import org.springframework.stereotype.Service; 017 018import javax.inject.Inject; 019import java.util.*; 020 021/** 022 * Create a part of PlantUML activity diagram, for example 023 * <pre> 024 * |Swimlane1| 025 * :foo4; 026 * </pre> 027 * from log lines, for example 028 * <i>04.03.2019 18:41:13.658|main|INFO |com.credibledoc.substitution.core.configuration.ConfigurationService - Properties loaded by ClassLoader from the resource: file..</i>. 029 */ 030@Service 031@RequiredArgsConstructor(onConstructor = @__(@Inject)) 032public class ModulesActivityTransformer implements Transformer { 033 034 @NonNull 035 public final LogMessageService logMessageService; 036 037 private static final String PLANTUML_CORE_MODULE_NAME = "plantuml-core"; 038 private static Map<String, String> packagePrefixToModuleName = new HashMap<>(); 039 040 static { 041 packagePrefixToModuleName.put("com.credibledoc.substitution.core", 042 ResourceService.SUBSTITUTION_CORE_MODULE_NAME); 043 packagePrefixToModuleName.put("com.credibledoc.substitution.doc", 044 SubstitutionDocMain.SUBSTITUTION_DOC); 045 packagePrefixToModuleName.put("com.credibledoc.plantuml", 046 PLANTUML_CORE_MODULE_NAME); 047 packagePrefixToModuleName.put("com.credibledoc.combiner", 048 ReaderService.COMBINER_CORE_MODULE_NAME); 049 packagePrefixToModuleName.put("com.credibledoc.substitution.content.generator", 050 LocalJarNameContentGenerator.MODULE_NAME); 051 packagePrefixToModuleName.put("com.credibledoc.substitution.reporting", 052 ReportService.MODULE_NAME); 053 packagePrefixToModuleName.put("org.springframework.context.annotation", 054 "spring-libraries"); 055 056 // Should be here for activating of the "com.credibledoc.plantuml" class loader 057 SvgGeneratorService.class.getPackage(); 058 LocalJarNameContentGenerator.class.getPackage(); 059 validatePackagesExist(); 060 } 061 062 private static void validatePackagesExist() { 063 Set<String> foundPrefixes = new HashSet<>(); 064 for (Package pkg : Package.getPackages()) { 065 String name = pkg.getName(); 066 for (String prefix : packagePrefixToModuleName.keySet()) { 067 if (name.startsWith(prefix)) { 068 foundPrefixes.add(prefix); 069 if (foundPrefixes.size() == packagePrefixToModuleName.size()) { 070 return; 071 } 072 } 073 } 074 } 075 Set<String> missingPrefixes = new HashSet<>(packagePrefixToModuleName.keySet()); 076 missingPrefixes.removeAll(foundPrefixes); 077 078 throw new SubstitutionDocRuntimeException("Package(s) not found: " + missingPrefixes); 079 } 080 081 @Override 082 public String transform(Deriving deriving, 083 List<String> multiLine, LogBufferedReader logBufferedReader) { 084 String canonicalClassName = parseClassName(multiLine.get(0)); 085 String moduleName = findModuleName(canonicalClassName); 086 087 int maxRowLength = moduleName.length() * 2 + moduleName.length() / 2; 088 List<String> cacheLines = deriving.getCacheLines(); 089 addMessageToCache(multiLine, moduleName, maxRowLength, cacheLines); 090 091 return null; 092 } 093 094 private String findModuleName(String canonicalClassName) { 095 for (Map.Entry<String, String> entry : packagePrefixToModuleName.entrySet()) { 096 if (canonicalClassName.startsWith(entry.getKey())) { 097 return entry.getValue(); 098 } 099 } 100 throw new SubstitutionDocRuntimeException("Module name cannot be found for package: " + canonicalClassName); 101 } 102 103 private void addMessageToCache(List<String> multiLine, String canonicalClassName, int maxRowLength, 104 List<String> cacheLines) { 105 String message = logMessageService.parseMessage(multiLine.get(0), maxRowLength); 106 String result = "|" + canonicalClassName + "|" + LogMessageService.LINE_SEPARATOR + 107 LogMessageService.FOUR_SPACES + ":" + message + ";" + LogMessageService.LINE_SEPARATOR; 108 cacheLines.add(result); 109 } 110 111 private String parseClassName(String line) { 112 int separatorIndex = line.indexOf(LogMessageService.LOG_SEPARATOR); 113 String firstPart = line.substring(0, separatorIndex); 114 int startIndex = firstPart.lastIndexOf('|') + 1; 115 return firstPart.substring(startIndex); 116 } 117}