docs: private static Map<String, LibertyFeature> parseFeaturesAndCreateModifiedJson(File jsonFile, File modifiedJsonFile, boolean isWebsphereLiberty) throws MavenRepoGeneratorException {
  		Map<String, LibertyFeature> features = new HashMap<String, LibertyFeature>();
  
  		try {
  			InputStream is = new FileInputStream(jsonFile);
  			String jsonTxt = IOUtils.toString(is, (Charset) null);
  			JsonReader jsonReader = Json.createReader(new StringReader(jsonTxt));
  			JsonArray jsonArray = jsonReader.readArray();
  			jsonReader.close();
  
  			for (int i = 0; i < jsonArray.size(); i++) {
  				JsonObject json = jsonArray.getJsonObject(i);
  
  				JsonObject wlpInfo = json.getJsonObject(Constants.WLP_INFORMATION_KEY);
  
  				JsonArray provideFeatureArray = wlpInfo.getJsonArray(Constants.PROVIDE_FEATURE_KEY);
  				String symbolicName = provideFeatureArray.getString(0);
  
  				String appliesTo = wlpInfo.getString(Constants.APPLIES_TO_KEY);
  				String productVersion = parseProductVersion(appliesTo);
  				if (productVersion == null) {
  					throw new MavenRepoGeneratorException("Cannot parse product version from " + Constants.APPLIES_TO_KEY
  							+ " key for feature " + symbolicName + " in file " + jsonFile.getAbsolutePath());
  				}
  
  				JsonObject wlpInfo2 = json.containsKey(Constants.WLP_INFORMATION_2_KEY) ? json.getJsonObject(Constants.WLP_INFORMATION_2_KEY) : null;
  				boolean isBundle = (wlpInfo2 != null) && wlpInfo2.containsKey(Constants.VISIBILITY_KEY) && Constants.VISIBILITY_VALUE_INSTALL.equals(wlpInfo2.getString(Constants.VISIBILITY_KEY));
  				boolean isPublicFeature = wlpInfo.containsKey(Constants.VISIBILITY_KEY) && Constants.VISIBILITY_VALUE_PUBLIC.equals(wlpInfo.getString(Constants.VISIBILITY_KEY));
  				String shortName = null;
  				if (isBundle || isPublicFeature) {
  					if (wlpInfo.containsKey(Constants.SHORT_NAME_KEY)) {
  						shortName = wlpInfo.getString(Constants.SHORT_NAME_KEY);
  					}
  				}
  
  				// parse requireFeature
  				Map<String, Collection<String>> requireFeaturesWithTolerates = new HashMap<String, Collection<String>>();
  				if (wlpInfo.containsKey(Constants.REQUIRE_FEATURE_KEY)) {
  					JsonArray requireFeatureArray = wlpInfo.getJsonArray(Constants.REQUIRE_FEATURE_KEY);
  					if (requireFeatureArray != null && requireFeatureArray.size() > 0) {
  						for (int j = 0; j < requireFeatureArray.size(); j++) {
  							requireFeaturesWithTolerates.put(requireFeatureArray.getString(j), null);
  						}
  					}
  				}
  				
  				// parse requireFeatureWithTolerates and add to the above map (overwriting any existing null value)
  				if (wlpInfo.containsKey(Constants.REQUIRE_FEATURE_WITH_TOLERATES_KEY)) {
  					JsonArray requireFeatureWithToleratesArray = wlpInfo.getJsonArray(Constants.REQUIRE_FEATURE_WITH_TOLERATES_KEY);
  					if (requireFeatureWithToleratesArray != null && requireFeatureWithToleratesArray.size() > 0) {
  						for (int j = 0; j < requireFeatureWithToleratesArray.size(); j++) {
  							JsonObject requireFeatureWithToleratesObject = requireFeatureWithToleratesArray.getJsonObject(j);
  							String requireFeature = requireFeatureWithToleratesObject.getString(Constants.FEATURE_KEY);
  							if (requireFeatureWithToleratesObject.containsKey(Constants.TOLERATES_KEY)) {
  								JsonArray tolerateArray = requireFeatureWithToleratesObject.getJsonArray(Constants.TOLERATES_KEY);
  								Collection<String> tolerateVersions = new ArrayList<String>();
  								for (int k = 0; k < tolerateArray.size(); k++) {
  									tolerateVersions.add(tolerateArray.getString(k));
  								}
  								requireFeaturesWithTolerates.put(requireFeature, tolerateVersions);
  							} else {
  								requireFeaturesWithTolerates.put(requireFeature, null);
  							}
  						}
  					}
  				}
  
  				String name = json.getString(Constants.NAME_KEY);
  				String description = json.getString(Constants.SHORT_DESCRIPTION_KEY);
  				if (description.equals("%description")){
  					description = name;
  				}
  				
  				String licenseId = json.getString(Constants.LICENSE_ID_KEY);
  				boolean restrictedLicense = licenseId.contains(Constants.LICENSE_ID_RESTRICTED_SUBSTRING);
  				
  				String mavenCoordinates = null;
  				if (wlpInfo.containsKey(Constants.MAVEN_COORDINATES_KEY)) {
  					mavenCoordinates = wlpInfo.getString(Constants.MAVEN_COORDINATES_KEY);
  				}
  
  				LibertyFeature feature = new LibertyFeature(symbolicName, shortName, name, description, requireFeaturesWithTolerates, productVersion, mavenCoordinates, isWebsphereLiberty, restrictedLicense);
  				
  				features.put(symbolicName, feature);
  			}
  			
  			// Add Maven coordinates into a modified copy of the JSON
  			try {
  				addMavenCoordinates(modifiedJsonFile, jsonArray, features);
  			} catch (IOException e) {
  				throw new MavenRepoGeneratorException(
  						"Could not write modified JSON to temporary file " + modifiedJsonFile, e);
  			}
  		} catch (FileNotFoundException e) {
  			throw new MavenRepoGeneratorException("JSON file " + jsonFile + " does not exist.", e);
  		} catch (IOException e) {
  			throw new MavenRepoGeneratorException("Could not parse JSON file " + jsonFile, e);
  		}
  		return features;
  	}