package marubinotto.piggydb.model; import java.util.List; import java.util.Set; import marubinotto.piggydb.model.auth.User; import marubinotto.piggydb.model.base.Repository; import marubinotto.piggydb.model.entity.RawFragment; import marubinotto.piggydb.model.entity.RawTag; import marubinotto.piggydb.model.enums.FragmentField; import marubinotto.piggydb.model.exception.AuthorizationException; import marubinotto.piggydb.model.exception.BaseDataObsoleteException; import marubinotto.piggydb.model.exception.DuplicateException; import marubinotto.piggydb.model.exception.NoSuchEntityException; import marubinotto.util.Assert; import marubinotto.util.time.Month; public interface FragmentRepository extends Repository<Fragment> { public Fragment newInstance(User user); // NOTE: "updateTimestamp = false" will disable optimistic lock. // That means the update might be overwritten by another, without notice public boolean update(Fragment fragment, boolean updateTimestamp) throws BaseDataObsoleteException, Exception; public TagRepository getTagRepository(); public boolean containsId(Long id) throws Exception; public Fragment get(long id, boolean fetchRelations) throws Exception; public Fragment getHome(boolean fetchRelations, User user) throws Exception; public List<Fragment> getFragmentsAtHome(User user) throws Exception; public void setFileRepository(FileRepository fileRepository); public void refreshClassifications(List<? extends Fragment> fragments) throws Exception; public void deleteTrashes(User user) throws Exception; public Set<Integer> getDaysOfMonth(FragmentField field, Month month) throws Exception; public long createRelation(long from, long to, User user) throws NoSuchEntityException, DuplicateException, Exception; public FragmentRelation getRelation(long relationId) throws Exception; public FragmentRelation deleteRelation(long relationId, User user) throws Exception; public Long countRelations() throws Exception; public void updateChildRelationPriorities(Fragment parent, List<Long> relationOrder, User user) throws Exception; public Fragment newInstance(Tag tag, User user) throws Exception; public Long registerFragmentIfNotExists(Tag tag, User user) throws Exception; public Fragment asFragment(Tag tag) throws Exception; public void update(Tag tag, User user) throws Exception; public Fragment delete(Tag tag, User user) throws Exception; public static abstract class Base extends Repository.Base<Fragment, RawFragment> implements FragmentRepository { protected FileRepository fileRepository; public RawFragment newRawEntity() { return new RawFragment(); } public RawFragment newInstance(User user) { Assert.Arg.notNull(user, "user"); return new RawFragment(user); } public abstract TagRepository.Base getTagRepository(); public void setFileRepository(FileRepository fileRepository) { this.fileRepository = fileRepository; } public FileRepository getFileRepository() { return fileRepository; } public Fragment get(long id) throws Exception { return get(id, true); } public Fragment getHome(boolean fetchRelations, User user) throws Exception { Assert.Arg.notNull(user, "user"); RawFragment home = (RawFragment)get(Fragment.ID_HOME, fetchRelations); if (home == null) { try { home = newInstance(user); home.setId(Fragment.ID_HOME); register(home); } catch (AuthorizationException e) { return null; } } return home; } public final boolean update(Fragment fragment) throws Exception { return update(fragment, true); } public final boolean update(Fragment fragment, boolean updateTimestamp) throws Exception { Assert.Arg.notNull(fragment, "fragment"); Assert.require(fragment instanceof RawFragment, "fragment instanceof RawFragment"); Assert.Arg.notNull(fragment.getId(), "fragment.getId()"); Assert.Property.requireNotNull(fileRepository, "fileRepository"); if (!containsId(fragment.getId())) return false; if (fragment.getUpdateDatetime() == null) throw new BaseDataObsoleteException(); saveTagSide((RawFragment)fragment); updateFragment(fragment, updateTimestamp); return true; } public abstract void updateFragment(Fragment fragment, boolean updateTimestamp) throws Exception; protected void saveTagSide(RawFragment fragment) throws Exception { Assert.Arg.notNull(fragment.getId(), "fragment.getId()"); if (fragment.isTag()) { RawTag tag = (RawTag)fragment.asTag(); if (tag == null) return; // skip the updating if not prepared // new if (tag.getId() == null) { tag.setFragmentId(fragment.getId()); Long tagId = getTagRepository().register(tag); fragment.setTagId(tagId); } // update else { getTagRepository().update(tag); } // refresh the fragment's tags fragment.syncClassificationWith(tag); } else { Long tagId = fragment.getTagId(); // delete if (tagId != null) { getTagRepository().delete(tagId); fragment.setTagId(null); } } } public RawFragment newInstance(Tag tag, User user) throws Exception { Assert.Arg.notNull(tag, "tag"); Assert.Arg.notNull(tag.getId(), "tag.getId()"); Assert.Arg.notNull(user, "user"); RawFragment fragment = newInstance(user); fragment.setTagId(tag.getId()); fragment.syncWith(tag, user); return fragment; } public synchronized Long registerFragmentIfNotExists(Tag tag, User user) throws Exception { if (asFragment(tag) != null) return null; Fragment newfragment = newInstance(tag, user); long fragmentId = register(newfragment); ((RawTag)tag).setFragmentId(fragmentId); getTagRepository().update(tag); return fragmentId; } public RawFragment asFragment(Tag tag) throws Exception { Assert.Arg.notNull(tag, "tag"); return tag.getFragmentId() != null ? (RawFragment)get(tag.getFragmentId()) : null; } public void update(Tag tag, User user) throws Exception { Assert.Arg.notNull(tag, "tag"); Assert.Arg.notNull(tag.getId(), "tag.getId()"); Assert.Arg.notNull(user, "user"); getTagRepository().update(tag); RawFragment fragment = asFragment(tag); if (fragment != null) { fragment.syncWith(tag, user); updateFragment(fragment, true); } } public Fragment delete(Tag tag, User user) throws Exception { Assert.Arg.notNull(tag, "tag"); Assert.Arg.notNull(tag.getId(), "tag.getId()"); Assert.Arg.notNull(user, "user"); getTagRepository().delete(tag.getId()); RawFragment fragment = asFragment(tag); if (fragment != null) { fragment.setTagId(null); updateFragment(fragment, true); } return fragment; } public final long createRelation(long from, long to, User user) throws NoSuchEntityException, DuplicateException, Exception { Assert.Arg.notNull(user, "user"); Assert.require(from != to, "from != to"); FragmentRelation.ensureCanCreate(user); return doCreateRelation(from, to, user); } protected abstract long doCreateRelation(long from, long to, User user) throws NoSuchEntityException, DuplicateException, Exception; public final FragmentRelation deleteRelation(long relationId, User user) throws Exception { Assert.Arg.notNull(user, "user"); FragmentRelation relation = getRelation(relationId); if (relation == null) return null; relation.ensureCanDelete(user); doDeleteRelation(relation.getId()); return relation; } protected abstract void doDeleteRelation(long relationId) throws Exception; public final void updateChildRelationPriorities(Fragment parent, List<Long> relationOrder, User user) throws Exception { Assert.Arg.notNull(parent, "parent"); Assert.Arg.notNull(relationOrder, "relationOrder"); Assert.Arg.notNull(user, "user"); parent.ensureCanChange(user); if (relationOrder.isEmpty()) return; doUpdateChildRelationPriorities(relationOrder); } protected abstract void doUpdateChildRelationPriorities(List<Long> relationOrder) throws Exception; } }