package org.fenixedu.bennu.core.api;
import static org.fenixedu.bennu.core.i18n.BundleUtil.getLocalizedString;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.fenixedu.bennu.core.bootstrap.BootstrapError;
import org.fenixedu.bennu.core.bootstrap.BootstrapperRegistry;
import org.fenixedu.bennu.core.bootstrap.SectionsBootstrapper;
import org.fenixedu.bennu.core.bootstrap.SectionsBootstrapper.BootstrapException;
import org.fenixedu.bennu.core.bootstrap.annotations.Bootstrapper;
import org.fenixedu.bennu.core.bootstrap.annotations.Field;
import org.fenixedu.bennu.core.bootstrap.annotations.Section;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.core.domain.exceptions.AuthorizationException;
import org.fenixedu.bennu.core.rest.BennuRestResource;
import org.fenixedu.bennu.core.util.CoreConfiguration;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
@Path("/bennu-core/bootstrap")
public class BootstrapResource extends BennuRestResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response create(final JsonObject json) throws Throwable {
checkApplicationNotBootstrapped();
try {
SectionsBootstrapper.bootstrapAll(json);
return ok();
} catch (BootstrapException e) {
return Response.status(Status.PRECONDITION_FAILED).entity(toJson(createErrors(e.getErrors()))).build();
}
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public JsonObject getData() {
checkApplicationNotBootstrapped();
JsonObject json = new JsonObject();
json.add("bootstrappers", getBootstrappers());
json.add("availableLocales", getLocales());
return json;
}
private void checkApplicationNotBootstrapped() {
if (!Bennu.getInstance().getUserSet().isEmpty()) {
throw AuthorizationException.applicationAlreadyBootstrapped();
}
}
private JsonArray createErrors(Collection<BootstrapError> errors) {
JsonArray json = new JsonArray();
for (BootstrapError error : errors) {
JsonObject errorJson = new JsonObject();
errorJson.add("fieldKey", new JsonPrimitive(error.getFieldKey()));
errorJson.add("message", getLocalizedString(error.getBundle(), error.getMessage()).json());
json.add(errorJson);
}
return json;
}
private JsonArray getLocales() {
JsonArray json = new JsonArray();
for (Locale locale : CoreConfiguration.supportedLocales()) {
JsonObject localeJson = new JsonObject();
localeJson.addProperty("name", locale.getDisplayName(Locale.ENGLISH));
String key = String.format("%s-%s", locale.getLanguage(), locale.getCountry());
localeJson.addProperty("key", key);
json.add(localeJson);
}
return json;
}
private JsonArray getBootstrappers() {
Set<Class<?>> registeredSections = Sets.newHashSet();
JsonArray bootstrappersJson = new JsonArray();
for (Class<?> bootstrapperClass : BootstrapperRegistry.getBootstrappers()) {
List<Class<?>> bootstrapperSections = BootstrapperRegistry.getSections(bootstrapperClass);
Bootstrapper bootstrapper = bootstrapperClass.getAnnotation(Bootstrapper.class);
JsonObject bootstrapperJson = new JsonObject();
JsonArray sectionsJson = new JsonArray();
if (bootstrapperSections != null && !bootstrapperSections.isEmpty()) {
for (Class<?> sectionClass : bootstrapperSections) {
if (!registeredSections.contains(sectionClass)) {
sectionsJson.add(createSection(sectionClass.getAnnotation(Section.class), sectionClass));
registeredSections.add(sectionClass);
}
}
bootstrapperJson.add("name", getLocalizedString(bootstrapper.bundle(), bootstrapper.name()).json());
bootstrapperJson.add(
"description",
getLocalizedString(bootstrapper.bundle(),
bootstrapper.description().isEmpty() ? bootstrapper.name() : bootstrapper.description()).json());
bootstrapperJson.add("sections", sectionsJson);
bootstrappersJson.add(bootstrapperJson);
}
}
return bootstrappersJson;
}
private JsonObject createSection(Section section, Class<?> sectionClass) {
JsonObject json = new JsonObject();
JsonArray fields = new JsonArray();
for (Method method : BootstrapperRegistry.getSectionFields(sectionClass)) {
fields.add(createField(method.getAnnotation(Field.class), method, section.bundle()));
}
json.add("fields", fields);
json.addProperty("key", sectionClass.getName());
json.add("name", getLocalizedString(section.bundle(), section.name()).json());
json.add("description", getLocalizedString(section.bundle(), section.description()).json());
return json;
}
private JsonObject createField(Field field, Method fieldMethod, String bundle) {
JsonObject json = new JsonObject();
JsonArray validValues = new JsonArray();
for (String validValue : field.validValues()) {
validValues.add(new JsonPrimitive(validValue));
}
json.add("validValues", validValues);
json.addProperty("isMandatory", field.isMandatory());
json.addProperty("fieldType", field.fieldType().name());
json.add("name", getLocalizedString(bundle, field.name()).json());
if (!Strings.isNullOrEmpty(field.hint())) {
json.add("hint", getLocalizedString(bundle, field.hint()).json());
}
json.addProperty("defaultValue", field.defaultValue());
json.addProperty("key", fieldMethod.getDeclaringClass().getName() + "." + fieldMethod.getName());
return json;
}
}