package controllers; import static play.data.Form.form; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import models.Collection; import models.Subject; import models.Target; import models.Taxonomy; import models.User; import org.apache.commons.lang3.StringUtils; import play.Logger; import play.data.DynamicForm; import play.data.Form; import play.data.validation.ValidationError; import play.libs.Json; import play.mvc.BodyParser; import play.mvc.Result; import play.mvc.Security; import uk.bl.Const; import uk.bl.api.Utils; import views.html.subjects.*; import com.avaje.ebean.Ebean; import com.avaje.ebean.Page; import com.fasterxml.jackson.databind.JsonNode; @Security.Authenticated(SecuredController.class) public class SubjectController extends AbstractController { final static Form<Subject> subjectForm = new Form<Subject>(Subject.class); /** * Display the subjects. */ public static Result index() { Logger.debug("Subjects.index()"); return GO_HOME; } public static Result GO_HOME = redirect(routes.SubjectController.list(0, "name", "asc", "")); /** * Display the paginated list of subjects. * * @param page * Current page number (starts from 0) * @param sortBy * Column to be sorted * @param order * Sort order (either asc or desc) * @param filter * Filter applied on target urls */ public static Result list(int pageNo, String sortBy, String order, String filter) { JsonNode node = getSubjectsDataByFilter(filter); Page<Subject> pages = Subject.pager(pageNo, 10, sortBy, order, filter); return ok(list.render("Subjects", User.findByEmail(request().username()), filter, pages, sortBy, order, node)); } /** * This method enables searching for given URL and redirection in order to * add new entry if required. * * @return */ public static Result search() { DynamicForm form = form().bindFromRequest(); String action = form.get("action"); String query = form.get(Const.URL); Logger.debug("action: " + action); Logger.debug("subjects search() query: " + query); if (StringUtils.isBlank(query)) { Logger.debug("Subject name is empty. Please write name in search window."); flash("message", "Please enter a name in the search window"); return redirect( routes.SubjectController.list(0, "name", "asc", "") ); } int pageNo = Integer.parseInt(form.get(Const.PAGE_NO)); String sort = form.get(Const.SORT_BY); String order = form.get(Const.ORDER); if (StringUtils.isEmpty(action)) { return badRequest("You must provide a valid action"); } else { if (Const.SEARCH.equals(action)) { return redirect(routes.SubjectController.list(pageNo, sort, order, query)); } else { return badRequest("This action is not allowed"); } } } @BodyParser.Of(BodyParser.Json.class) public static Result filterByJson(String name) { JsonNode jsonData = null; if (name != null) { List<Taxonomy> subjects = Taxonomy.filterSubjectsByName(name); jsonData = Json.toJson(subjects); } return ok(jsonData); } public static Result view(Long id) { Subject subject = Subject.findById(id); if (subject == null) return notFound("There is no Subject with ID " + id); User user = User.findByEmail(request().username()); return ok(view.render(subject, user)); } public static Result newForm() { User user = User.findByEmail(request().username()); JsonNode node = getSubjectsData(); Form<Subject> subjectForm = Form.form(Subject.class); Subject subject = new Subject(); subjectForm = subjectForm.fill(subject); return ok(newForm.render(subjectForm, user, node)); } public static Result edit(Long id) { Subject subject = Subject.findById(id); if (subject == null) return notFound("There is no Subject with ID " + id); User user = User.findByEmail(request().username()); if( subject.description != null ) { subject.description = subject.description.replace("<p>", "").replace("</p>", "").replace("<br />", "\n").replace("<br>", "\n"); } List<Subject> thisSubject = new ArrayList<Subject>(); thisSubject.add((Subject)subject.parent); JsonNode node = getSubjectsData(thisSubject); Form<Subject> subjectForm = Form.form(Subject.class); subjectForm = subjectForm.fill(subject); Logger.debug("id: " + subjectForm.get().id); return ok(edit.render(subjectForm, user, id, node)); } public static Result info(Form<Subject> form, Long id) { Logger.debug("info"); User user = User.findByEmail(request().username()); List<Subject> thisSubject = new ArrayList<Subject>(); Subject subject = form.get(); thisSubject.add(subject); JsonNode node = getSubjectsData(thisSubject); return badRequest(edit.render(form, user, id, node)); } public static Result newInfo(Form<Subject> form) { User user = User.findByEmail(request().username()); JsonNode node = getSubjectsData(); return badRequest(newForm.render(form, user, node)); } public static Result save() { DynamicForm requestData = form().bindFromRequest(); String action = requestData.get("action"); Logger.debug("action: " + action); if (StringUtils.isNotEmpty(action)) { if (action.equals("save")) { Form<Subject> filledForm = form(Subject.class).bindFromRequest(); if(filledForm.hasErrors()) { Logger.debug("errors: " + filledForm.errors()); return newInfo(filledForm); } String subjectSelect = requestData.get("subjectSelect").replace("\"", ""); Logger.debug("subjectSelect: " + subjectSelect); if (StringUtils.isNotEmpty(subjectSelect)) { String[] subjects = subjectSelect.split(", "); if (subjects.length == 1) { Long subjectId = Long.valueOf(subjects[0]); Subject subject = Subject.findById(subjectId); filledForm.get().parent = subject; Logger.debug("looking good"); } else if (subjects.length > 1) { Logger.debug("Please select only one parent."); flash("message", "Please select only one parent."); return newInfo(filledForm); } } filledForm.get().save(); flash("message", "Subject " + filledForm.get().name + " has been created"); return redirect(routes.SubjectController.view(filledForm.get().id)); } } return null; } public static Result update(Long id) { DynamicForm requestData = form().bindFromRequest(); Form<Subject> filledForm = form(Subject.class).bindFromRequest(); Logger.debug("hasGlobalErrors: " + filledForm.hasGlobalErrors()); Logger.debug("hasErrors: " + filledForm.hasErrors()); String action = requestData.get("action"); Logger.debug("action: " + action); if (StringUtils.isNotEmpty(action)) { if (action.equals("save")) { if (filledForm.hasErrors()) { Logger.debug("hasErrors: " + filledForm.errors()); return info(filledForm, id); } String subjectSelect = requestData.get("subjectSelect").replace("\"", ""); Logger.debug("subjectSelect: " + subjectSelect); if (StringUtils.isNotEmpty(subjectSelect)) { String[] subjects = subjectSelect.split(", "); if (subjects.length == 1) { Long subjectId = Long.valueOf(subjects[0]); if (subjectId.longValue() == id.longValue()) { Logger.debug("same id"); ValidationError e = new ValidationError("subjectSelect", "It is not possible to assign a node to itself as a parent. Please select one parent."); filledForm.reject(e); return info(filledForm, id); } else { Subject subject = Subject.findById(subjectId); filledForm.get().parent = subject; Logger.debug("looking good"); } } else if (subjects.length > 1) { Logger.debug("Please select only one parent."); flash("message", "Please select only one parent."); return info(filledForm, id); } } // Check if the 'publish' field is empty, which corresponds to 'false': if( filledForm.get().publish == null ) { filledForm.get().publish = false; } filledForm.get().update(id); flash("message", "Collection " + filledForm.get().name + " has been updated"); return redirect(routes.SubjectController.view(filledForm.get().id)); } else if (action.equals("delete")) { Subject subject = Subject.findById(id); flash("message", "Subject " + filledForm.get().name + " has been deleted"); subject.delete(); return redirect(routes.SubjectController.index()); } } return null; } /** * This method demonstrates targets associated with given subject. * @param url The URL identifier for subject * @return */ public static Result sites(Long id) { return redirect(routes.TargetController.subjectTargets(0, Const.TITLE, Const.ASC, "", id)); } /** * * @return */ @BodyParser.Of(BodyParser.Json.class) public static Result getAllSubjects() { List<Subject> subjects = Subject.getFirstLevelSubjects(); if( subjects == null || subjects.size() == 0 ) { Logger.info("No subjects found!"); return notFound("No subjects in database!"); } Logger.info("Found " + subjects.size() + " subjects."); JsonNode jsonData = Json.toJson(subjects); return ok(jsonData); } /** * This method presents subjects in a tree form. * @param url * @return */ private static JsonNode getSubjectsTreeByUrl(String url) { JsonNode jsonData = null; final StringBuffer sb = new StringBuffer(); List<Taxonomy> parentSubjects = Taxonomy.findListByTypeSorted(Const.SUBJECT); if (url != null && url.length() > 0) { try { Taxonomy subject = Taxonomy.findByUrl(url); if (subject != null) { // url = subject.parent.id; } } catch (Exception e) { Logger.debug("New subject has no parent yet."); } } sb.append(getSubjectTreeElementsExt(parentSubjects, url, true)); // Logger.debug("collections main level size: " + suggestedCollections.size()); jsonData = Json.toJson(Json.parse(sb.toString())); // Logger.debug("getCollections() json: " + jsonData.toString()); return jsonData; } /** * This method calculates first order subjects. * @param subjectList The list of all subjects * @param url This is an identifier for current subject object * @param parent This parameter is used to differentiate between root and children nodes * @return collection object in JSON form */ public static String getSubjectTreeElementsExt(List<Taxonomy> subjectList, String url, boolean parent) { // Logger.debug("getSubjectTreeElements() URL: " + url); String res = ""; if (subjectList.size() > 0) { final StringBuffer sb = new StringBuffer(); sb.append("["); if (parent) { sb.append("{\"title\": \"" + "None" + "\"," + checkNone(url) + " \"key\": \"" + "None" + "\"" + "}, "); } Iterator<Taxonomy> itr = subjectList.iterator(); boolean firstTime = true; while (itr.hasNext()) { Taxonomy subject = itr.next(); // Logger.debug("add subject: " + subject.name + ", with url: " + subject.url + // ", parent:" + subject.parent + ", parent size: " + subject.parent.length()); // if ((parent && subject.parent == null) || !parent || subject.parent == null) { // if (firstTime) { // firstTime = false; // } else { // sb.append(", "); // } //// Logger.debug("added"); // sb.append("{\"title\": \"" + subject.name + "\"," + checkSelection(subject.name, url) + // " \"key\": \"" + subject.url + "\"" + // getSubjectChildren(subject.url, url) + "}"); // } } // Logger.debug("subjectList level size: " + subjectList.size()); sb.append("]"); res = sb.toString(); // Logger.debug("getSubjectTreeElements() res: " + res); } return res; } /** * Check if none value is selected * @param url This is an identifier for current subject object * @return */ public static String checkNone(String url) { String res = ""; if (StringUtils.isNotEmpty(url) && url.toLowerCase().equals(Const.NONE.toLowerCase())) { res = "\"select\": true ,"; } return res; } /** * Mark subjects that are stored in target object as selected * @param subjectUrl The subject identifier * @param currentUrl This is an identifier for current subject object * @return */ public static String checkSelection(String subjectUrl, String currentUrl) { String res = ""; if (currentUrl.contains(Const.COMMA)) { currentUrl = currentUrl.replace(Const.COMMA, Const.COMMA + " "); // in database entry with comma has additional space after comma } // Logger.debug("checkSelection() 1: " + subjectUrl + ", 2: " + currentUrl); if (currentUrl != null && currentUrl.length() > 0) { if (currentUrl.equals(subjectUrl) || currentUrl.equals(subjectUrl)) { res = "\"select\": true ,"; } } return res; } /** * This method calculates subject children - objects that have parents. * @param url The identifier for parent * @param currentUrl This is an identifier for current subject object * @return child subject in JSON form */ public static String getSubjectChildren(String url, String currentUrl) { // Logger.debug("getChildren() target URL: " + targetUrl); String res = ""; final StringBuffer sb = new StringBuffer(); sb.append(", \"children\":"); // List<Taxonomy> childSubjectList = Taxonomy.findListByType(Const.SUBSUBJECT); // List<Taxonomy> childSubjectList = Taxonomy.getChildLevelSubjects(url); Taxonomy subject = Taxonomy.findByUrl(url); List<Taxonomy> childSubjectList = Taxonomy.findSubSubjectsList(subject.name); // List<Taxonomy> childSubjectList = Taxonomy.getChildLevelSubjects(subject.name); if (childSubjectList.size() > 0) { sb.append(getSubjectTreeElementsExt(childSubjectList, currentUrl, false)); res = sb.toString(); // Logger.debug("getChildren() res: " + res); } return res; } }