private JoinableResourceBundle buildJoinableResourceBundle(PropertiesConfigHelper props, String bundleName,
			String fileExtension, ResourceReaderHandler rsHandler) {

		// Id for the bundle
		String bundleId = props.getCustomBundleProperty(bundleName, PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_ID);

		String bundlePrefix = props.getCustomBundleProperty(bundleName,
				PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_BUNDLE_PREFIX);

		boolean isComposite = props.getCustomBundleBooleanProperty(bundleName,
				PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_COMPOSITE_FLAG);

		InclusionPattern inclusionPattern = getInclusionPattern(props, bundleName);
		JoinableResourceBundleImpl bundle = null;
		if (isComposite) {
			List<JoinableResourceBundle> nestedBundles = new ArrayList<>();
			List<String> nestedBundleNames = props.getCustomBundlePropertyAsList(bundleName,
					PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_COMPOSITE_NAMES);
			for (String nestedBundleName : nestedBundleNames) {
				JoinableResourceBundle nestedBundle = buildJoinableResourceBundle(props, nestedBundleName,
						fileExtension, rsHandler);
				nestedBundles.add(nestedBundle);
			}
			bundle = new CompositeResourceBundle(bundleId, bundleName, nestedBundles, inclusionPattern, rsHandler,
					bundlePrefix, fileExtension, generatorRegistry);
		} else {

			bundle = new JoinableResourceBundleImpl(bundleId, bundleName, bundlePrefix, fileExtension, inclusionPattern,
					rsHandler, generatorRegistry);
		}

		// Override bundle postprocessor
		String bundlePostProcessors = props.getCustomBundleProperty(bundleName,
				PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_POSTPROCESSOR);
		if (StringUtils.isNotEmpty(bundlePostProcessors)) {
			bundle.setBundlePostProcessor(chainFactory.buildPostProcessorChain(bundlePostProcessors));
		}

		// Override unitary postprocessor
		String unitaryPostProcessors = props.getCustomBundleProperty(bundleName,
				PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_FILE_POSTPROCESSOR);
		if (StringUtils.isNotEmpty(unitaryPostProcessors)) {
			bundle.setUnitaryPostProcessor(chainFactory.buildPostProcessorChain(unitaryPostProcessors));
		}

		// Set conditional comment for IE, in case one is specified
		String explorerConditionalCondition = props.getCustomBundleProperty(bundleName,
				PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_IE_CONDITIONAL_EXPRESSION);
		if (StringUtils.isNotEmpty(explorerConditionalCondition)) {
			bundle.setExplorerConditionalExpression(explorerConditionalCondition);
		}

		// Sets the alternate URL for production mode.
		String alternateProductionURL = props.getCustomBundleProperty(bundleName,
				PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_PRODUCTION_ALT_URL);
		if (StringUtils.isNotEmpty(alternateProductionURL)) {
			bundle.setAlternateProductionURL(props.getCustomBundleProperty(bundleName,
					PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_PRODUCTION_ALT_URL));
		}

		boolean hasDebugURL = false;
		// Sets the debug URL for debug mode.
		if (null != props.getCustomBundleProperty(bundleName, BUNDLE_FACTORY_CUSTOM_DEBUG_URL)) {
			bundle.setDebugURL(props.getCustomBundleProperty(bundleName, BUNDLE_FACTORY_CUSTOM_DEBUG_URL));
			hasDebugURL = true;
			if (StringUtils.isEmpty(bundle.getAlternateProductionURL())) {
				throw new IllegalArgumentException("The bundle '" + bundleName
						+ "', which use a static external resource in debug mode, must use an external resource in Production mode.\n"
						+ "Please check your configuration. ");
			}

			if (StringUtils.isNotEmpty(props.getCustomBundleProperty(bundleName, BUNDLE_FACTORY_CUSTOM_MAPPINGS))) {
				throw new IllegalArgumentException("The bundle '" + bundleName
						+ "', which use a static external resource in debug mode, can't have a bundle mapping.\n"
						+ "Please check your configuration. ");
			}
		}

		// Sets the licence path lists.
		Set<String> licencePathList = props.getCustomBundlePropertyAsSet(bundleName,
				PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_LICENCE_PATH_LIST);
		if (!licencePathList.isEmpty()) {
			bundle.setLicensesPathList(licencePathList);
		}

		List<String> mappings = props.getCustomBundlePropertyAsList(bundleName,
				PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_MAPPINGS);
		if (!hasDebugURL && mappings.isEmpty() && !bundle.isComposite()) {
			throw new IllegalArgumentException("No mappings were defined for the bundle with name: " + bundleName
					+ ". Please specify at least one in configuration. ");
		}

		if (!hasDebugURL) {

			// Add the mappings
			bundle.setMappings(mappings);

			Map<String, VariantSet> variants = props.getCustomBundleVariantSets(bundleName);
			bundle.setVariants(variants);

			// Checks if the bundle files have been modified
			verifyIfBundleIsModified(bundle, mappings, props);
			if (!bundle.isDirty()) {
				for (String variantKey : bundle.getVariantKeys()) {
					if (StringUtils.isNotEmpty(variantKey)) {
						String hashcode = props.getCustomBundleProperty(bundleName,
								PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_HASHCODE_VARIANT + variantKey);
						bundle.setBundleDataHashCode(variantKey, hashcode);
					}
				}

				String hashcode = props.getCustomBundleProperty(bundleName,
						PropertiesBundleConstant.BUNDLE_FACTORY_CUSTOM_HASHCODE);
				bundle.setBundleDataHashCode(null, hashcode);
			}
		}

		return bundle;
	}
private JoinableResourceBundle buildJoinableResourceBundle ( PropertiesConfigHelper props , String bundleName , String fileExtension , ResourceReaderHandler rsHandler ) { String bundleId = props . getCustomBundleProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_ID ) ; String bundlePrefix = props . getCustomBundleProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_BUNDLE_PREFIX ) ; boolean isComposite = props . getCustomBundleBooleanProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_COMPOSITE_FLAG ) ; InclusionPattern inclusionPattern = getInclusionPattern ( props , bundleName ) ; JoinableResourceBundleImpl bundle = null ; if ( isComposite ) { List < JoinableResourceBundle > nestedBundles = new ArrayList < > ( ) ; List < String > nestedBundleNames = props . getCustomBundlePropertyAsList ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_COMPOSITE_NAMES ) ; for ( String nestedBundleName : nestedBundleNames ) { JoinableResourceBundle nestedBundle = buildJoinableResourceBundle ( props , nestedBundleName , fileExtension , rsHandler ) ; nestedBundles . add ( nestedBundle ) ; } bundle = new CompositeResourceBundle ( bundleId , bundleName , nestedBundles , inclusionPattern , rsHandler , bundlePrefix , fileExtension , generatorRegistry ) ; } else { bundle = new JoinableResourceBundleImpl ( bundleId , bundleName , bundlePrefix , fileExtension , inclusionPattern , rsHandler , generatorRegistry ) ; } String bundlePostProcessors = props . getCustomBundleProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_POSTPROCESSOR ) ; if ( StringUtils . isNotEmpty ( bundlePostProcessors ) ) { bundle . setBundlePostProcessor ( chainFactory . buildPostProcessorChain ( bundlePostProcessors ) ) ; } String unitaryPostProcessors = props . getCustomBundleProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_FILE_POSTPROCESSOR ) ; if ( StringUtils . isNotEmpty ( unitaryPostProcessors ) ) { bundle . setUnitaryPostProcessor ( chainFactory . buildPostProcessorChain ( unitaryPostProcessors ) ) ; } String explorerConditionalCondition = props . getCustomBundleProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_IE_CONDITIONAL_EXPRESSION ) ; if ( StringUtils . isNotEmpty ( explorerConditionalCondition ) ) { bundle . setExplorerConditionalExpression ( explorerConditionalCondition ) ; } String alternateProductionURL = props . getCustomBundleProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_PRODUCTION_ALT_URL ) ; if ( StringUtils . isNotEmpty ( alternateProductionURL ) ) { bundle . setAlternateProductionURL ( props . getCustomBundleProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_PRODUCTION_ALT_URL ) ) ; } boolean hasDebugURL = false ; if ( null != props . getCustomBundleProperty ( bundleName , BUNDLE_FACTORY_CUSTOM_DEBUG_URL ) ) { bundle . setDebugURL ( props . getCustomBundleProperty ( bundleName , BUNDLE_FACTORY_CUSTOM_DEBUG_URL ) ) ; hasDebugURL = true ; if ( StringUtils . isEmpty ( bundle . getAlternateProductionURL ( ) ) ) { throw new IllegalArgumentException ( "The bundle '" + bundleName + "', which use a static external resource in debug mode, must use an external resource in Production mode.\n" + "Please check your configuration. " ) ; } if ( StringUtils . isNotEmpty ( props . getCustomBundleProperty ( bundleName , BUNDLE_FACTORY_CUSTOM_MAPPINGS ) ) ) { throw new IllegalArgumentException ( "The bundle '" + bundleName + "', which use a static external resource in debug mode, can't have a bundle mapping.\n" + "Please check your configuration. " ) ; } } Set < String > licencePathList = props . getCustomBundlePropertyAsSet ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_LICENCE_PATH_LIST ) ; if ( ! licencePathList . isEmpty ( ) ) { bundle . setLicensesPathList ( licencePathList ) ; } List < String > mappings = props . getCustomBundlePropertyAsList ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_MAPPINGS ) ; if ( ! hasDebugURL && mappings . isEmpty ( ) && ! bundle . isComposite ( ) ) { throw new IllegalArgumentException ( "No mappings were defined for the bundle with name: " + bundleName + ". Please specify at least one in configuration. " ) ; } if ( ! hasDebugURL ) { bundle . setMappings ( mappings ) ; Map < String , VariantSet > variants = props . getCustomBundleVariantSets ( bundleName ) ; bundle . setVariants ( variants ) ; verifyIfBundleIsModified ( bundle , mappings , props ) ; if ( ! bundle . isDirty ( ) ) { for ( String variantKey : bundle . getVariantKeys ( ) ) { if ( StringUtils . isNotEmpty ( variantKey ) ) { String hashcode = props . getCustomBundleProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_HASHCODE_VARIANT + variantKey ) ; bundle . setBundleDataHashCode ( variantKey , hashcode ) ; } } String hashcode = props . getCustomBundleProperty ( bundleName , PropertiesBundleConstant . BUNDLE_FACTORY_CUSTOM_HASHCODE ) ; bundle . setBundleDataHashCode ( null , hashcode ) ; } } return bundle ; }
Create a JoinableResourceBundle based on the properties file.

@param props
the properties config helper
@param bundleName
the bundle name
@param rsHandler
the resource handler
@return the Resource Bundle