* @param <M> the model type that will manage this fxml node
*/
@SuppressWarnings("unchecked")
public static <M extends Model> FXMLComponent loadFXML(final M model, final String fxmlPath, final String bundlePath) {
final FXMLLoader fxmlLoader = new FXMLLoader();
// Use Custom controller factory to attach the root model to the controller
fxmlLoader.setControllerFactory(new DefaultFXMLControllerBuilder(model));
fxmlLoader.setLocation(convertFxmlUrl(model, fxmlPath));
try {
if (bundlePath != null) {
fxmlLoader.setResources(ResourceBundle.getBundle(bundlePath));
}
} catch (final MissingResourceException e) {
LOGGER.log(MISSING_RESOURCE_BUNDLE, e, bundlePath);
}
Node node = null;
boolean error = false;
try {
error = fxmlLoader.getLocation() == null;
if (error) {
node = TextBuilder.create().text(FXML_ERROR_NODE_LABEL.getText(fxmlPath)).build();
} else {
node = (Node) fxmlLoader.load(fxmlLoader.getLocation().openStream());
}
} catch (final IOException e) {
throw new CoreRuntimeException(FXML_NODE_DOESNT_EXIST.getText(fxmlPath), e);
}
final FXMLController<M, ?> fxmlController = (FXMLController<M, ?>) fxmlLoader.getController();
// It's tolerated to have a null controller for an fxml node
if (fxmlController != null) {
// The fxml controller must extends AbstractFXMLController
if (!error && !(fxmlLoader.getController() instanceof AbstractFXMLController)) {
throw new CoreRuntimeException(BAD_FXML_CONTROLLER_ANCESTOR.getText(fxmlLoader.getController().getClass().getCanonicalName()));
}
// Link the View component with the fxml controller
fxmlController.setModel(model);
}