class ResourceUtils {

    @SuppressWarnings("unchecked")
    public static JAXRSServerFactoryBean createApplication(Application app,
                                                           boolean ignoreAppPath,
                                                           boolean staticSubresourceResolution,
                                                           boolean useSingletonResourceProvider,
                                                           Bus bus) {

        Set<Object> singletons = app.getSingletons();
        verifySingletons(singletons);

        List<Class<?>> resourceClasses = new ArrayList<>();
        List<Object> providers = new ArrayList<>();
        List<Feature> features = new ArrayList<>();
        Map<Class<?>, ResourceProvider> map = new HashMap<>();

        // Note, app.getClasses() returns a list of per-request classes
        // or singleton provider classes
        for (Class<?> cls : app.getClasses()) {
            if (isValidApplicationClass(cls, singletons)) {
                if (isValidProvider(cls)) {
                    providers.add(createProviderInstance(cls));
                } else if (Feature.class.isAssignableFrom(cls)) {
                    features.add(createFeatureInstance((Class<? extends Feature>) cls));
                } else {
                    resourceClasses.add(cls);
                    if (useSingletonResourceProvider) {
                        map.put(cls, new SingletonResourceProvider(createProviderInstance(cls)));
                    } else {
                        map.put(cls, new PerRequestResourceProvider(cls));
                    }
                }
            }
        }

        // we can get either a provider or resource class here
        for (Object o : singletons) {
            if (isValidProvider(o.getClass())) {
                providers.add(o);
            } else if (o instanceof Feature) {
                features.add((Feature) o);
            } else {
                resourceClasses.add(o.getClass());
                map.put(o.getClass(), new SingletonResourceProvider(o));
            }
        }

        JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
        if (bus != null) {
            bean.setBus(bus);
        }

        String address = "/";
        if (!ignoreAppPath) {
            ApplicationPath appPath = locateApplicationPath(app.getClass());
            if (appPath != null) {
                address = appPath.value();
            }
        }
        if (!address.startsWith("/")) {
            address = "/" + address;
        }
        bean.setAddress(address);
        bean.setStaticSubresourceResolution(staticSubresourceResolution);
        bean.setResourceClasses(resourceClasses);
        bean.setProviders(providers);
        bean.getFeatures().addAll(features);
        for (Map.Entry<Class<?>, ResourceProvider> entry : map.entrySet()) {
            bean.setResourceProvider(entry.getKey(), entry.getValue());
        }
        Map<String, Object> appProps = app.getProperties();
        if (appProps != null) {
            bean.getProperties(true).putAll(appProps);
        }
        bean.setApplication(app);
        return bean;
    }

    private  ResourceUtils();

}