Skip to content

Commit

Permalink
Update AppliesToProcessor for open liberty edition
Browse files Browse the repository at this point in the history
AppliesToProcessor needs to recognize OPEN as a valid edition
and also have an appropriate mapping to a human readable edition.
OPEN features can be installed on any edition apart from CORE

Also do a bit of refactoring to put the parsing logic into a
common method, and make a couple of methods private, as they
clearly should have been
  • Loading branch information
idlewis committed Apr 20, 2018
1 parent d119c75 commit 71cc83c
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
Expand All @@ -33,10 +34,32 @@
*/
public class AppliesToProcessor {

private final static List<String> allEditions = Arrays.asList("Liberty Core", "Base", "Express", "Developers", "ND", "z/OS");
private final static List<String> betaEditions = Arrays.asList("Beta");
// Human readable edition names for display.
private static final String BASE = "Base";
private static final String EXPRESS = "Express";
private static final String DEVELOPERS = "Developers";
private static final String ND = "ND";
private static final String ZOS = "z/OS";
private static final String CORE = "Liberty Core";
private static final String BETA = "Beta";

private final static Map<String, String> editionsMap = new HashMap<String, String>();
/**
* Open liberty features with an edition of OPEN in the appliesTo can be
* installed on everything except CORE.
*/
private final static List<String> nonCoreEditions = Arrays.asList(BASE, EXPRESS, DEVELOPERS, ND, ZOS);
private final static List<String> allEditions;
static {
ArrayList<String> temp = new ArrayList<String>();
// The editions are added in this order to
// a) This is the order we'd like things to appear when displayed to a human
// a) preserve the order they were in originally when there was only one list of all editions
temp.add(CORE);
temp.addAll(nonCoreEditions);
allEditions = Collections.unmodifiableList(temp);
}

private final static Map<String, List<String>> editionsMap = new HashMap<String, List<String>>();
public final static String VERSION_ATTRIB_NAME = "productVersion";
public final static String EDITION_ATTRIB_NAME = "productEdition";
public final static String INSTALL_TYPE_ATTRIB_NAME = "productInstallType";
Expand All @@ -52,20 +75,21 @@ public class AppliesToProcessor {
private final static String EDITION_UNKNOWN = "EDITION_UNKNOWN";

static {
editionsMap.put("Core", "Liberty Core");
editionsMap.put("CORE", "Liberty Core");
editionsMap.put("LIBERTY_CORE", "Liberty Core");
editionsMap.put("BASE", "Base");
editionsMap.put("DEVELOPERS", "Developers");
editionsMap.put("EXPRESS", "Express");
editionsMap.put("EARLY_ACCESS", "Beta");
editionsMap.put("zOS", "z/OS");
editionsMap.put("ND", "ND");
editionsMap.put("BASE_ILAN", EDITION_UNMAPPED);
editionsMap.put("Core", Arrays.asList(CORE));
editionsMap.put("CORE", Arrays.asList(CORE));
editionsMap.put("LIBERTY_CORE", Arrays.asList(CORE));
editionsMap.put("BASE", Arrays.asList(BASE));
editionsMap.put("DEVELOPERS", Arrays.asList(DEVELOPERS));
editionsMap.put("EXPRESS", Arrays.asList(EXPRESS));
editionsMap.put("EARLY_ACCESS", Arrays.asList(BETA));
editionsMap.put("zOS", Arrays.asList(ZOS));
editionsMap.put("ND", Arrays.asList(ND));
editionsMap.put("BASE_ILAN", Arrays.asList(EDITION_UNMAPPED));
editionsMap.put("OPEN", nonCoreEditions);
}
public final static String BETA_REGEX = "[2-9][0-9][0-9][0-9][.].*";

public static String getValue(String substring) {
private static String getValue(String substring) {
int index = substring.indexOf('=');
substring = substring.substring(index + 1).trim();
if (substring.charAt(0) == '"') {
Expand All @@ -75,7 +99,7 @@ public static String getValue(String substring) {
}
}

private static void add(AppliesToFilterInfo atfi, String substring, Map<String, String> helperMap) {
private static void add(AppliesToFilterInfo atfi, String substring) {
substring = substring.trim();
if (atfi.getProductId() == null) {
atfi.setProductId(substring);
Expand Down Expand Up @@ -139,18 +163,18 @@ private static void add(AppliesToFilterInfo atfi, String substring, Map<String,
rawEditions.add(edition);

// Map entries to happier names.
String mappedEdition = mapRawEditionToHumanReadable(edition, helperMap);
if (EDITION_UNMAPPED.equals(mappedEdition)) {
List<String> mappedEdition = mapRawEditionToHumanReadable(edition);
if (mappedEdition.size() == 1 && mappedEdition.get(0).equals(EDITION_UNMAPPED)) {
// In this case, we don't map the edition to anything
} else if (EDITION_UNKNOWN.equals(mappedEdition)) {
} else if (mappedEdition.size() == 1 && mappedEdition.get(0).equals(EDITION_UNKNOWN)) {
// In this case, we don't know about the edition, so map
// it to itself in order to retain the same behaviour as
// the previous version of the code
editions.add(edition);
} else {
// Any other possibility means that this edition maps to something
// good so use that
editions.add(mappedEdition);
editions.addAll(mappedEdition);
}

if (endIndex == -1) {
Expand All @@ -166,38 +190,19 @@ private static void add(AppliesToFilterInfo atfi, String substring, Map<String,

public static List<AppliesToFilterInfo> parseAppliesToHeader(String appliesTo) {
List<AppliesToFilterInfo> result = new ArrayList<AppliesToFilterInfo>();

Map<String, String> editionNameMap = editionsMap;

boolean quoted = false;
int index = 0;
AppliesToFilterInfo match = new AppliesToFilterInfo();
for (int i = 0; i < appliesTo.length(); i++) {
char c = appliesTo.charAt(i);
if (c == '"') {
quoted = !quoted;
}
if (!quoted) {
if (c == ',') {
add(match, appliesTo.substring(index, i), editionNameMap);
index = i + 1;
addEditions(match);
result.add(match);
match = new AppliesToFilterInfo();
} else if (c == ';') {
add(match, appliesTo.substring(index, i), editionNameMap);
index = i + 1;
}
List<List<String>> parsedProducts = doParse(appliesTo);
for (List<String> parsedProduct : parsedProducts) {
AppliesToFilterInfo atfi = new AppliesToFilterInfo();
for (String productChunk : parsedProduct) {
add(atfi, productChunk);
}
addEditions(atfi);
result.add(atfi);
}
add(match, appliesTo.substring(index), editionNameMap);
addEditions(match);
result.add(match);

return result;
}

public static void addEditions(AppliesToFilterInfo match) {
private static void addEditions(AppliesToFilterInfo match) {
List<String> editionsList = allEditions;

// No editions in the appliesTo? That means *all* editions. Note that we need to
Expand All @@ -209,7 +214,7 @@ public static void addEditions(AppliesToFilterInfo match) {

if ((match.getMinVersion() != null) && (match.getMinVersion().getCompatibilityLabel() != null) &&
(match.getMinVersion().getCompatibilityLabel().equals(EARLY_ACCESS_LABEL))) {
editions.addAll(betaEditions);
editions.add(BETA);
} else {
editions.addAll(editionsList);
}
Expand All @@ -223,9 +228,9 @@ public static void addEditions(AppliesToFilterInfo match) {
* if the edition is known but should not be mapped to anything or "" if the edition is now known (ie an
* error case).
*/
private static String mapRawEditionToHumanReadable(String rawEdition, Map<String, String> map) {
String result = map.get(rawEdition);
return result != null ? result : EDITION_UNKNOWN;
private static List<String> mapRawEditionToHumanReadable(String rawEdition) {
List<String> result = editionsMap.get(rawEdition);
return result != null ? result : Arrays.asList(EDITION_UNKNOWN);
}

/**
Expand All @@ -238,7 +243,8 @@ private static String mapRawEditionToHumanReadable(String rawEdition, Map<String
public static void validateEditions(AppliesToFilterInfo info, String appliesToHeader) throws RepositoryResourceCreationException {
if (info.getRawEditions() != null) {
for (String rawEdition : info.getRawEditions()) {
if (EDITION_UNKNOWN.equals(mapRawEditionToHumanReadable(rawEdition, editionsMap))) {
List<String> mappedEditions = mapRawEditionToHumanReadable(rawEdition);
if (mappedEditions.size() == 1 && mappedEditions.get(0).equals(EDITION_UNKNOWN)) {
throw new RepositoryResourceCreationException("Resource applies to at least one unknown edition: " + rawEdition +
"; appliesTo= " + appliesToHeader, null);
}
Expand All @@ -247,19 +253,34 @@ public static void validateEditions(AppliesToFilterInfo info, String appliesToHe
}

/**
* Similiar logic to parseAppliesToHeader above, duplicate logic, be nice to find time to factor this into
* a common routine
*
* @param appliesTo
* @return
* Parse the given raw appliesTo header into a list
* of AppliesToEntry objects
*/
public static List<AppliesToEntry> parseAppliesToEntries(String appliesTo) {
List<AppliesToEntry> result = new ArrayList<AppliesToEntry>();
List<List<String>> parsedProducts = doParse(appliesTo);
for (List<String> parsedProduct : parsedProducts) {
AppliesToEntry entry = new AppliesToEntry();
for (String productChunk : parsedProduct) {
entry.add(productChunk);
}
result.add(entry);
}
return result;
}

/**
* Should be parsing a string that looks like
* "blah;blah;blah,foo;foo;foo,baz;baz;baz"
* into a list of lists, so something like
* <blah,blah,blah>,<foo,foo,foo>,<baz,baz,baz>
*/
private static List<List<String>> doParse(String appliesTo) {
boolean quoted = false;
int index = 0;

AppliesToEntry entry = new AppliesToEntry();
List<String> entry = new ArrayList<String>();
List<List<String>> result = new ArrayList<List<String>>();
for (int i = 0; i < appliesTo.length(); i++) {
char c = appliesTo.charAt(i);
if (c == '"') {
Expand All @@ -268,10 +289,11 @@ public static List<AppliesToEntry> parseAppliesToEntries(String appliesTo) {
if (!quoted) {
if (c == ',') {
entry.add(appliesTo.substring(index, i));
// We've read one applied to entry in. Make sure its ok
// We've read one applies to entry in
// Add to result and start a new one
index = i + 1;
result.add(entry);
entry = new AppliesToEntry();
entry = new ArrayList<String>();
} else if (c == ';') {
entry.add(appliesTo.substring(index, i));
index = i + 1;
Expand All @@ -280,7 +302,6 @@ public static List<AppliesToEntry> parseAppliesToEntries(String appliesTo) {
}
entry.add(appliesTo.substring(index));
result.add(entry);

return result;
}

Expand Down Expand Up @@ -338,4 +359,4 @@ public String toString() {
_version + "> <installType=" + _installType + ">";
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,21 @@ public void testUnknownEdition() {
assertEquals("filter info.editions should have the correct unkonwn edition", "AN_UNKNOWN", atfi.getEditions().get(0));
}

@Test
public void testOpenEdition() {
String appliesToHeader = "com.ibm.cheese-ston; productVersion=8.5.5.4; productEditions=\"OPEN\"";
List<AppliesToFilterInfo> atfis = AppliesToProcessor.parseAppliesToHeader(appliesToHeader);
assertEquals("Expected one filter info to be returned", 1, atfis.size());
AppliesToFilterInfo atfi = atfis.get(0);
assertNotNull("filter info should have edition info", atfi.getEditions());
assertEquals("filter info should have one edition", 5, atfi.getEditions().size());
assertTrue("filter info should contain all editions", atfi.getEditions().contains("Base"));
assertTrue("filter info should contain all editions", atfi.getEditions().contains("Express"));
assertTrue("filter info should contain all editions", atfi.getEditions().contains("Developers"));
assertTrue("filter info should contain all editions", atfi.getEditions().contains("ND"));
assertTrue("filter info should contain all editions", atfi.getEditions().contains("z/OS"));
}

@Test(expected = RepositoryResourceCreationException.class)
public void testValidateUnknownEdition() throws RepositoryResourceCreationException {
String appliesToHeader = "com.ibm.cheese-ston; productVersion=8.5.5.4; productEditions=\"AN_UNKNOWN\"";
Expand Down

0 comments on commit 71cc83c

Please sign in to comment.