/* * Copyright 2012 Kazumune Katagiri. (http://d.hatena.ne.jp/nemuzuka) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package jp.co.nemuzuka.dao; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import jp.co.nemuzuka.entity.TicketMstEntity.TicketMst; import jp.co.nemuzuka.meta.TicketModelMeta; import jp.co.nemuzuka.model.TicketModel; import jp.co.nemuzuka.utils.CurrentDateUtils; import org.apache.commons.lang.StringUtils; import org.slim3.datastore.Datastore; import org.slim3.datastore.FilterCriterion; import org.slim3.datastore.InMemoryFilterCriterion; import org.slim3.datastore.InMemorySortCriterion; import org.slim3.datastore.ModelMeta; import org.slim3.datastore.ModelQuery; import com.google.appengine.api.datastore.Key; /** * TicketModelに対するDao. * @author kazumune */ public class TicketDao extends AbsDao { /* (非 Javadoc) * @see jp.co.nemuzuka.dao.AbsDao#getModelMeta() */ @SuppressWarnings("rawtypes") @Override ModelMeta getModelMeta() { return TicketModelMeta.get(); } /* (非 Javadoc) * @see jp.co.nemuzuka.dao.AbsDao#getModelClass() */ @SuppressWarnings("rawtypes") @Override Class getModelClass() { return TicketModel.class; } TicketSeqDao ticketSeqDao = TicketSeqDao.getInstance(); private static TicketDao ticketDao = new TicketDao(); /** * インスタンス取得. * @return インスタンス */ public static TicketDao getInstance() { return ticketDao; } /** * デフォルトコンストラクタ. */ private TicketDao() {} /** * put処理. * 新規登録の場合、Noを設定します。 * @param model 対象Model */ public void put(TicketModel model){ if(model.getKey() == null) { //新規の場合 model.setNo(ticketSeqDao.createMaxTicketSeqModel().getNo()); } super.put(model); } /** * List取得. * @param param 検索条件 * @return 該当レコード */ public List<TicketModel> getList(Param param) { TicketModelMeta e = (TicketModelMeta) getModelMeta(); Set<InMemoryFilterCriterion> filterSet = new HashSet<InMemoryFilterCriterion>(); //ステータスの検索条件 String[] status = param.status; if(status != null && status.length != 0) { Set<String> statusSet = new HashSet<String>(); for(String statusValue : status) { if(TicketMst.NO_FINISH.equals(statusValue)) { //未完了が選択された際には、未完了を意味するステータスを設定 for(String target : param.openStatus) { statusSet.add(target); } } else { statusSet.add(statusValue); } } if(statusSet.size() != 0) { filterSet.add(e.status.in(statusSet)); } } //件名の検索条件 if(StringUtils.isNotEmpty(param.title)) { filterSet.add(e.title.startsWith(param.title)); } //優先度の検索条件 if(StringUtils.isNotEmpty(param.priority)) { filterSet.add(e.priority.equal(param.priority)); } //種別の検索条件 if(StringUtils.isNotEmpty(param.kind)) { filterSet.add(e.targetKind.equal(param.kind)); } //カテゴリの検索条件 if(StringUtils.isNotEmpty(param.category)) { filterSet.add(e.category.equal(param.category)); } //バージョンの検索条件 if(StringUtils.isNotEmpty(param.version)) { filterSet.add(e.targetVersion.equal(param.version)); } //マイルストーンの検索条件 if(StringUtils.isNotEmpty(param.milestone)) { Key milestoneKey = Datastore.stringToKey(param.milestone); filterSet.add(e.milestone.equal(milestoneKey)); } //担当者の検索条件 if(StringUtils.isNotEmpty(param.targetMember)) { Key targetMemberKey = Datastore.stringToKey(param.targetMember); filterSet.add(e.targetMemberKey.equal(targetMemberKey)); } //チケットNoの検索条件 if(param.no != null) { filterSet.add(e.no.equal(param.no)); } //期限Fromの検索条件 if(param.fromPeriod != null) { filterSet.add(e.period.isNotNull()); filterSet.add(e.period.greaterThanOrEqual(param.fromPeriod)); } //期限Toの検索条件 if(param.toPeriod != null) { filterSet.add(e.period.isNotNull()); filterSet.add(e.period.lessThanOrEqual(param.toPeriod)); } //期限未設定のみを抽出 if(param.periodNull) { //期限がnullであることを指定する filterSet.add(e.period.equal(null)); } Set<InMemorySortCriterion> sortSet = new LinkedHashSet<InMemorySortCriterion>(); if(param.orderByPeriod) { //期限の昇順でソートする sortSet.add(e.period.asc); } sortSet.add(e.no.asc); //プロジェクトの検索条件 Key projectKey = Datastore.stringToKey(param.projectKeyString); filterSet.add(e.projectKey.equal(projectKey)); ModelQuery<TicketModel> query = Datastore.query(e).filterInMemory(filterSet.toArray(new InMemoryFilterCriterion[0])) .sortInMemory(sortSet.toArray(new InMemorySortCriterion[0])); List<TicketModel> retList = query.asList(); if(param.limit != null) { int toIndex = param.limit; if(toIndex > retList.size()) { //結果が一覧取得数より少ない場合 toIndex = retList.size(); } //一覧取得数の指定がされている場合、設定 return retList.subList(0, toIndex); } return retList; } /** * ダッシュボード用一覧取得. * 指定したプロジェクトにおいて、 * ステータスが未完了でかつ、担当者が自分のチケットを指定したlimit件数分取得します。 * 一覧は、 * ・期限が設定されているもの(期限の昇順) * ・期限が未設定のもの(登録順) * の順番でソートされます。 * @param limit 取得件数 * @param memberKeyString ログインユーザのメールアドレスのKey文字列 * @param projectKeyString プロジェクトKey文字列 * @param openStatus 未完了を意味するステータス配列 * @return 該当レコード */ public List<TicketModel> getDashbordList(int limit, String memberKeyString, String projectKeyString, String[] openStatus) { //ステータスが未完了で、指定したLimit分取得する //期限が設定されていて、未完了のものを取得 Param param = new Param(); param.status = new String[]{TicketMst.NO_FINISH}; param.openStatus = openStatus; param.limit = limit; param.targetMember = memberKeyString; param.projectKeyString = projectKeyString; param.toPeriod = CurrentDateUtils.getInstance().getMaxDate(); param.orderByPeriod = true; List<TicketModel> list = getList(param); if(list.size() >= limit) { //指定件数分取得できた場合、終了 return list; } //期限が設定されておらず、未完了のものを取得 param.toPeriod = null; param.periodNull = true; param.orderByPeriod = false; List<TicketModel> periodNullList = getList(param); for(TicketModel target : periodNullList) { list.add(target); if(list.size() >= limit) { //追加後、上限件数を超えた場合、終了 break; } } return list; } /** * 子Ticket情報取得. * 自分の子どもとして登録されているTicketのKeyListを取得します。 * @param self 自Key * @param projectKey プロジェクトKey * @return 子どもとして登録されているTicketのKeyList */ public List<Key> getChildList(Key self, Key projectKey) { TicketModelMeta e = (TicketModelMeta) getModelMeta(); return Datastore.query(e).filter(e.parentTicketKey.equal(self), e.projectKey.equal(projectKey)) .sortInMemory(e.key.asc).asKeyList(); } /** * Map取得. * 指定したKey配列に合致するデータを取得します。 * @param projectKeyString プロジェクトKey文字列 * @param keys key配列 * @return 該当Map */ public Map<Key, TicketModel> getMap(String projectKeyString, Key...keys) { TicketModelMeta e = (TicketModelMeta) getModelMeta(); Set<FilterCriterion> filterSet = new HashSet<FilterCriterion>(); Map<Key, TicketModel> map = new HashMap<Key, TicketModel>(); if(keys != null && keys.length != 0) { filterSet.add(e.key.in(keys)); } else { return map; } Key projectKey = Datastore.stringToKey(projectKeyString); filterSet.add(e.projectKey.equal(projectKey)); List<TicketModel> list = Datastore.query(e).filter(filterSet.toArray(new FilterCriterion[0])).asList(); for(TicketModel target : list) { map.put(target.getKey(), target); } return map; } /** * Model取得. * @param key TicketModelのKey * @param projectKey ProjectModelのKey * @return 存在すればModelインスタンス */ public TicketModel getWithProjectKey(Key key, Key projectKey) { TicketModel model = get(key); if(model != null) { if(model.getProjectKey().equals(projectKey) == false) { model = null; } } return model; } /** * Model取得. * @param no TicketModelのNo * @param projectKey ProjectModelのKey * @return 存在すればModelのKey */ public Key getWithNoAndProjectKey(Long no, Key projectKey) { TicketModelMeta e = (TicketModelMeta) getModelMeta(); List<Key> list = Datastore.query(e).filter(e.no.equal(no)).sortInMemory(e.key.asc).asKeyList(); if(list.size() != 0) { return list.get(0); } return null; } /** * Model取得. * @param key TicketModelのKey * @param version TicketModelのバージョン * @param projectKey ProjectModelのKey * @return 存在すればModelインスタンス */ public TicketModel get(Key key, Long version, Key projectKey) { TicketModel model = get(key, version); if(model != null) { if(model.getProjectKey().equals(projectKey) == false) { model = null; } } return model; } /** * 検索条件パラメータ. * @author k-katagiri */ public static class Param { /** ステータス. */ public String[] status; /** 件名. */ public String title; /** 種別. */ public String kind; /** カテゴリ. */ public String category; /** バージョン. */ public String version; /** マイルストーン. */ public String milestone; /** 優先度. */ public String priority; /** 担当者. */ public String targetMember; /** チケットNo. */ public Long no; /** 期限From. */ public Date fromPeriod; /** 期限To. */ public Date toPeriod; /** 期限がnullのもののみ取得する場合、true */ boolean periodNull; /** 取得上限件数. */ public Integer limit; //必須 /** プロジェクトKey. */ public String projectKeyString; /** 未完了を意味するステータス. */ public String[] openStatus; /** 期限の昇順でソートする場合、true */ boolean orderByPeriod; } }