blob: bcc6df23d24ca6f2b8bf8a07981596aa30b7473b [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2018 Boeing
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Boeing - initial API and implementation
**********************************************************************/
package org.eclipse.osee.orcs.core.internal.applicability;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Sets;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.eclipse.osee.framework.core.applicability.FeatureDefinition;
import org.eclipse.osee.framework.core.data.ArtifactToken;
import org.eclipse.osee.framework.core.data.BlockApplicabilityCacheFile;
import org.eclipse.osee.framework.core.data.BranchId;
import org.eclipse.osee.framework.core.data.FileTypeApplicabilityData;
import org.eclipse.osee.framework.core.enums.CoreArtifactTokens;
import org.eclipse.osee.framework.core.enums.CoreArtifactTypes;
import org.eclipse.osee.framework.core.enums.CoreAttributeTypes;
import org.eclipse.osee.framework.core.enums.CoreBranches;
import org.eclipse.osee.framework.core.enums.CoreRelationTypes;
import org.eclipse.osee.framework.core.grammar.ApplicabilityBlock;
import org.eclipse.osee.framework.core.grammar.ApplicabilityBlock.ApplicabilityType;
import org.eclipse.osee.framework.core.grammar.ApplicabilityGrammarLexer;
import org.eclipse.osee.framework.core.grammar.ApplicabilityGrammarParser;
import org.eclipse.osee.framework.core.util.WordCoreUtil;
import org.eclipse.osee.framework.jdk.core.result.XResultData;
import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
import org.eclipse.osee.framework.jdk.core.util.Collections;
import org.eclipse.osee.framework.jdk.core.util.Strings;
import org.eclipse.osee.logger.Log;
import org.eclipse.osee.orcs.OrcsApi;
import org.eclipse.osee.orcs.data.ArtifactReadable;
/**
* @author Ryan D. Brooks
*/
public class BlockApplicabilityOps {
private static String SCRIPT_ENGINE_NAME = "JavaScript";
/**
* Regex for use withing BlockApplicability.<br/>
* (?!Group) is included within Configuration in order to void matching ConfigurationGroup text but leaving 'Group'
* behind. This ensures that ConfigurationGroup tags will properly match their own regex.
*/
public static final String INLINE_WHITESPACE = "[ \\t]*";
public static final String SINGLE_NEW_LINE = "\\r\\n|[\\n\\r]";
public static final String BEGINFEATURE = " ?(Feature ?(\\[(.*?)\\])) ?";
public static final String ENDFEATURE = " ?(End Feature ?((\\[.*?\\]))?) ?";
public static final String BEGINCONFIG = " ?(Configuration(?!Group)( Not)? ?(\\[(.*?)\\])) ?";
public static final String ENDCONFIG = " ?(End Configuration(?!Group) ?((\\[.*?\\]))?) ?";
public static final String BEGINCONFIGGRP = " ?(ConfigurationGroup( Not)? ?(\\[(.*?)\\])) ?";
public static final String ENDCONFIGGRP = " ?(End ConfigurationGroup ?((\\[.*?\\]))?) ?";
public static final String COMMENT_EXTRA_CHARS = INLINE_WHITESPACE + "(" + SINGLE_NEW_LINE + ")?";
public static final int beginFeatureCommentMatcherGroup = 1;
public static final int beginFeatureTagMatcherGroup = 2;
public static final int endFeatureCommentMatcherGroup = 6;
public static final int endFeatureTagMatcherGroup = 7;
public static final int beginConfigCommentMatcherGroup = 11;
public static final int beginConfigTagMatcherGroup = 12;
public static final int endConfigCommentMatcherGroup = 17;
public static final int endConfigTagMatcherGroup = 18;
public static final int beginConfigGrpCommentMatcherGroup = 22;
public static final int beginConfigGrpTagMatcherGroup = 23;
public static final int endConfigGrpCommentMatcherGroup = 28;
public static final int endConfigGrpTagMatcherGroup = 29;
private final OrcsApi orcsApi;
private final Log logger;
private final ScriptEngine se;
private final BranchId branch;
private final ArtifactToken view;
private final List<FeatureDefinition> featureDefinition;
private final Map<String, List<String>> viewApplicabilitiesMap;
private final boolean useCachedConfig;
private BlockApplicabilityRule rule;
private BlockApplicabilityCacheFile cache;
private String plPreferences;
private Map<String, FileTypeApplicabilityData> fileTypeApplicabilityDataMap;
private Map<String, List<String>> configurationMap;
private Map<String, Set<String>> fileApplicabilityCache = new HashMap<>();
public BlockApplicabilityOps(OrcsApi orcsApi, Log logger, BranchId branch, ArtifactToken view, BlockApplicabilityCacheFile cache) {
this.orcsApi = orcsApi;
this.logger = logger;
this.branch = branch;
this.view = view;
ScriptEngineManager sem = new ScriptEngineManager();
this.se = sem.getEngineByName(SCRIPT_ENGINE_NAME);
this.featureDefinition = cache.getFeatureDefinition();
this.viewApplicabilitiesMap = cache.getViewApplicabilitiesMap();
this.configurationMap = cache.getConfigurationMap();
this.plPreferences = cache.getProductLinePreferences();
this.fileTypeApplicabilityDataMap = populateFileTypeApplicabilityDataMap(plPreferences);
this.cache = cache;
this.useCachedConfig = true;
}
public BlockApplicabilityOps(OrcsApi orcsApi, Log logger, BranchId branch, ArtifactToken view) {
this.orcsApi = orcsApi;
this.logger = logger;
this.branch = branch;
this.view = view;
ScriptEngineManager sem = new ScriptEngineManager();
this.se = sem.getEngineByName(SCRIPT_ENGINE_NAME);
this.featureDefinition = orcsApi.getApplicabilityOps().getFeatureDefinitionData(branch);
this.viewApplicabilitiesMap =
orcsApi.getQueryFactory().applicabilityQuery().getNamedViewApplicabilityMap(branch, view);
this.configurationMap = new HashMap<>();
this.plPreferences = getProductLinePreferences();
this.fileTypeApplicabilityDataMap = populateFileTypeApplicabilityDataMap(plPreferences);
this.useCachedConfig = false;
}
public ApplicabilityBlock createApplicabilityBlock(ApplicabilityType applicType, String beginExpression) {
ApplicabilityBlock beginApplic = new ApplicabilityBlock(applicType);
beginExpression = beginExpression.replace(" [", "[");
beginApplic.setApplicabilityExpression(beginExpression);
return beginApplic;
}
public XResultData applyApplicabilityToFiles(boolean commentNonApplicableBlocks, String sourcePath, String stagePath) throws OseeCoreException {
XResultData results = new XResultData();
HashSet<String> excludedFiles = new HashSet<>();
excludedFiles.add("Staging");
setUpBlockApplicability(commentNonApplicableBlocks);
File sourceFile = new File(sourcePath);
rule.process(sourceFile, stagePath, excludedFiles);
if (!useCachedConfig) {
createCacheFile(results, stagePath);
}
if (sourceFile.isDirectory()) {
writeFileApplicabilityCache(results, sourceFile.getName(), stagePath);
}
return results;
}
public XResultData refreshStagedFiles(String sourcePath, String stagePath, List<String> files) {
XResultData results = new XResultData();
File sourceDir = new File(sourcePath);
File stageDir = new File(stagePath, sourceDir.getName());
File fileApplicCache = readFileApplicabilityCache(results, stageDir);
Set<String> excludedFiles;
for (String sourceFileString : files) {
File sourceFile = new File(sourceDir, sourceFileString);
File stageFile = new File(stageDir, sourceFileString).getParentFile();
if (sourceFile.getName().equals(".fileApplicability")) {
/**
* If it's a .fileApplicability file, it could be making changes to its' siblings and therefore those all
* need to be processed
*/
sourceFile = sourceFile.getParentFile();
stageFile = stageFile.getParentFile();
}
excludedFiles = fileApplicabilityCache.getOrDefault(stageFile.getPath(), Sets.newHashSet("Staging"));
rule.process(sourceFile, stageFile.getPath(), excludedFiles);
}
writeFileApplicabilityCache(results, fileApplicCache);
return results;
}
/**
* This method can be used internally or externally to set up the BlockApplicabilityRule class for the
* BlockApplicabilityTool's use.
*/
public void setUpBlockApplicability(boolean commentNonApplicableBlocks) {
if (useCachedConfig) {
configurationMap = cache.getConfigurationMap();
plPreferences = cache.getProductLinePreferences();
fileTypeApplicabilityDataMap = populateFileTypeApplicabilityDataMap(plPreferences);
} else {
configurationMap = new HashMap<>();
plPreferences = getProductLinePreferences();
fileTypeApplicabilityDataMap = populateFileTypeApplicabilityDataMap(plPreferences);
}
rule = new BlockApplicabilityRule(this, fileTypeApplicabilityDataMap, commentNonApplicableBlocks);
StringBuilder filePattern = new StringBuilder(".*\\.(");
filePattern.append(Collections.toString("|", fileTypeApplicabilityDataMap.keySet()));
filePattern.append(")");
rule.setFileNamePattern(filePattern.toString());
}
public String evaluateApplicabilityExpression(ApplicabilityBlock applic) {
String applicabilityExpression = applic.getApplicabilityExpression();
String toInsert = "";
try {
String insideText = applic.getInsideText();
ApplicabilityGrammarLexer lex =
new ApplicabilityGrammarLexer(new ANTLRStringStream(applicabilityExpression.toUpperCase()));
ApplicabilityGrammarParser parser = new ApplicabilityGrammarParser(new CommonTokenStream(lex));
parser.start();
ApplicabilityType type = applic.getType();
if (type.equals(ApplicabilityType.Feature)) {
toInsert =
getValidFeatureContent(insideText, applic.isInTable(), parser.getIdValuesMap(), parser.getOperators());
} else if (type.equals(ApplicabilityType.Configuration) || type.equals(ApplicabilityType.NotConfiguration)) {
toInsert = getValidConfigurationContent(type, insideText, parser.getIdValuesMap());
} else if (type.equals(ApplicabilityType.ConfigurationGroup) || type.equals(
ApplicabilityType.NotConfigurationGroup)) {
toInsert = getValidConfigurationGroupContent(type, insideText, applic.getBeginTag());
}
} catch (RecognitionException ex) {
logger.error(
"Failed to parse expression: " + applicabilityExpression + " at start Index: " + applic.getStartInsertIndex());
}
return toInsert;
}
private String getValidFeatureContent(String fullText, boolean isInTable, HashMap<String, List<String>> featureIdValuesMap, ArrayList<String> featureOperators) {
Matcher match = WordCoreUtil.ELSE_PATTERN.matcher(fullText);
String beginningText = fullText;
String elseText = "";
if (match.find()) {
if (isInTable) {
String temp = fullText.substring(0, match.end());
// Find last occurence of table row
int lastIndexOf = temp.lastIndexOf(WordCoreUtil.START_TABLE_ROW);
if (lastIndexOf != -1) {
elseText = fullText.substring(lastIndexOf);
elseText = elseText.replaceAll(WordCoreUtil.ELSE_EXP, "");
beginningText = fullText.substring(0, lastIndexOf);
}
} else {
beginningText = fullText.substring(0, match.start());
elseText = fullText.substring(match.end());
}
elseText = elseText.replaceAll(WordCoreUtil.ENDFEATURE, "");
elseText = elseText.replaceAll(WordCoreUtil.BEGINFEATURE, "");
}
String expression = createFeatureExpression(featureIdValuesMap, featureOperators);
boolean result = false;
try {
result = (boolean) se.eval(expression);
} catch (ScriptException ex) {
logger.error("Failed to parse expression: " + expression);
}
StringBuilder toReturn = new StringBuilder();
if (result) {
toReturn.append(beginningText);
} else {
toReturn.append(elseText);
}
return toReturn.toString();
}
private String getValidConfigurationGroupContent(ApplicabilityType type, String fullText, String beginTag) {
Matcher match = WordCoreUtil.ELSE_PATTERN.matcher(fullText);
String beginningText = fullText;
String elseText = "";
if (match.find()) {
beginningText = fullText.substring(0, match.start());
elseText = fullText.substring(match.end());
elseText = elseText.replaceAll(WordCoreUtil.ENDCONFIGGRP, "");
elseText = elseText.replaceAll(WordCoreUtil.BEGINCONFIGGRP, "");
}
String toReturn = "";
Boolean viewInCfgGroup = false;
// Note: this assumes only OR's are put in between configuration groups
viewInCfgGroup = viewInCfgGroup(beginTag);
if (type.equals(ApplicabilityType.NotConfigurationGroup)) {
if (viewInCfgGroup) {
toReturn = elseText;
} else {
toReturn = beginningText;
}
} else if (!viewInCfgGroup) {
toReturn = elseText;
} else {
toReturn = beginningText;
}
return toReturn;
}
private Boolean viewInCfgGroup(String beginTag) {
String beginConfigGroup = WordCoreUtil.textOnly(beginTag);
Boolean viewInCfgGroup = false;
int start = beginConfigGroup.indexOf("[") + 1;
int end = beginConfigGroup.indexOf("]");
String applicExpText = beginConfigGroup.substring(start, end);
String[] configGroups = applicExpText.split("&|\\|");
for (int i = 0; i < configGroups.length; i++) {
configGroups[i] = configGroups[i].split("=")[0].trim();
if (queryGroup(configGroups[i])) {
viewInCfgGroup = true;
break;
} else {
if (view.getName().equalsIgnoreCase(configGroups[i])) {
viewInCfgGroup = true;
}
}
}
return viewInCfgGroup;
}
private boolean queryGroup(String configGroup) {
if (useCachedConfig) {
return configurationMap.containsKey(configGroup);
} else {
return orcsApi.getQueryFactory().fromBranch(branch).andIsOfType(CoreArtifactTypes.GroupArtifact).andNameEquals(
configGroup).andRelatedTo(CoreRelationTypes.DefaultHierarchical_Parent,
CoreArtifactTokens.PlCfgGroupsFolder).andRelatedTo(CoreRelationTypes.PlConfigurationGroup_BranchView,
view).exists();
}
}
private String getValidConfigurationContent(ApplicabilityType type, String fullText, HashMap<String, List<String>> configIdValuesMap) {
Matcher match = WordCoreUtil.ELSE_PATTERN.matcher(fullText);
String beginningText = fullText;
String elseText = "";
if (match.find()) {
beginningText = fullText.substring(0, match.start());
elseText = fullText.substring(match.end());
elseText = elseText.replaceAll(WordCoreUtil.ENDCONFIG, "");
elseText = elseText.replaceAll(WordCoreUtil.BEGINCONFIG, "");
}
String toReturn = "";
// Note: this assumes only OR's are put in between configurations
List<String> matchingTags = new ArrayList<String>();
if (view.isTypeEqual(CoreArtifactTypes.GroupArtifact)) {
getGroupConfigMatchingTags(matchingTags, configIdValuesMap);
if (matchingTags.isEmpty()) {
matchingTags = null;
}
} else {
matchingTags = configIdValuesMap.get(view.getName().toUpperCase());
}
if (type.equals(ApplicabilityType.NotConfiguration)) {
//Note when publishing with view=configurationgroup, do not publish Configuration Not[configA] text
if (branchViewExists()) {
if (matchingTags != null) {
toReturn = elseText;
} else {
toReturn = beginningText;
}
}
} else if (matchingTags == null) {
toReturn = elseText;
} else {
toReturn = beginningText;
}
return toReturn;
}
private void getGroupConfigMatchingTags(List<String> matchingTags, HashMap<String, List<String>> configIdValuesMap) {
if (useCachedConfig) {
List<String> configs = configurationMap.getOrDefault(view.getName(), new ArrayList<String>());
for (String config : configs) {
if (configIdValuesMap.containsKey(config.toUpperCase())) {
matchingTags.add("Config = " + config);
}
}
} else {
for (ArtifactReadable memberConfig : orcsApi.getQueryFactory().fromBranch(branch).andId(
view).getArtifact().getRelated(CoreRelationTypes.PlConfigurationGroup_BranchView).getList()) {
if (configIdValuesMap.containsKey(memberConfig.getName().toUpperCase())) {
matchingTags.add("Config = " + memberConfig.getName());
}
}
}
}
private boolean branchViewExists() {
if (useCachedConfig) {
return true;
} else {
return orcsApi.getQueryFactory().fromBranch(branch).andId(view).andIsOfType(
CoreArtifactTypes.BranchView).exists();
}
}
private String createFeatureExpression(HashMap<String, List<String>> featureIdValuesMap, ArrayList<String> featureOperators) {
String myFeatureExpression = "";
Iterator<String> iterator = featureOperators.iterator();
for (String feature : featureIdValuesMap.keySet()) {
List<String> values = featureIdValuesMap.get(feature);
String valueExpression = createValueExpression(feature, values);
boolean result = false;
try {
result = (boolean) se.eval(valueExpression);
} catch (ScriptException ex) {
logger.error("Failed to parse expression: " + valueExpression);
}
myFeatureExpression += result + " ";
if (iterator.hasNext()) {
String next = iterator.next();
if (next.equals("|")) {
myFeatureExpression += "|| ";
} else if (next.equals("&")) {
myFeatureExpression += "&& ";
}
}
}
return myFeatureExpression;
}
private String createValueExpression(String feature, List<String> values) {
String myValueExpression = "";
for (String value : values) {
if (value.equals("(")) {
myValueExpression += "( ";
} else if (value.equals(")")) {
myValueExpression += ") ";
} else if (value.equals("|")) {
myValueExpression += "|| ";
} else if (value.equals("&")) {
myValueExpression += "&& ";
} else {
boolean eval = isFeatureValuePairValid(feature, value);
myValueExpression += eval + " ";
}
}
return myValueExpression;
}
private boolean isFeatureValuePairValid(String feature, String value) {
if (viewApplicabilitiesMap.containsKey(feature)) {
Collection<String> validValues = viewApplicabilitiesMap.get(feature);
value = value.equalsIgnoreCase("Default") ? getDefaultValue(feature) : value.trim();
return Strings.containsIgnoreCase(validValues, value);
}
return false;
}
private String getDefaultValue(String feature) {
String toReturn = null;
for (FeatureDefinition fDef : featureDefinition) {
if (fDef.getName().equals(feature)) {
toReturn = fDef.getDefaultValue();
break;
}
}
return toReturn;
}
public void addFileApplicabilityEntry(String path, Set<String> excludedFiles) {
Set<String> excludedSet = new HashSet<>();
excludedSet.addAll(excludedFiles);
fileApplicabilityCache.put(path, excludedSet);
}
public ArtifactToken getOpsView() {
return view;
}
private File readFileApplicabilityCache(XResultData results, File stageDir) {
File fileApplicCache = new File(stageDir, ".fileApplicabilityCache");
ObjectMapper objMap = new ObjectMapper();
JavaType type = objMap.getTypeFactory().constructMapType(HashMap.class, String.class, Set.class);
try {
fileApplicabilityCache = objMap.readValue(fileApplicCache, type);
} catch (IOException ex) {
results.error("Error reading fileApplicabilityCache");
}
return fileApplicCache;
}
private void writeFileApplicabilityCache(XResultData results, String sourceFileName, String stagePath) {
File fileApplicCache = new File(stagePath, sourceFileName);
fileApplicCache = new File(fileApplicCache, ".fileApplicabilityCache");
writeFileApplicabilityCache(results, fileApplicCache);
}
private void writeFileApplicabilityCache(XResultData results, File fileApplicCache) {
ObjectMapper objMap = new ObjectMapper();
try {
objMap.writeValue(fileApplicCache, fileApplicabilityCache);
} catch (IOException ex) {
results.error("Error writing file applicability cache file");
}
}
/**
* This cache file is created to store necessary information to process applicability within this class. Anything
* that is normally queried from the database, should be stored in this json file and saved within the stagePath.
*/
public void createCacheFile(XResultData results, String stagePath) {
ObjectMapper objMap = new ObjectMapper();
try {
BlockApplicabilityCacheFile cache = new BlockApplicabilityCacheFile();
cache.setViewId(view.getId());
cache.setViewName(view.getName());
cache.setViewTypeId(view.getArtifactType().getId());
cache.setViewApplicabilitiesMap(viewApplicabilitiesMap);
cache.setFeatureDefinition(featureDefinition);
cache.setConfigurationMap(createCacheConfigurationMap());
cache.setProductLinePreferences(plPreferences);
File cacheFile = new File(stagePath, ".applicabilityCache");
objMap.writeValue(cacheFile, cache);
} catch (IOException ex) {
results.error(String.format("There was a problem while writing the cache file %s", ex.getMessage()));
}
}
/**
* The configurationMap should be specific to the view given. If the view is a GroupConfig, it will map that group
* config to all of the configurations related to it. If the view is a configuration, it will map each related group
* config to its' configurations.
*/
private Map<String, List<String>> createCacheConfigurationMap() {
Map<String, List<String>> configMap = new HashMap<>();
List<ArtifactReadable> groupConfigs = new ArrayList<>();
if (view.isOfType(CoreArtifactTypes.GroupArtifact)) {
groupConfigs =
orcsApi.getQueryFactory().fromBranch(branch).andIsOfType(CoreArtifactTypes.GroupArtifact).andRelatedTo(
CoreRelationTypes.DefaultHierarchical_Parent, CoreArtifactTokens.PlCfgGroupsFolder).follow(
CoreRelationTypes.PlConfigurationGroup_BranchView).asArtifacts();
} else {
groupConfigs =
orcsApi.getQueryFactory().fromBranch(branch).andIsOfType(CoreArtifactTypes.GroupArtifact).andRelatedTo(
CoreRelationTypes.DefaultHierarchical_Parent, CoreArtifactTokens.PlCfgGroupsFolder).andRelatedTo(
CoreRelationTypes.PlConfigurationGroup_BranchView, view).follow(
CoreRelationTypes.PlConfigurationGroup_BranchView).asArtifacts();
}
for (ArtifactReadable groupConfig : groupConfigs) {
List<ArtifactReadable> branchViews =
groupConfig.getRelatedList(CoreRelationTypes.PlConfigurationGroup_BranchView);
List<String> viewNames = new ArrayList<>();
for (ArtifactReadable view : branchViews) {
viewNames.add(view.getName());
}
configMap.put(groupConfig.getName(), viewNames);
}
return configMap;
}
private String getProductLinePreferences() {
ArtifactReadable globalPreferences = orcsApi.getQueryFactory().fromBranch(CoreBranches.COMMON).andId(
CoreArtifactTokens.GlobalPreferences).asArtifact();
String preferences = globalPreferences.getSoleAttributeValue(CoreAttributeTypes.ProductLinePreferences, "");
return preferences;
}
private Map<String, FileTypeApplicabilityData> populateFileTypeApplicabilityDataMap(String plPreferences) {
Map<String, FileTypeApplicabilityData> fileTypeApplicabilityDataMap = new HashMap<>();
JsonNode preferencesJson = orcsApi.jaxRsApi().readTree(plPreferences);
JsonNode commentStyles = preferencesJson.findValue("FileExtensionCommentStyle");
Iterator<JsonNode> iter = commentStyles.elements();
while (iter.hasNext()) {
JsonNode currNode = iter.next();
String fileExtension = currNode.findValue("FileExtension").asText();
String commentPrefixRegex = currNode.findValue("CommentPrefixRegex").asText();
JsonNode optionalSuffixRegex = currNode.findValue("CommentSuffixRegex");
String commentSuffixRegex = optionalSuffixRegex == null ? "" : optionalSuffixRegex.asText();
Pattern pattern = createFullPatternFromCommentStyle(commentPrefixRegex, commentSuffixRegex);
String commentPrefix = currNode.findValue("CommentPrefix").asText();
JsonNode optionalSuffix = currNode.findValue("CommentSuffix");
String commentSuffix = optionalSuffix == null ? "" : optionalSuffix.asText();
FileTypeApplicabilityData data = new FileTypeApplicabilityData(pattern, commentPrefixRegex, commentSuffixRegex,
commentPrefix, commentSuffix);
fileTypeApplicabilityDataMap.put(fileExtension.toLowerCase(), data);
}
return fileTypeApplicabilityDataMap;
}
/**
* Using the given comments for the file type, creates an applicability pattern used to match Product Line tagging.
* Places content inside parenthesis to group each type together, uses an OR statement between each potential match
* pattern. Ex. Start Feature or End Feature. Also appends regex after the potential suffix to match any extra
* spaces, plus a single new line character. This is to maintain formatting in the newly written file.
*/
private Pattern createFullPatternFromCommentStyle(String commentPrefix, String commentSuffix) {
String commentedFeatureStart =
"(" + INLINE_WHITESPACE + commentPrefix + BEGINFEATURE + INLINE_WHITESPACE + commentSuffix + COMMENT_EXTRA_CHARS + ")";
String commentedFeatureEnd =
"(" + INLINE_WHITESPACE + commentPrefix + ENDFEATURE + INLINE_WHITESPACE + commentSuffix + COMMENT_EXTRA_CHARS + ")";
String commentedConfigStart =
"(" + INLINE_WHITESPACE + commentPrefix + BEGINCONFIG + INLINE_WHITESPACE + commentSuffix + COMMENT_EXTRA_CHARS + ")";
String commentedConfigEnd =
"(" + INLINE_WHITESPACE + commentPrefix + ENDCONFIG + INLINE_WHITESPACE + commentSuffix + COMMENT_EXTRA_CHARS + ")";
String commentedConfigGrpStart =
"(" + INLINE_WHITESPACE + commentPrefix + BEGINCONFIGGRP + INLINE_WHITESPACE + commentSuffix + COMMENT_EXTRA_CHARS + ")";
String commentedConfigGrpEnd =
"(" + INLINE_WHITESPACE + commentPrefix + ENDCONFIGGRP + INLINE_WHITESPACE + commentSuffix + COMMENT_EXTRA_CHARS + ")";
String pattern =
commentedFeatureStart + "|" + commentedFeatureEnd + "|" + commentedConfigStart + "|" + commentedConfigEnd + "|" + commentedConfigGrpStart + "|" + commentedConfigGrpEnd;
return Pattern.compile(pattern, Pattern.DOTALL | Pattern.MULTILINE);
}
}