class UidlWriter implements Serializable {

    public JsonObject createUidl(UI ui, boolean async, boolean resync) {
        JsonObject response = Json.createObject();

        UIInternals uiInternals = ui.getInternals();

        VaadinSession session = ui.getSession();
        VaadinService service = session.getService();

        // Purge pending access calls as they might produce additional changes
        // to write out
        service.runPendingAccessTasks(session);

        // Paints components
        getLogger().debug("* Creating response to client");

        int syncId = service.getDeploymentConfiguration().isSyncIdCheckEnabled()
                ? uiInternals.getServerSyncId()
                : -1;

        response.put(ApplicationConstants.SERVER_SYNC_ID, syncId);
        if (resync) {
            response.put(ApplicationConstants.RESYNCHRONIZE_ID, true);
        }
        int nextClientToServerMessageId = uiInternals
                .getLastProcessedClientToServerId() + 1;
        response.put(ApplicationConstants.CLIENT_TO_SERVER_ID,
                nextClientToServerMessageId);

        SystemMessages messages = ui.getSession().getService()
                .getSystemMessages(ui.getLocale(), null);

        JsonObject meta = new MetadataWriter().createMetadata(ui, false, async,
                messages);
        if (meta.keys().length > 0) {
            response.put("meta", meta);
        }

        JsonArray stateChanges = Json.createArray();

        encodeChanges(ui, stateChanges);

        populateDependencies(response, uiInternals.getDependencyList(),
                new ResolveContext(service, session.getBrowser()));

        if (uiInternals.getConstantPool().hasNewConstants()) {
            response.put("constants",
                    uiInternals.getConstantPool().dumpConstants());
        }
        if (stateChanges.length() != 0) {
            response.put("changes", stateChanges);
        }

        List<PendingJavaScriptInvocation> executeJavaScriptList = uiInternals
                .dumpPendingJavaScriptInvocations();
        if (!executeJavaScriptList.isEmpty()) {
            response.put(JsonConstants.UIDL_KEY_EXECUTE,
                    encodeExecuteJavaScriptList(executeJavaScriptList));
        }
        if (ui.getSession().getService().getDeploymentConfiguration()
                .isRequestTiming()) {
            response.put("timings", createPerformanceData(ui));
        }
        uiInternals.incrementServerId();
        return response;
    }

}