package com.gentics.mesh.context;

import static com.gentics.mesh.core.rest.error.Errors.error;
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
import static org.apache.commons.lang3.StringUtils.isEmpty;

import java.util.HashMap;
import java.util.Map;

import com.gentics.mesh.core.data.Project;
import com.gentics.mesh.core.data.Release;
import com.gentics.mesh.core.rest.common.RestModel;
import com.gentics.mesh.json.JsonUtil;

import io.netty.handler.codec.http.HttpResponseStatus;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;

/**
 * Abstract class for internal action context.
 */
public abstract class AbstractInternalActionContext extends AbstractActionContext implements InternalActionContext {

	@Override
	public void send(RestModel restModel, HttpResponseStatus status) {
		send(JsonUtil.toJson(restModel), status);
	}

	@Override
	public <T> Handler<AsyncResult<T>> errorHandler() {
		Handler<AsyncResult<T>> handler = t -> {
			if (t.failed()) {
				fail(t.cause());
			}
		};
		return handler;
	}

	/**
	 * Cache for project specific releases.
	 */
	private Map<Project, Release> releaseCache = new HashMap<>();

	@Override
	public Release getRelease(Project project) {
		return releaseCache.computeIfAbsent(project, p -> {
			if (p == null) {
				p = getProject();
			}
			if (p == null) {
				// TODO i18n
				throw error(INTERNAL_SERVER_ERROR, "Cannot get release without a project");
			}

			Release release = null;

			String releaseNameOrUuid = getVersioningParameters().getRelease();
			if (!isEmpty(releaseNameOrUuid)) {
				release = p.getReleaseRoot().findByUuid(releaseNameOrUuid);
				if (release == null) {
					release = p.getReleaseRoot().findByName(releaseNameOrUuid);
				}
				if (release == null) {
					throw error(BAD_REQUEST, "release_error_not_found", releaseNameOrUuid);
				}
			} else {
				release = p.getLatestRelease();
			}

			return release;
		});
	}

}

@@ -325,20 +325,16 @@
 va.util.
-Hash
 Map;%0Aimp
@@ -343,24 +343,49 @@
 t java.util.
+concurrent.ConcurrentHash
 Map;%0A%0Aimport
@@ -1258,16 +1258,26 @@
 e = new 
+Concurrent
 HashMap%3C
@@ -1281,16 +1281,16 @@
 ap%3C%3E();%0A
-
 %0A%09@Overr
@@ -1339,16 +1339,72 @@
 ject) %7B%0A
+%09%09if (project == null) %7B%0A%09%09%09project = getProject();%0A%09%09%7D%0A
 %09%09return
@@ -1473,55 +1473,8 @@
 ) %7B%0A
-%09%09%09%09p = getProject();%0A%09%09%09%7D%0A%09%09%09if (p == null) %7B%0A
 %09%09%09%09

Fix concurrency issue within action context