jp.co.nemuzuka.service.impl.GanttServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for jp.co.nemuzuka.service.impl.GanttServiceImpl.java

Source

/*
 * 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.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jp.co.nemuzuka.dao.MilestoneDao;
import jp.co.nemuzuka.dao.TicketDao.Param;
import jp.co.nemuzuka.entity.ChildKeyListEntity;
import jp.co.nemuzuka.entity.TicketModelEx;
import jp.co.nemuzuka.model.MilestoneModel;
import jp.co.nemuzuka.service.GanttService;
import jp.co.nemuzuka.service.TicketService;
import jp.co.nemuzuka.utils.ConvertUtils;
import jp.co.nemuzuka.utils.CurrentDateUtils;
import jp.co.nemuzuka.utils.DateTimeUtils;

import org.apache.commons.lang.StringUtils;

import com.google.appengine.api.datastore.Key;

/**
 * GanttService?.
 * @author k-katagiri
 */
public class GanttServiceImpl implements GanttService {

    TicketService ticketService = TicketServiceImpl.getInstance();
    MilestoneDao milestoneDao = MilestoneDao.getInstance();

    private static GanttServiceImpl impl = new GanttServiceImpl();

    /**
     * ?.
     * @return 
     */
    public static GanttServiceImpl getInstance() {
        return impl;
    }

    /**
     * .
     */
    private GanttServiceImpl() {
    }

    /* (? Javadoc)
     * @see jp.co.nemuzuka.service.GanttService#getList(jp.co.nemuzuka.dao.TicketDao.Param)
     */
    @Override
    public Result getList(Param param) {

        //?
        List<TicketModelEx> ticketList = ticketService.getList(param, "", false);
        reCreateTicketList(ticketList);

        Result result = new Result();
        result.ticketList = ticketList;

        //?
        Date startDate = null;
        Date endDate = null;
        if (StringUtils.isNotEmpty(param.milestone)) {
            MilestoneModel milestone = milestoneDao.get(param.milestone);
            if (milestone != null) {
                startDate = milestone.getStartDate();
                endDate = milestone.getEndDate();
                result.milestoneName = milestone.getMilestoneName();
                SimpleDateFormat sdf = DateTimeUtils.createSdf("yyyyMMdd");
                result.startDate = ConvertUtils.toString(startDate, sdf);
                result.endDate = ConvertUtils.toString(endDate, sdf);
                result.milestoneStartDate = ConvertUtils.toString(startDate, sdf);
                result.milestoneEndDate = ConvertUtils.toString(endDate, sdf);
            }
        }

        //????
        setDate(result, startDate, endDate);
        reCreateTicketList(result.ticketList);
        return result;
    }

    /**
     * ???.
     * ??????????
     * @param ticketList ?
     */
    void reCreateTicketList(List<TicketModelEx> ticketList) {

        //Key????TicketMap??Key?????Ticket?Entity?
        Map<Key, TicketModelEx> map = new HashMap<Key, TicketModelEx>();
        Map<Key, ChildKeyListEntity> parentMap = new LinkedHashMap<Key, ChildKeyListEntity>();
        for (TicketModelEx target : ticketList) {
            Key key = target.getModel().getKey();
            map.put(key, target);

            Key parentKey = target.getModel().getParentTicketKey();
            ChildKeyListEntity entity = parentMap.get(parentKey);
            if (entity == null) {
                entity = new ChildKeyListEntity();
                parentMap.put(parentKey, entity);
            }
            int index = entity.childKeys.size();
            entity.childKeys.add(key);
            entity.childMap.put(key, index);
            entity.grandchildList.add(null);
        }

        boolean isContinue = true;
        Set<Key> doneParentKeySet = new HashSet<Key>();
        while (isContinue) {
            int beforeSize = parentMap.size();
            for (Map.Entry<Key, ChildKeyListEntity> e : parentMap.entrySet()) {
                Key parentKey = e.getKey();
                if (parentKey == null) {
                    //Key????Ticket?????
                    continue;
                }
                if (doneParentKeySet.contains(parentKey)) {
                    //???Key?????
                    continue;
                }

                //??Key???????
                if (moveParentKey(parentMap, parentKey, e.getValue())) {
                    //?????Map???loop
                    parentMap.remove(parentKey);
                    break;
                } else {
                    //??Key????????????
                    doneParentKeySet.add(parentKey);
                }
            }
            int afterSize = parentMap.size();

            if (beforeSize == afterSize) {
                //?????Map???????
                isContinue = false;
            }
        }

        //??Map????
        createList(ticketList, map, parentMap);
        return;
    }

    /**
     * TicketList?.
     * Ticket?Map????List????
     * @param ticketList TicketList
     * @param map Ticket?Map
     * @param parentMap Ticket?Map
     */
    private void createList(List<TicketModelEx> ticketList, Map<Key, TicketModelEx> map,
            Map<Key, ChildKeyListEntity> parentMap) {

        ticketList.clear();

        for (Map.Entry<Key, ChildKeyListEntity> e : parentMap.entrySet()) {
            ChildKeyListEntity targetEntity = e.getValue();
            int nestingLevel = 0;
            setTicketList(targetEntity, nestingLevel, ticketList, map);
        }
    }

    /**
     * List.
     * ?TicketKeyList?List????
     * Ticket????List?????
     * ??????
     * @param targetEntity ?Ticket?Entity
     * @param nestingLevel ???
     * @param ticketList TicketList
     * @param map Ticket?Map
     */
    void setTicketList(ChildKeyListEntity targetEntity, int nestingLevel, List<TicketModelEx> ticketList,
            Map<Key, TicketModelEx> map) {
        //?TicketKeyList?
        int index = 0;
        for (Key key : targetEntity.childKeys) {
            TicketModelEx targetModelEx = map.get(key);
            targetModelEx.setNestingLevel(nestingLevel);
            ticketList.add(targetModelEx);

            //TicketKey???
            ChildKeyListEntity grandchild = targetEntity.grandchildList.get(index);
            index++;
            if (grandchild == null) {
                continue;
            }
            setTicketList(grandchild, (nestingLevel + 1), ticketList, map);
        }
    }

    /**
     * ???.
     * ?Key???????????????
     * @param parentMap Map
     * @param targetKey Key
     * @param targetEntity ?
     * @return ?Key???????????true
     */
    boolean moveParentKey(Map<Key, ChildKeyListEntity> parentMap, Key targetKey, ChildKeyListEntity targetEntity) {
        for (Map.Entry<Key, ChildKeyListEntity> e : parentMap.entrySet()) {
            //????????
            if (e.getKey() != null && e.getKey().equals(targetKey)) {
                continue;
            }
            ChildKeyListEntity entity = e.getValue();
            if (moveParentKey(targetKey, entity, targetEntity)) {
                return true;
            }
        }
        return false;
    }

    /**
     * ???.
     * ?Key?????????
     * ??????
     * ??????????????
     * @param targetKey Key
     * @param checkTarget ??Ticket?Entity
     * @param targetEntity ?
     * @return ?Key???????????true
     */
    boolean moveParentKey(Key targetKey, ChildKeyListEntity checkTarget, ChildKeyListEntity targetEntity) {

        //?????Key?????
        Integer index = checkTarget.childMap.get(targetKey);
        if (index != null) {
            checkTarget.grandchildList.set(index, targetEntity);
            return true;
        } else {
            //??Ticket?EntityList????????
            for (ChildKeyListEntity target : checkTarget.grandchildList) {
                if (target != null) {
                    if (moveParentKey(targetKey, target, targetEntity)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * ???.
     * @param result ?
     * @param startDate 
     * @param endDate 
     */
    void setDate(Result result, Date startDate, Date endDate) {

        Date targetStartDate = startDate;
        Date targetEndDate = endDate;

        for (TicketModelEx target : result.ticketList) {

            Date ticketStartDate = target.getModel().getStartDate();
            Date ticketEndDate = target.getModel().getPeriod();
            if (ticketEndDate != null && ticketStartDate == null) {
                //????????????
                //????????????
                ticketStartDate = ticketEndDate;
            }

            targetStartDate = checkDate(ticketStartDate, targetStartDate, true);
            targetEndDate = checkDate(ticketEndDate, targetEndDate, false);
        }

        //?null????
        if (targetStartDate == null) {
            targetStartDate = CurrentDateUtils.getInstance().getCurrentDate();
        }
        //?null????1?
        if (targetEndDate == null) {
            targetEndDate = DateTimeUtils.addMonths(targetStartDate, 1);
        }

        //???????15????15?
        if (DateTimeUtils.getDays(targetStartDate, targetEndDate) < 15) {
            targetEndDate = DateTimeUtils.addDays(targetStartDate, 15);
        }

        //Ticket????null??????
        replaceNullDate(result.ticketList, targetStartDate, targetEndDate);

        //??
        SimpleDateFormat sdf = DateTimeUtils.createSdf("yyyyMMdd");
        result.startDate = ConvertUtils.toString(targetStartDate, sdf);
        result.endDate = ConvertUtils.toString(targetEndDate, sdf);

        //??????
        //?????
        if (StringUtils.isNotEmpty(result.milestoneName)) {
            if (StringUtils.isEmpty(result.milestoneStartDate)) {
                result.milestoneStartDate = result.startDate;
                result.updateStartDate = true;
            }

            if (StringUtils.isEmpty(result.milestoneEndDate)) {
                result.milestoneEndDate = result.endDate;
                result.updateEndDate = true;
            }
        }
    }

    /**
     * Ticket??null?.
     * Ticket??null?????null????????
     * @param ticketList Ticket
     * @param startDate ?
     * @param endDate ?
     */
    private void replaceNullDate(List<TicketModelEx> ticketList, Date startDate, Date endDate) {
        SimpleDateFormat sdf = DateTimeUtils.createSdf("yyyyMMdd");
        String start = ConvertUtils.toString(startDate, sdf);
        String end = ConvertUtils.toString(endDate, sdf);

        for (TicketModelEx target : ticketList) {
            if (StringUtils.isEmpty(target.getStartDate())) {
                target.setStartDate(start);
                target.setUpdateStartDate(true);
            }
            if (StringUtils.isEmpty(target.getPeriod())) {
                target.setPeriod(end);
                target.setUpdatePeriod(true);
            }
        }
    }

    /**
     * ?.
     * ?????
     *    ? < ????????
     * ?????
     *    ? > ????????
     * @param targetDate ?
     * @param baseDate 
     * @param startDate ?????true
     * @return 
     */
    private Date checkDate(Date targetDate, Date baseDate, boolean startDate) {
        if (baseDate == null) {
            return targetDate;
        }

        if (targetDate == null) {
            return baseDate;
        }
        if (startDate) {
            if (targetDate.getTime() < baseDate.getTime()) {
                return targetDate;
            }
        } else {
            if (targetDate.getTime() > baseDate.getTime()) {
                return targetDate;
            }
        }
        return baseDate;
    }
}