package marubinotto.piggydb.ui.page.common;
import static marubinotto.util.CollectionUtils.set;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import java.util.List;
import java.util.Map;
import marubinotto.piggydb.model.Fragment;
import marubinotto.piggydb.model.ModelUtils;
import marubinotto.piggydb.model.Tag;
import marubinotto.piggydb.model.enums.FragmentField;
import marubinotto.piggydb.model.exception.DuplicateException;
import marubinotto.piggydb.model.exception.NoSuchEntityException;
import marubinotto.piggydb.model.query.FragmentsByIds;
import marubinotto.piggydb.model.query.FragmentsSortOption;
import marubinotto.piggydb.ui.page.control.form.PublicFieldForm;
import marubinotto.piggydb.ui.page.model.SelectedFragments;
import marubinotto.piggydb.ui.page.partial.AbstractFragments;
import marubinotto.util.message.CodedException;
import marubinotto.util.procedure.Procedure;
import net.sf.click.Context;
import net.sf.click.control.HiddenField;
import org.apache.commons.lang.StringUtils;
public abstract class AbstractFragmentsPage extends AbstractBorderPage {
public AbstractFragmentsPage() {
}
protected String getAtomUrl() {
return null;
}
protected String getDefaultAtomUrl() {
return StringUtils.replace(getFullPageUrl(), ".htm", ".atom");
}
//
// Model
//
public static final String MK_ATOM_URL = "atomUrl";
public static final String MK_HIGHLIGHTED_FRAGMENT = "highlightedFragment";
private static final String SK_HIGHLIGHTED_FRAGMENT = "highlightedFragment";
public Boolean fragmentOperations = true;
public List<FragmentField> fragmentFields = FragmentField.getEnumList();
public Integer fragmentsViewScale;
public Integer fragmentsViewOrderBy;
public Boolean fragmentsViewAscending;
@Override
protected void setModels() throws Exception {
super.setModels();
String atomUrl = getAtomUrl();
if (atomUrl != null) addModel(MK_ATOM_URL, atomUrl);
importCss("style/piggydb-tags.css", true, null);
importCss("click/tree/tree.css", false, null);
importBottomJs("js/vendor/highlightRegex.js", true);
importBottomJs("js/piggydb.widget.QuickEdit.js", true);
importBottomJs("js/piggydb.widget.ContentToggle.js", true);
importBottomJs("js/piggydb.widget.FragmentTree.js", true);
importBottomJs("js/piggydb.widget.FragmentsView.js", true);
importBottomJs("js/piggydb.widget.tags.js", true);
if (showsSelectedFragments()) setSelectedFragments();
setHighlightedFragment();
this.fragmentsViewScale = (Integer)
getContext().getSessionAttribute(AbstractFragments.SK_SCALE);
if (this.fragmentsViewScale == null)
this.fragmentsViewScale = getWarSetting().getDefaultFragmentsViewScale();
setFragmentsViewSortOption();
}
protected boolean showsSelectedFragments() {
return true;
}
public void highlightFragment(Long id) {
getContext().setFlashAttribute(SK_HIGHLIGHTED_FRAGMENT, id);
}
public static void highlightFragment(Long id, Context context) {
context.setFlashAttribute(SK_HIGHLIGHTED_FRAGMENT, id);
}
private void setHighlightedFragment() {
Long id = (Long)getContext().getSessionAttribute(SK_HIGHLIGHTED_FRAGMENT);
if (id != null) addModel(MK_HIGHLIGHTED_FRAGMENT, id);
}
private void setFragmentsViewSortOption() {
FragmentsSortOption defaultSortOption = FragmentsSortOption.getDefault();
this.fragmentsViewOrderBy = (Integer)
getContext().getSessionAttribute(AbstractFragments.SK_ORDERBY);
if (this.fragmentsViewOrderBy == null)
this.fragmentsViewOrderBy = defaultSortOption.orderBy.getValue();
this.fragmentsViewAscending = (Boolean)
getContext().getSessionAttribute(AbstractFragments.SK_ASCENDING);
if (this.fragmentsViewAscending == null)
this.fragmentsViewAscending = defaultSortOption.ascending;
}
//
// Control
//
protected void addParameterToCommonForms(String name, Object value) {
this.createRelationForm.add(new HiddenField(name, value));
this.createRelationsToSelectedForm.add(new HiddenField(name, value));
this.removeTagForm.add(new HiddenField(name, value));
this.addTagForm.add(new HiddenField(name, value));
this.addTagsToSelectedForm.add(new HiddenField(name, value));
this.removeBookmarkForm.add(new HiddenField(name, value));
}
// Create a relation
public static class CreateRelationForm extends PublicFieldForm {
public CreateRelationForm(Object listener, String method) {
super(listener, method);
}
public HiddenField fromId = new HiddenField("fromId", Long.class);
public HiddenField toId = new HiddenField("toId", Long.class);
public HiddenField forward = new HiddenField("forward", String.class);
public HiddenField backward = new HiddenField("backward", String.class);
}
public CreateRelationForm createRelationForm = new CreateRelationForm(this, "onCreateRelation");
public final boolean onCreateRelation() throws Exception {
// [param] fromId, toId
final Long fromId = (Long)this.createRelationForm.fromId.getValueObject();
final Long toId = (Long)this.createRelationForm.toId.getValueObject();
if (fromId == null || toId == null) {
setRedirectToThisPage();
return false;
}
if (fromId.equals(toId)) {
setRedirectToThisPage(getMessage("cannot-relate-to-itself"));
return false;
}
// [param] forward, backward
final String forward = this.createRelationForm.forward.getValue();
final String backward = this.createRelationForm.backward.getValue();
if (isBlank(forward) && isBlank(backward)) {
setRedirectToThisPage();
return false;
}
try {
getDomain().getTransaction().execute(new Procedure() {
public Object execute(Object input) throws Exception {
if (isNotBlank(forward)) createRelation(fromId, toId);
if (isNotBlank(backward)) createRelation(toId, fromId);
return null;
}
});
}
catch (CodedException e) {
setRedirectToThisPage(getMessage(e));
return false;
}
catch (NoSuchEntityException e) {
setRedirectToThisPage(getMessage("no-such-fragment", e.id));
return false;
}
// Get the node fragments for a result message
FragmentsByIds query = (FragmentsByIds)
getDomain().getFragmentRepository().getQuery(FragmentsByIds.class);
query.setIds(set(fromId, toId));
Map<Long, Fragment> fragments = ModelUtils.toIdMap(query.getAll());
Fragment from = fragments.get(fromId);
Fragment to = fragments.get(toId);
if (from == null || to == null) {
// [rare case] either of the fragments has been deleted just after created
// the relation
setRedirectToThisPage();
return false;
}
setRedirectToThisPage(
getMessage(
"completed-create-relation",
new Object[]{
this.html.fragmentInMessage(from),
this.html.fragmentInMessage(to)},
false));
return false;
}
private void createRelation(long from, long to)
throws NoSuchEntityException, Exception {
try {
getDomain().getFragmentRepository().createRelation(from, to, getUser());
}
catch (DuplicateException e) {
// Ignore duplication
}
}
// Create relations to the selected fragments
public static class CreateRelationsToSelectedForm extends PublicFieldForm {
public CreateRelationsToSelectedForm(Object listener, String method) {
super(listener, method);
}
public HiddenField fromId = new HiddenField("fromId", Long.class);
}
public CreateRelationsToSelectedForm createRelationsToSelectedForm =
new CreateRelationsToSelectedForm(this, "onCreateRelationsToSelected");
public final boolean onCreateRelationsToSelected() throws Exception {
// from
final Long fromId = (Long)this.createRelationsToSelectedForm.fromId.getValueObject();
if (fromId == null) {
setRedirectToThisPage();
return false;
}
// to
final SelectedFragments selected = getSession().getSelectedFragments();
if (selected.isEmpty()) {
setRedirectToThisPage(getMessage("no-selected-fragments"));
return false;
}
Integer relationCount = (Integer)getDomain().getTransaction().execute(new Procedure() {
public Object execute(Object input) throws Exception {
Integer count = 0;
getLogger().info("Create relations from #" + fromId + " {");
for (long toId : selected) {
if (fromId == toId) {
getLogger().info(" Cannot relate itself");
continue;
}
try {
getDomain().getFragmentRepository().createRelation(fromId, toId, getUser());
count++;
getLogger().info(" → #" + toId);
}
catch (NoSuchEntityException e) {
getLogger().info(" No such fragment: #" + e.id);
continue;
}
catch (DuplicateException e) {
getLogger().info(" Duplicate relation: #" + toId);
continue;
}
}
getLogger().info("}");
return count;
}
});
setRedirectToThisPage(
getMessage("completed-create-relations-to-selected",
new Object[]{relationCount}));
return false;
}
// Remove a tag
public static class RemoveTagForm extends PublicFieldForm {
public RemoveTagForm(Object listener, String method) {
super(listener, method);
}
public HiddenField fragmentId = new HiddenField("fragmentId", Long.class);
public HiddenField tagName = new HiddenField("tagName", String.class);
}
public RemoveTagForm removeTagForm = new RemoveTagForm(this, "onRemoveTag");
public final boolean onRemoveTag() throws Exception {
long fragmentId = (Long)this.removeTagForm.fragmentId.getValueObject();
String tagName = this.removeTagForm.tagName.getValue();
Fragment fragment = getDomain().getFragmentRepository().get(fragmentId);
if (fragment == null || StringUtils.isBlank(tagName)) {
setRedirectToThisPage();
return false;
}
getLogger().info("Removing the tag: " + tagName + " from: #" + fragmentId);
fragment.removeTagByUser(tagName, getUser());
getDomain().saveFragment(fragment, getUser());
highlightFragment(fragment.getId());
setRedirectToThisPage(
getMessage(
"completed-remove-tag",
new Object[]{
this.html.linkToTag(tagName),
this.html.fragmentInMessage(fragment)},
false));
return false;
}
// Add a tag
public static class AddTagForm extends PublicFieldForm {
public AddTagForm(Object listener, String method) {
super(listener, method);
}
public HiddenField fragmentId = new HiddenField("fragmentId", Long.class);
public HiddenField tagName = new HiddenField("tagName", String.class);
}
public AddTagForm addTagForm = new AddTagForm(this, "onAddTag");
public final boolean onAddTag() throws Exception {
long fragmentId = (Long)this.addTagForm.fragmentId.getValueObject();
String tagName = this.addTagForm.tagName.getValue();
Fragment fragment = getDomain().getFragmentRepository().get(fragmentId);
if (fragment == null) {
setRedirectToThisPage();
return false;
}
getLogger().info("Add a tag <" + tagName + "> to: #" + fragmentId);
fragment.addTagByUser(tagName, getDomain().getTagRepository(), getUser());
getDomain().saveFragment(fragment, getUser());
String message = null;
if (tagName.equals(Tag.NAME_TRASH)) {
message = getMessage(
"completed-tag-as-trash",
new Object[]{
this.html.linkToFragment(fragmentId),
this.resources.tagPathByName(Tag.NAME_TRASH)},
false);
}
else {
message = getMessage(
"completed-add-tag",
new Object[]{
this.html.fragmentInMessage(fragment),
this.html.linkToTag(tagName)},
false);
}
highlightFragment(fragment.getId());
setRedirectToThisPage(message);
return false;
}
// Add tags to the selected fragments
public static class AddTagsToSelectedForm extends PublicFieldForm {
public AddTagsToSelectedForm(Object listener, String method) {
super(listener, method);
}
public HiddenField tagId = new HiddenField("tagId", Long.class);
}
public AddTagsToSelectedForm addTagsToSelectedForm = new AddTagsToSelectedForm(this, "onAddTagsToSelected");
public final boolean onAddTagsToSelected() throws Exception {
// tag
Long tagId = (Long)this.addTagsToSelectedForm.tagId.getValueObject();
Tag tag = (tagId != null) ? getDomain().getTagRepository().get(tagId) : null;
if (tag == null) {
setRedirectToThisPage();
return false;
}
// selected fragments
SelectedFragments selected = getSession().getSelectedFragments();
if (selected.isEmpty()) {
setRedirectToThisPage(getMessage("no-selected-fragments"));
return false;
}
final List<Fragment> fragments = selected.getAllFragments(getDomain().getFragmentRepository(), true);
// do tagging
try {
getDomain().addTagToFragments(fragments, tag, getUser());
}
catch (Exception e) {
setRedirectToThisPage(CodedException.getCodedMessageOrThrow(e, this));
return false;
}
setRedirectToThisPage(
getMessage(
"completed-add-tags-to-selected",
new Object[]{this.html.linkToTag(tag.getName())},
false));
return false;
}
// Remove from bookmarks
public static class RemoveBookmarkForm extends PublicFieldForm {
public RemoveBookmarkForm(Object listener, String method) {
super(listener, method);
}
public HiddenField fragmentId = new HiddenField("fragmentId", Long.class);
}
public RemoveBookmarkForm removeBookmarkForm = new RemoveBookmarkForm(this, "onRemoveBookmark");
public final boolean onRemoveBookmark() throws Exception {
long fragmentId = (Long)this.removeBookmarkForm.fragmentId.getValueObject();
Fragment fragment = getDomain().getFragmentRepository().get(fragmentId);
if (fragment == null) {
setRedirectToThisPage();
return false;
}
getLogger().info("Removing #" + fragmentId + " from the bookmarks ...");
fragment.removeTagsByUserClassifiedAs(Tag.NAME_BOOKMARK, getUser());
getDomain().saveFragment(fragment, getUser());
highlightFragment(fragment.getId());
setRedirectToThisPage(
getMessage(
"completed-remove-bookmark",
new Object[]{this.html.fragmentInMessage(fragment)},
false));
return false;
}
}