[from now] 2012/05/30 15:03:14

diff --git a/src/main/java/org/ryu22e/nico2cal/controller/GenerateNicoliveController.java b/src/main/java/org/ryu22e/nico2cal/controller/GenerateNicoliveController.java
index 7b4bcab..f0cffa8 100644
--- a/src/main/java/org/ryu22e/nico2cal/controller/GenerateNicoliveController.java
+++ b/src/main/java/org/ryu22e/nico2cal/controller/GenerateNicoliveController.java
@@ -3,8 +3,6 @@ package org.ryu22e.nico2cal.controller;
 import java.util.List;
 import java.util.logging.Logger;

-import org.ryu22e.nico2cal.model.MyCalendar;
-import org.ryu22e.nico2cal.service.CalendarService;
 import org.ryu22e.nico2cal.service.NicoliveRssService;
 import org.ryu22e.nico2cal.service.NicoliveService;
 import org.slim3.controller.Controller;
@@ -13,7 +11,6 @@ import org.slim3.datastore.Datastore;
 import org.slim3.memcache.Memcache;

 import com.google.appengine.api.datastore.Key;
-import com.google.appengine.api.taskqueue.QueueFactory;
 import com.google.appengine.api.taskqueue.TaskOptions;
 import com.google.appengine.api.taskqueue.TaskOptions.Method;
 import com.sun.syndication.feed.synd.SyndFeed;
@@ -47,11 +44,6 @@ public final class GenerateNicoliveController extends Controller {
     private NicoliveService nicoliveService = new NicoliveService();

     /**
-     * @see CalendarService
-     */
-    private CalendarService calendarService = new CalendarService();
-
-    /**
      * TaskQueueを追加する。
      * @param keys NicoliveのキーのList
      */
@@ -68,33 +60,6 @@ public final class GenerateNicoliveController extends Controller {
                             "keys[]",
                             Datastore.keyToString(key));
             }
-            QueueFactory.getQueue("generate-nicoliveindex").add(
-                optiotnForNicoIndex);
-
-            // マイカレンダー（Google Calendar）にニコニコ生放送放送予定日をインポートする。
-            List<MyCalendar> myCalendars = calendarService.getMyCalendars();
-            for (MyCalendar myCalendar : myCalendars) {
-                TaskOptions optiotnForMyCalendarImport =
-                        TaskOptions.Builder
-                            .withUrl("/myCalendar/import")
-                            .method(Method.POST);
-                for (Key key : keys) {
-                    optiotnForMyCalendarImport =
-                            optiotnForMyCalendarImport.param(
-                                "keys[]",
-                                Datastore.keyToString(key));
-                }
-                optiotnForMyCalendarImport =
-                        optiotnForMyCalendarImport.param(
-                            "calendarId",
-                            myCalendar.getCalendarId());
-                optiotnForMyCalendarImport =
-                        optiotnForMyCalendarImport.param("userId", myCalendar
-                            .getUser()
-                            .getUserId());
-                QueueFactory.getQueue("mycalendar-import").add(
-                    optiotnForMyCalendarImport);
-            }
         }
     }

diff --git a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/IndexController.java b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/IndexController.java
index 4ffc8c8..4d53a65 100644
--- a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/IndexController.java
+++ b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/IndexController.java
@@ -41,7 +41,7 @@ public final class IndexController extends Controller {
         if (AppEngineUtil.isProduction()) {
             CalendarList feed = null;
             try {
-                feed = calendarService.getCalendarList();
+                feed = calendarService.getGoogleCalendarList();
             } catch (IOException e) {
                 LOGGER.warning(e.getMessage());
             }
diff --git a/src/main/java/org/ryu22e/nico2cal/model/MyCalendarLog.java b/src/main/java/org/ryu22e/nico2cal/model/MyCalendarLog.java
new file mode 100644
index 0000000..fa9aa6a
--- /dev/null
+++ b/src/main/java/org/ryu22e/nico2cal/model/MyCalendarLog.java
@@ -0,0 +1,131 @@
+package org.ryu22e.nico2cal.model;
+
+import java.io.Serializable;
+
+import org.slim3.datastore.Attribute;
+import org.slim3.datastore.Model;
+import org.slim3.datastore.ModelRef;
+
+import com.google.appengine.api.datastore.Key;
+
+/**
+ * @author ryu22e
+ *
+ */
+@Model(schemaVersion = 1)
+public final class MyCalendarLog implements Serializable {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @Attribute(primaryKey = true)
+    private Key key;
+
+    /**
+     *
+     */
+    @Attribute(version = true)
+    private Long version;
+
+    /**
+     *
+     */
+    private String userId;
+
+    /**
+     *
+     */
+    private ModelRef<Nicolive> nicolive =
+            new ModelRef<Nicolive>(Nicolive.class);
+
+    /**
+     * Returns the key.
+     *
+     * @return the key
+     */
+    public Key getKey() {
+        return key;
+    }
+
+    /**
+     * Sets the key.
+     *
+     * @param key
+     *            the key
+     */
+    public void setKey(Key key) {
+        this.key = key;
+    }
+
+    /**
+     * Returns the version.
+     *
+     * @return the version
+     */
+    public Long getVersion() {
+        return version;
+    }
+
+    /**
+     * Sets the version.
+     *
+     * @param version
+     *            the version
+     */
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+
+    /**
+     * @return the userId
+     */
+    public String getUserId() {
+        return userId;
+    }
+
+    /**
+     * @param userId the userId to set
+     */
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public ModelRef<Nicolive> getNicolive() {
+        return nicolive;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((key == null) ? 0 : key.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        MyCalendarLog other = (MyCalendarLog) obj;
+        if (key == null) {
+            if (other.key != null) {
+                return false;
+            }
+        } else if (!key.equals(other.key)) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java b/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java
index d81fb38..39be058 100644
--- a/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java
+++ b/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java
@@ -3,6 +3,7 @@ package org.ryu22e.nico2cal.service;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
@@ -22,10 +23,12 @@ import net.fortuna.ical4j.model.property.Url;
 import net.fortuna.ical4j.model.property.Version;
 import net.fortuna.ical4j.model.property.XProperty;

+import org.ryu22e.nico2cal.meta.MyCalendarLogMeta;
 import org.ryu22e.nico2cal.meta.MyCalendarMeta;
 import org.ryu22e.nico2cal.meta.NicoliveIndexMeta;
 import org.ryu22e.nico2cal.meta.NicoliveMeta;
 import org.ryu22e.nico2cal.model.MyCalendar;
+import org.ryu22e.nico2cal.model.MyCalendarLog;
 import org.ryu22e.nico2cal.model.Nicolive;
 import org.ryu22e.nico2cal.model.NicoliveIndex;
 import org.ryu22e.nico2cal.util.GoogleApiKeyUtil;
@@ -48,6 +51,8 @@ import com.google.api.client.json.JsonFactory;
 import com.google.api.client.json.jackson.JacksonFactory;
 import com.google.api.services.calendar.CalendarScopes;
 import com.google.api.services.calendar.model.CalendarList;
+import com.google.api.services.calendar.model.Event;
+import com.google.api.services.calendar.model.EventDateTime;
 import com.google.appengine.api.datastore.Key;
 import com.google.appengine.api.datastore.Query.SortDirection;
 import com.google.appengine.api.users.User;
@@ -246,7 +251,7 @@ public class CalendarService {
      * @return Google Calendarのカレンダー一覧
      * @throws IOException
      */
-    public CalendarList getCalendarList() throws IOException {
+    public CalendarList getGoogleCalendarList() throws IOException {
         com.google.api.services.calendar.Calendar client =
                 createGoogleCalendarClient();
         if (client == null) {
@@ -333,15 +338,72 @@ public class CalendarService {
      * @return {@link MyCalendar}のリスト
      */
     public List<MyCalendar> getMyCalendars() {
-        return Datastore.query(MyCalendarMeta.get()).asList();
+        MyCalendarMeta mc = MyCalendarMeta.get();
+        return Datastore.query(mc).filter(mc.disabled.equal(false)).asList();
     }

     /**
      * マイカレンダー（Google Calendar）にニコニコ生放送の放送予定日をインポートする。
      * @param myCalendar マイカレンダー
-     * @param key {@link Nicolive}の{@link Key}
+     * @throws IOException マイカレンダー（Google Calendar）へのインポートに失敗した場合
      */
-    public void importToMyCalendar(MyCalendar myCalendar, Key key) {
-        throw new AssertionError();
+    public void importToMyCalendar(MyCalendar myCalendar) throws IOException {
+        com.google.api.services.calendar.Calendar client =
+                createGoogleCalendarClient();
+        if (client != null) {
+            NicoliveMeta n = NicoliveMeta.get();
+            MyCalendarLogMeta ml = MyCalendarLogMeta.get();
+            org.joda.time.DateTime d = new org.joda.time.DateTime();
+            d = d.minusWeeks(1);
+            List<Nicolive> nicolives =
+                    Datastore
+                        .query(n)
+                        .filter(n.openTime.greaterThanOrEqual(d.toDate()))
+                        .asList();
+            List<MyCalendarLog> myCalendarLogs = new ArrayList<MyCalendarLog>();
+            for (Nicolive nicolive : nicolives) {
+                int count =
+                        Datastore
+                            .query(ml)
+                            .filter(
+                                ml.userId.equal(myCalendar
+                                    .getUser()
+                                    .getUserId()),
+                                ml.nicolive.equal(nicolive.getKey()))
+                            .count();
+                if (count <= 0) {
+                    Event event = new Event();
+                    // カレンダーのSummaryに生放送のタイトルを設定する。
+                    event.setSummary(nicolive.getTitle());
+                    // カレンダーのDescriptionに生放送の説明文を設定する。
+                    event.setDescription(nicolive.getDescription().toString());
+                    java.util.Calendar c =
+                            DateUtil.toCalendar(nicolive.getOpenTime());
+                    // 生放送会場日時をcom.google.api.client.util.DateTimeに変換する。
+                    TimeZone timezone = TimeZoneLocator.get();
+                    c.setTimeZone(timezone);
+                    com.google.api.client.util.DateTime datetime =
+                            new com.google.api.client.util.DateTime(c.getTime());
+                    // カレンダーのStartに生放送会場日時を設定する。
+                    EventDateTime start = new EventDateTime();
+                    start.setDateTime(datetime);
+                    event.setStart(start);
+                    // カレンダーのEndに生放送会場日時を設定する。
+                    EventDateTime end = new EventDateTime();
+                    end.setDateTime(datetime);
+                    event.setEnd(end);
+
+                    client.events().insert(myCalendar.getCalendarId(), event);
+
+                    // インポートしたNicoliveをmyCalendarLogに登録して、二度とインポートしないようにする。
+                    MyCalendarLog myCalendarLog = new MyCalendarLog();
+                    myCalendarLog.setUserId(myCalendar.getUser().getUserId());
+                    myCalendarLog.getNicolive().setModel(nicolive);
+                    myCalendarLogs.add(myCalendarLog);
+                }
+
+                Datastore.putAsync(myCalendarLogs);
+            }
+        }
     }
 }
diff --git a/src/test/java/org/ryu22e/nico2cal/model/MyCalendarLogTest.java b/src/test/java/org/ryu22e/nico2cal/model/MyCalendarLogTest.java
new file mode 100644
index 0000000..2ff9620
--- /dev/null
+++ b/src/test/java/org/ryu22e/nico2cal/model/MyCalendarLogTest.java
@@ -0,0 +1,27 @@
+package org.ryu22e.nico2cal.model;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.slim3.tester.AppEngineTestCase;
+
+/**
+ * @author ryu22e
+ *
+ */
+public final class MyCalendarLogTest extends AppEngineTestCase {
+
+    /**
+     *
+     */
+    private MyCalendarLog model = new MyCalendarLog();
+
+    /**
+     * @throws Exception
+     */
+    @Test
+    public void test() throws Exception {
+        assertThat(model, is(notNullValue()));
+    }
+}
diff --git a/src/test/java/org/ryu22e/nico2cal/service/CalendarServiceTest.java b/src/test/java/org/ryu22e/nico2cal/service/CalendarServiceTest.java
index 3ac95a4..6ccd215 100644
--- a/src/test/java/org/ryu22e/nico2cal/service/CalendarServiceTest.java
+++ b/src/test/java/org/ryu22e/nico2cal/service/CalendarServiceTest.java
@@ -19,7 +19,9 @@ import net.fortuna.ical4j.model.component.VEvent;

 import org.joda.time.DateTime;
 import org.junit.Test;
+import org.ryu22e.nico2cal.meta.MyCalendarLogMeta;
 import org.ryu22e.nico2cal.model.MyCalendar;
+import org.ryu22e.nico2cal.model.MyCalendarLog;
 import org.ryu22e.nico2cal.model.Nicolive;
 import org.ryu22e.nico2cal.model.NicoliveIndex;
 import org.slim3.datastore.Datastore;
@@ -58,19 +60,19 @@ public final class CalendarServiceTest extends AppEngineTestCase {
      * @throws IOException
      */
     private CalendarService createMockService() throws IOException {
-        CalendarService mockService = mock(CalendarService.class);
-        when(mockService.createGoogleCalendarClientFromUserId("42"))
-            .thenReturn(
-                com.google.api.services.calendar.Calendar.builder(
-                    new NetHttpTransport(),
-                    new JacksonFactory()).build());
-        when(mockService.createGoogleCalendarClient()).thenCallRealMethod();
+        CalendarService mockService = spy(new CalendarService());
+        doReturn(
+            com.google.api.services.calendar.Calendar.builder(
+                new NetHttpTransport(),
+                new JacksonFactory()).build())
+            .when(mockService)
+            .createGoogleCalendarClientFromUserId("42");
         CalendarList calendarList = new CalendarList();
         calendarList.setItems(Arrays.asList(
             new CalendarListEntry(),
             new CalendarListEntry(),
             new CalendarListEntry()));
-        when(mockService.getCalendarList()).thenReturn(calendarList);
+        doReturn(calendarList).when(mockService).getGoogleCalendarList();

         return mockService;
     }
@@ -284,7 +286,7 @@ public final class CalendarServiceTest extends AppEngineTestCase {
     public void GoogleCalendarのカレンダー一覧を取得する_ログインしていない() throws Exception {
         assertThat(service, is(notNullValue()));

-        CalendarList feed = service.getCalendarList();
+        CalendarList feed = service.getGoogleCalendarList();
         assertThat(feed, is(nullValue()));
     }

@@ -301,11 +303,11 @@ public final class CalendarServiceTest extends AppEngineTestCase {
         envAttributes.put(
             "com.google.appengine.api.users.UserService.user_id_key",
             "42");
-        CalendarList feed = mockService.getCalendarList();
+        CalendarList feed = mockService.getGoogleCalendarList();
         assertThat(feed, is(notNullValue()));
         assertThat(feed.getItems(), is(notNullValue()));
         assertThat(feed.getItems().size(), is(3));
-        verify(mockService, times(1)).getCalendarList();
+        verify(mockService, times(1)).getGoogleCalendarList();
     }

     /**
@@ -535,9 +537,18 @@ public final class CalendarServiceTest extends AppEngineTestCase {
                 "test" + 1 + "@gmail.com",
                 "example.com",
                 "test" + 1));
+            myCalendar.setDisabled(false);
             testDataList.add(myCalendar);
         }
         List<Key> testDatakeys = Datastore.put(testDataList);
+        MyCalendar disabledMyCalendar = new MyCalendar();
+        disabledMyCalendar.setCalendarId("disabledCalendarId");
+        disabledMyCalendar.setUser(new User(
+            "test" + 1 + "@gmail.com",
+            "example.com",
+            "test" + 1));
+        disabledMyCalendar.setDisabled(true);
+        Datastore.put(disabledMyCalendar);

         List<MyCalendar> result = service.getMyCalendars();
         assertThat(result, is(notNullValue()));
@@ -565,19 +576,48 @@ public final class CalendarServiceTest extends AppEngineTestCase {
      */
     @Test
     public void GoogleCalendarにニコニコ生放送の放送予定日をインポートする() throws Exception {
-        assertThat(service, is(notNullValue()));
+        CalendarService mockservice = createMockService();
+        assertThat(mockservice, is(notNullValue()));

-        Nicolive nicolinve = new Nicolive();
-        nicolinve.setTitle("ほげほげ");
-        nicolinve.setDescription(new Text("ほげほげ説明文"));
-        DateTime datetime = new DateTime(2011, 1, 1, 0, 0, 0, 0);
-        nicolinve.setOpenTime(datetime.toDate());
-        nicolinve.setLink(new Link("http://ryu22e.org/"));
-        Key key = Datastore.put(nicolinve);
+        tester.environment.setEmail("dummy@gmail.com");
+        Map<String, Object> envAttributes = new HashMap<String, Object>();
+        envAttributes.put(
+            "com.google.appengine.api.users.UserService.user_id_key",
+            "42");
+        tester.environment.setAttributes(envAttributes);
+        User user = UserServiceFactory.getUserService().getCurrentUser();
+
+        // テストデータの登録。
+        List<Nicolive> testDataList = new ArrayList<Nicolive>();
+        for (int i = 0; i < 10; i++) {
+            Nicolive nicolive = new Nicolive();
+            nicolive.setTitle("ほげほげ");
+            nicolive.setDescription(new Text("ほげほげ説明文"));
+            DateTime datetime = new DateTime();
+            nicolive.setOpenTime(datetime.toDate());
+            nicolive.setLink(new Link("http://ryu22e.org/"));
+            testDataList.add(nicolive);
+        }
+        List<Key> testDataKeys = Datastore.put(testDataList);

         MyCalendar myCalendar = new MyCalendar();
         myCalendar.setCalendarId("calendar1");
-        myCalendar.setUser(new User("test1@gmail.com", "example.com", "test1"));
-        service.importToMyCalendar(myCalendar, key);
+        myCalendar.setUser(user);
+        mockservice.importToMyCalendar(myCalendar);
+
+        MyCalendarLogMeta ml = MyCalendarLogMeta.get();
+        List<MyCalendarLog> myCalendarLogs =
+                Datastore
+                    .query(ml)
+                    .filter(ml.userId.equal(user.getUserId()))
+                    .asList();
+        assertThat(myCalendarLogs, is(notNullValue()));
+        assertThat(myCalendarLogs.size(), is(10));
+        List<Key> storedKeys = new ArrayList<Key>();
+        for (MyCalendarLog myCalendarLog : myCalendarLogs) {
+            storedKeys.add(myCalendarLog.getNicolive().getKey());
+        }
+        assertThat(storedKeys, hasItems(testDataKeys.toArray(new Key[0])));
     }
+
 }
[from now] 2012/05/30 16:45:49

diff --git a/src/main/java/org/ryu22e/nico2cal/controller/GenerateNicoliveController.java b/src/main/java/org/ryu22e/nico2cal/controller/GenerateNicoliveController.java
index f0cffa8..6913dde 100644
--- a/src/main/java/org/ryu22e/nico2cal/controller/GenerateNicoliveController.java
+++ b/src/main/java/org/ryu22e/nico2cal/controller/GenerateNicoliveController.java
@@ -11,6 +11,7 @@ import org.slim3.datastore.Datastore;
 import org.slim3.memcache.Memcache;

 import com.google.appengine.api.datastore.Key;
+import com.google.appengine.api.taskqueue.QueueFactory;
 import com.google.appengine.api.taskqueue.TaskOptions;
 import com.google.appengine.api.taskqueue.TaskOptions.Method;
 import com.sun.syndication.feed.synd.SyndFeed;
@@ -44,22 +45,20 @@ public final class GenerateNicoliveController extends Controller {
     private NicoliveService nicoliveService = new NicoliveService();

     /**
-     * TaskQueueを追加する。
+     * 全文検索用インデックスを作成するTaskQueueを追加する。
      * @param keys NicoliveのキーのList
      */
     private void addTaskQueue(List<Key> keys) {
         if (0 < keys.size()) {
-            // 全文検索用インデックスを作成する。
-            TaskOptions optiotnForNicoIndex =
+            TaskOptions options =
                     TaskOptions.Builder
                         .withUrl("/GenerateNicoliveIndex")
                         .method(Method.POST);
             for (Key key : keys) {
-                optiotnForNicoIndex =
-                        optiotnForNicoIndex.param(
-                            "keys[]",
-                            Datastore.keyToString(key));
+                options = options.param("keys[]", Datastore.keyToString(key));
             }
+
+            QueueFactory.getQueue("generate-nicoliveindex").add(options);
         }
     }

diff --git a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllController.java b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllController.java
new file mode 100644
index 0000000..03d39ee
--- /dev/null
+++ b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllController.java
@@ -0,0 +1,58 @@
+package org.ryu22e.nico2cal.controller.myCalendar;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.ryu22e.nico2cal.model.MyCalendar;
+import org.ryu22e.nico2cal.service.CalendarService;
+import org.slim3.controller.Controller;
+import org.slim3.controller.Navigation;
+import org.slim3.datastore.Datastore;
+
+import com.google.appengine.api.taskqueue.QueueFactory;
+import com.google.appengine.api.taskqueue.TaskOptions;
+import com.google.appengine.api.taskqueue.TaskOptions.Method;
+
+/**
+ * Google Calendarに{@link org.ryu22e.nico2cal.model.Nicolive}の内容を全ての{@link org.ryu22e.nico2cal.model.MyCalendar}インポートするコントローラー。
+ * @author ryu22e
+ *
+ */
+public final class ImportAllController extends Controller {
+
+    /**
+     *
+     */
+    public static final Logger LOGGER = Logger
+        .getLogger(ImportAllController.class.getName());
+
+    /**
+     *
+     */
+    private CalendarService calendarService = new CalendarService();
+
+    /*
+     * (non-Javadoc) {@inheritDoc}
+     */
+    @Override
+    public Navigation run() throws Exception {
+        LOGGER.info("BEGIN: " + this.getClass().getName());
+
+        List<MyCalendar> myCalendars = calendarService.getMyCalendars();
+        for (MyCalendar myCalendar : myCalendars) {
+            TaskOptions options =
+                    TaskOptions.Builder
+                        .withUrl("/GenerateNicoliveIndex")
+                        .method(Method.POST);
+            options =
+                    options.param(
+                        "key",
+                        Datastore.keyToString(myCalendar.getKey()));
+            options = options.param("userId", myCalendar.getUser().getUserId());
+            QueueFactory.getQueue("generate-nicoliveindex").add(options);
+        }
+
+        LOGGER.info("END: " + this.getClass().getName());
+        return null;
+    }
+}
diff --git a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportController.java b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportController.java
index 150c19b..504c05d 100644
--- a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportController.java
+++ b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportController.java
@@ -4,7 +4,7 @@ import org.slim3.controller.Controller;
 import org.slim3.controller.Navigation;

 /**
- * Google Calendarに{@link org.ryu22e.nico2cal.model.Nicolive}の内容をインポートするコントローラー。
+ * Google Calendarに{@link org.ryu22e.nico2cal.model.Nicolive}の内容を個別の{@link org.ryu22e.nico2cal.model.MyCalendar}にインポートするコントローラー。
  * @author ryu22e
  *
  */
diff --git a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/IndexController.java b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/IndexController.java
index 4d53a65..9c762f2 100644
--- a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/IndexController.java
+++ b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/IndexController.java
@@ -12,6 +12,7 @@ import org.slim3.util.AppEngineUtil;

 import com.google.api.services.calendar.model.CalendarList;
 import com.google.api.services.calendar.model.CalendarListEntry;
+import com.google.appengine.api.users.UserServiceFactory;

 /**
  * マイカレンダーのトップページを表示させるコントローラー。
@@ -41,7 +42,11 @@ public final class IndexController extends Controller {
         if (AppEngineUtil.isProduction()) {
             CalendarList feed = null;
             try {
-                feed = calendarService.getGoogleCalendarList();
+                feed =
+                        calendarService
+                            .getGoogleCalendarList(UserServiceFactory
+                                .getUserService()
+                                .getCurrentUser());
             } catch (IOException e) {
                 LOGGER.warning(e.getMessage());
             }
@@ -64,7 +69,7 @@ public final class IndexController extends Controller {
             requestScope("calendars", Arrays.asList(entry1, entry2, entry3));
             storedCredential = true;
         }
-        MyCalendar myCalendar = calendarService.getMyCalendar();
+        MyCalendar myCalendar = calendarService.getCurrentMyCalendar();
         if (myCalendar != null) {
             requestScope("calendarSummaries", myCalendar.getCalendarId());
             requestScope(
diff --git a/src/main/java/org/ryu22e/nico2cal/model/MyCalendarLog.java b/src/main/java/org/ryu22e/nico2cal/model/MyCalendarLog.java
index fa9aa6a..1b56f28 100644
--- a/src/main/java/org/ryu22e/nico2cal/model/MyCalendarLog.java
+++ b/src/main/java/org/ryu22e/nico2cal/model/MyCalendarLog.java
@@ -7,6 +7,7 @@ import org.slim3.datastore.Model;
 import org.slim3.datastore.ModelRef;

 import com.google.appengine.api.datastore.Key;
+import com.google.appengine.api.users.User;

 /**
  * @author ryu22e
@@ -35,7 +36,7 @@ public final class MyCalendarLog implements Serializable {
     /**
      *
      */
-    private String userId;
+    private User user;

     /**
      *
@@ -82,17 +83,17 @@ public final class MyCalendarLog implements Serializable {
     }

     /**
-     * @return the userId
+     * @return the user
      */
-    public String getUserId() {
-        return userId;
+    public User getUser() {
+        return user;
     }

     /**
-     * @param userId the userId to set
+     * @param user the user to set
      */
-    public void setUserId(String userId) {
-        this.userId = userId;
+    public void setUser(User user) {
+        this.user = user;
     }

     public ModelRef<Nicolive> getNicolive() {
diff --git a/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java b/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java
index 39be058..ccdec55 100644
--- a/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java
+++ b/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java
@@ -237,11 +237,12 @@ public class CalendarService {
     /**
      * Google Calendar API用Clientを取得する。
      * @return Google Calendar API用Client
+     * @throws NullPointerException パラメータがnullの場合。
      */
-    public com.google.api.services.calendar.Calendar createGoogleCalendarClient() {
-        User user = UserServiceFactory.getUserService().getCurrentUser();
-        if (user == null || user.getUserId() == null) {
-            return null;
+    public com.google.api.services.calendar.Calendar createGoogleCalendarClient(
+            User user) {
+        if (user == null) {
+            throw new NullPointerException("user is null.");
         }
         return createGoogleCalendarClientFromUserId(user.getUserId());
     }
@@ -250,10 +251,11 @@ public class CalendarService {
      * Google Calendarのカレンダー一覧を取得する。
      * @return Google Calendarのカレンダー一覧
      * @throws IOException
+     * @throws NullPointerException パラメータがnullの場合。
      */
-    public CalendarList getGoogleCalendarList() throws IOException {
+    public CalendarList getGoogleCalendarList(User user) throws IOException {
         com.google.api.services.calendar.Calendar client =
-                createGoogleCalendarClient();
+                createGoogleCalendarClient(user);
         if (client == null) {
             return null;
         }
@@ -306,7 +308,7 @@ public class CalendarService {
     /**
      * 連携対象のGoogleCalendarを取得する。
      */
-    public MyCalendar getMyCalendar() {
+    public MyCalendar getCurrentMyCalendar() {
         User user = UserServiceFactory.getUserService().getCurrentUser();
         if (user == null) {
             return null;
@@ -343,13 +345,27 @@ public class CalendarService {
     }

     /**
+    * {@link MyCalendar}のキーリストを取得する。
+     * @return {@link MyCalendar}のキーリスト
+     */
+    public List<Key> getMyCalendarKeys() {
+        MyCalendarMeta mc = MyCalendarMeta.get();
+        return Datastore.query(mc).filter(mc.disabled.equal(false)).asKeyList();
+    }
+
+    /**
      * マイカレンダー（Google Calendar）にニコニコ生放送の放送予定日をインポートする。
-     * @param myCalendar マイカレンダー
+     * @param myCalendarKey {@link MyCalendar}のキー
      * @throws IOException マイカレンダー（Google Calendar）へのインポートに失敗した場合
      */
-    public void importToMyCalendar(MyCalendar myCalendar) throws IOException {
+    public void importToMyCalendar(Key myCalendarKey) throws IOException {
+        MyCalendar myCalendar =
+                Datastore.getOrNull(MyCalendar.class, myCalendarKey);
+        if (myCalendar == null) {
+            return;
+        }
         com.google.api.services.calendar.Calendar client =
-                createGoogleCalendarClient();
+                createGoogleCalendarClient(myCalendar.getUser());
         if (client != null) {
             NicoliveMeta n = NicoliveMeta.get();
             MyCalendarLogMeta ml = MyCalendarLogMeta.get();
@@ -366,9 +382,7 @@ public class CalendarService {
                         Datastore
                             .query(ml)
                             .filter(
-                                ml.userId.equal(myCalendar
-                                    .getUser()
-                                    .getUserId()),
+                                ml.user.equal(myCalendar.getUser()),
                                 ml.nicolive.equal(nicolive.getKey()))
                             .count();
                 if (count <= 0) {
@@ -397,11 +411,13 @@ public class CalendarService {

                     // インポートしたNicoliveをmyCalendarLogに登録して、二度とインポートしないようにする。
                     MyCalendarLog myCalendarLog = new MyCalendarLog();
-                    myCalendarLog.setUserId(myCalendar.getUser().getUserId());
+                    myCalendarLog.setUser(myCalendar.getUser());
                     myCalendarLog.getNicolive().setModel(nicolive);
                     myCalendarLogs.add(myCalendarLog);
                 }
+            }

+            if (0 < myCalendarLogs.size()) {
                 Datastore.putAsync(myCalendarLogs);
             }
         }
diff --git a/src/main/java/org/ryu22e/nico2cal/servlet/ConnectGoogleApiCallback.java b/src/main/java/org/ryu22e/nico2cal/servlet/ConnectGoogleApiCallback.java
index e07544b..040e0c7 100644
--- a/src/main/java/org/ryu22e/nico2cal/servlet/ConnectGoogleApiCallback.java
+++ b/src/main/java/org/ryu22e/nico2cal/servlet/ConnectGoogleApiCallback.java
@@ -45,7 +45,7 @@ public final class ConnectGoogleApiCallback extends
     @Override
     protected void onSuccess(HttpServletRequest req, HttpServletResponse resp,
             Credential credential) throws ServletException, IOException {
-        MyCalendar myCalendar = calendarService.getMyCalendar();
+        MyCalendar myCalendar = calendarService.getCurrentMyCalendar();
         if (myCalendar != null) {
             myCalendar.setDisabled(false);
             calendarService.putMyCalendar(myCalendar);
diff --git a/src/test/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllControllerTest.java b/src/test/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllControllerTest.java
new file mode 100644
index 0000000..bc818e0
--- /dev/null
+++ b/src/test/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllControllerTest.java
@@ -0,0 +1,49 @@
+package org.ryu22e.nico2cal.controller.myCalendar;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.ryu22e.nico2cal.model.MyCalendar;
+import org.slim3.datastore.Datastore;
+import org.slim3.tester.ControllerTestCase;
+
+import com.google.appengine.api.users.User;
+
+/**
+ * @author ryu22e
+ *
+ */
+public class ImportAllControllerTest extends ControllerTestCase {
+
+    /**
+     * @throws Exception
+     */
+    @Test
+    public void run() throws Exception {
+        // テストデータの登録。
+        List<MyCalendar> myCalendars = new ArrayList<MyCalendar>();
+        for (int i = 0; i < 10; i++) {
+            MyCalendar myCalendar = new MyCalendar();
+            myCalendar.setCalendarId("test" + i);
+            myCalendar.setUser(new User(
+                "test" + i + "@gmail.com",
+                "example.com",
+                "test" + i));
+            myCalendar.setDisabled(false);
+            myCalendars.add(myCalendar);
+        }
+        Datastore.put(myCalendars);
+
+        tester.start("/myCalendar/importAll");
+        ImportAllController controller = tester.getController();
+        assertThat(controller, is(notNullValue()));
+        assertThat(tester.isRedirect(), is(false));
+        assertThat(tester.response.getStatus(), is(200));
+
+        assertThat(tester.tasks.size(), is(10));
+    }
+}
diff --git a/src/test/java/org/ryu22e/nico2cal/service/CalendarServiceTest.java b/src/test/java/org/ryu22e/nico2cal/service/CalendarServiceTest.java
index 6ccd215..0407468 100644
--- a/src/test/java/org/ryu22e/nico2cal/service/CalendarServiceTest.java
+++ b/src/test/java/org/ryu22e/nico2cal/service/CalendarServiceTest.java
@@ -66,13 +66,14 @@ public final class CalendarServiceTest extends AppEngineTestCase {
                 new NetHttpTransport(),
                 new JacksonFactory()).build())
             .when(mockService)
-            .createGoogleCalendarClientFromUserId("42");
+            .createGoogleCalendarClientFromUserId("dummy");
         CalendarList calendarList = new CalendarList();
         calendarList.setItems(Arrays.asList(
             new CalendarListEntry(),
             new CalendarListEntry(),
             new CalendarListEntry()));
-        doReturn(calendarList).when(mockService).getGoogleCalendarList();
+        doReturn(calendarList).when(mockService).getGoogleCalendarList(
+            new User("dummy@gmail.com", "example.com", "dummy"));

         return mockService;
     }
@@ -248,21 +249,19 @@ public final class CalendarServiceTest extends AppEngineTestCase {
     /**
      * @throws Exception
      */
-    @Test
-    public void GoogleCalendarAPI用Clientを取得する_ログインしていない() throws Exception {
+    @Test(expected = NullPointerException.class)
+    public void GoogleCalendarAPI用Clientを取得する_パラメータがnull() throws Exception {
         CalendarService mockService = createMockService();
         assertThat(mockService, is(notNullValue()));

-        com.google.api.services.calendar.Calendar calendar =
-                mockService.createGoogleCalendarClient();
-        assertThat(calendar, is(nullValue()));
+        mockService.createGoogleCalendarClient(null);
     }

     /**
      * @throws Exception
      */
     @Test
-    public void GoogleCalendarAPI用Clientを取得する_ログインしている() throws Exception {
+    public void GoogleCalendarAPI用Clientを取得する() throws Exception {
         CalendarService mockService = createMockService();
         assertThat(mockService, is(notNullValue()));

@@ -273,21 +272,13 @@ public final class CalendarServiceTest extends AppEngineTestCase {
             "42");
         tester.environment.setAttributes(envAttributes);
         com.google.api.services.calendar.Calendar calendar =
-                mockService.createGoogleCalendarClient();
+                mockService.createGoogleCalendarClient(new User(
+                    "dummy@gmail.com",
+                    "example.com",
+                    "dummy"));
         assertThat(calendar, is(notNullValue()));
-        verify(mockService, times(1))
-            .createGoogleCalendarClientFromUserId("42");
-    }
-
-    /**
-     * @throws Exception
-     */
-    @Test
-    public void GoogleCalendarのカレンダー一覧を取得する_ログインしていない() throws Exception {
-        assertThat(service, is(notNullValue()));
-
-        CalendarList feed = service.getGoogleCalendarList();
-        assertThat(feed, is(nullValue()));
+        verify(mockService, times(1)).createGoogleCalendarClientFromUserId(
+            "dummy");
     }

     /**
@@ -298,16 +289,12 @@ public final class CalendarServiceTest extends AppEngineTestCase {
         CalendarService mockService = createMockService();
         assertThat(mockService, is(notNullValue()));

-        tester.environment.setEmail("dummy@gmail.com");
-        Map<String, Object> envAttributes = new HashMap<String, Object>();
-        envAttributes.put(
-            "com.google.appengine.api.users.UserService.user_id_key",
-            "42");
-        CalendarList feed = mockService.getGoogleCalendarList();
+        User user = new User("dummy@gmail.com", "example.com", "dummy");
+        CalendarList feed = mockService.getGoogleCalendarList(user);
         assertThat(feed, is(notNullValue()));
         assertThat(feed.getItems(), is(notNullValue()));
         assertThat(feed.getItems().size(), is(3));
-        verify(mockService, times(1)).getGoogleCalendarList();
+        verify(mockService, times(1)).getGoogleCalendarList(user);
     }

     /**
@@ -408,7 +395,7 @@ public final class CalendarServiceTest extends AppEngineTestCase {
         myCalendar
             .setUser(UserServiceFactory.getUserService().getCurrentUser());
         Datastore.put(myCalendar);
-        MyCalendar result = service.getMyCalendar();
+        MyCalendar result = service.getCurrentMyCalendar();
         assertThat(result, is(nullValue()));
     }

@@ -425,7 +412,7 @@ public final class CalendarServiceTest extends AppEngineTestCase {
         myCalendar
             .setUser(UserServiceFactory.getUserService().getCurrentUser());
         Key key = Datastore.put(myCalendar);
-        MyCalendar result = service.getMyCalendar();
+        MyCalendar result = service.getCurrentMyCalendar();
         assertThat(result, is(notNullValue()));
         assertThat(result.getKey(), is(key));
     }
@@ -438,7 +425,7 @@ public final class CalendarServiceTest extends AppEngineTestCase {
         assertThat(service, is(notNullValue()));

         tester.environment.setEmail("dummy@gmail.com");
-        MyCalendar result = service.getMyCalendar();
+        MyCalendar result = service.getCurrentMyCalendar();
         assertThat(result, is(nullValue()));
     }

@@ -575,17 +562,64 @@ public final class CalendarServiceTest extends AppEngineTestCase {
      * @throws Exception
      */
     @Test
+    public void 連携対象カレンダーのキーリストを取得する() throws Exception {
+        assertThat(service, is(notNullValue()));
+
+        // テストデータの登録。
+        List<MyCalendar> testDataList = new ArrayList<MyCalendar>();
+        for (int i = 0; i < 10; i++) {
+            MyCalendar myCalendar = new MyCalendar();
+            myCalendar.setCalendarId("test" + 1);
+            myCalendar.setUser(new User(
+                "test" + 1 + "@gmail.com",
+                "example.com",
+                "test" + 1));
+            myCalendar.setDisabled(false);
+            testDataList.add(myCalendar);
+        }
+        List<Key> testDatakeys = Datastore.put(testDataList);
+        MyCalendar disabledMyCalendar = new MyCalendar();
+        disabledMyCalendar.setCalendarId("disabledCalendarId");
+        disabledMyCalendar.setUser(new User(
+            "test" + 1 + "@gmail.com",
+            "example.com",
+            "test" + 1));
+        disabledMyCalendar.setDisabled(true);
+        Datastore.put(disabledMyCalendar);
+
+        List<Key> result = service.getMyCalendarKeys();
+        assertThat(result, is(notNullValue()));
+        assertThat(result, is(testDatakeys));
+    }
+
+    /**
+     * @throws Exception
+     */
+    @Test
+    public void 連携対象カレンダーのキーリストを取得する_データが存在しない() throws Exception {
+        assertThat(service, is(notNullValue()));
+
+        List<Key> result = service.getMyCalendarKeys();
+        assertThat(result, is(notNullValue()));
+        assertThat(result.size(), is(0));
+    }
+
+    /**
+     * @throws Exception
+     */
+    @Test
     public void GoogleCalendarにニコニコ生放送の放送予定日をインポートする() throws Exception {
-        CalendarService mockservice = createMockService();
-        assertThat(mockservice, is(notNullValue()));
+        CalendarService mockService = createMockService();
+        assertThat(mockService, is(notNullValue()));

-        tester.environment.setEmail("dummy@gmail.com");
-        Map<String, Object> envAttributes = new HashMap<String, Object>();
-        envAttributes.put(
-            "com.google.appengine.api.users.UserService.user_id_key",
-            "42");
-        tester.environment.setAttributes(envAttributes);
-        User user = UserServiceFactory.getUserService().getCurrentUser();
+        User user = new User("dummy@gmail.com", "example.com", "dummy");
+
+        doReturn(
+            com.google.api.services.calendar.Calendar.builder(
+                new NetHttpTransport(),
+                new JacksonFactory()).build())
+            .when(mockService)
+            .createGoogleCalendarClient(user);

         // テストデータの登録。
         List<Nicolive> testDataList = new ArrayList<Nicolive>();
@@ -599,25 +633,22 @@ public final class CalendarServiceTest extends AppEngineTestCase {
             testDataList.add(nicolive);
         }
         List<Key> testDataKeys = Datastore.put(testDataList);
-
         MyCalendar myCalendar = new MyCalendar();
         myCalendar.setCalendarId("calendar1");
         myCalendar.setUser(user);
-        mockservice.importToMyCalendar(myCalendar);
+        Key myCalendarKey = Datastore.put(myCalendar);
+
+        mockService.importToMyCalendar(myCalendarKey);

         MyCalendarLogMeta ml = MyCalendarLogMeta.get();
         List<MyCalendarLog> myCalendarLogs =
-                Datastore
-                    .query(ml)
-                    .filter(ml.userId.equal(user.getUserId()))
-                    .asList();
+                Datastore.query(ml).filter(ml.user.equal(user)).asList();
         assertThat(myCalendarLogs, is(notNullValue()));
         assertThat(myCalendarLogs.size(), is(10));
         List<Key> storedKeys = new ArrayList<Key>();
         for (MyCalendarLog myCalendarLog : myCalendarLogs) {
             storedKeys.add(myCalendarLog.getNicolive().getKey());
         }
-        assertThat(storedKeys, hasItems(testDataKeys.toArray(new Key[0])));
+        assertThat(storedKeys, is(testDataKeys));
     }
-
 }
diff --git a/war/WEB-INF/cron.xml b/war/WEB-INF/cron.xml
index cb302f4..0a89fe3 100644
--- a/war/WEB-INF/cron.xml
+++ b/war/WEB-INF/cron.xml
@@ -12,4 +12,10 @@
     <schedule>every day 00:00</schedule>
     <timezone>Asia/Tokyo</timezone>
   </cron>
+  <cron>
+    <url>/myCalendar/importAll</url>
+    <description>Generate Nicolive</description>
+    <schedule>every 1 hours</schedule>
+    <timezone>Asia/Tokyo</timezone>
+  </cron>
 </cronentries>
\ No newline at end of file
diff --git a/war/WEB-INF/web.xml b/war/WEB-INF/web.xml
index 22ae295..ff1cf77 100644
--- a/war/WEB-INF/web.xml
+++ b/war/WEB-INF/web.xml
@@ -173,6 +173,7 @@
     </security-constraint>
     <security-constraint>
         <web-resource-collection>
+            <url-pattern>/myCalendar/importAll</url-pattern>
             <url-pattern>/myCalendar/import</url-pattern>
         </web-resource-collection>
         <auth-constraint>
[from now] 2012/05/30 17:13:35

diff --git a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllController.java b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllController.java
index 03d39ee..9db3c1e 100644
--- a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllController.java
+++ b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportAllController.java
@@ -3,12 +3,12 @@ package org.ryu22e.nico2cal.controller.myCalendar;
 import java.util.List;
 import java.util.logging.Logger;

-import org.ryu22e.nico2cal.model.MyCalendar;
 import org.ryu22e.nico2cal.service.CalendarService;
 import org.slim3.controller.Controller;
 import org.slim3.controller.Navigation;
 import org.slim3.datastore.Datastore;

+import com.google.appengine.api.datastore.Key;
 import com.google.appengine.api.taskqueue.QueueFactory;
 import com.google.appengine.api.taskqueue.TaskOptions;
 import com.google.appengine.api.taskqueue.TaskOptions.Method;
@@ -38,18 +38,14 @@ public final class ImportAllController extends Controller {
     public Navigation run() throws Exception {
         LOGGER.info("BEGIN: " + this.getClass().getName());

-        List<MyCalendar> myCalendars = calendarService.getMyCalendars();
-        for (MyCalendar myCalendar : myCalendars) {
+        List<Key> myCalendarKeys = calendarService.getMyCalendarKeys();
+        for (Key key : myCalendarKeys) {
             TaskOptions options =
-                    TaskOptions.Builder
-                        .withUrl("/GenerateNicoliveIndex")
-                        .method(Method.POST);
+                    TaskOptions.Builder.withUrl("/myCalendar/import").method(
+                        Method.POST);
             options =
-                    options.param(
-                        "key",
-                        Datastore.keyToString(myCalendar.getKey()));
-            options = options.param("userId", myCalendar.getUser().getUserId());
-            QueueFactory.getQueue("generate-nicoliveindex").add(options);
+                    options.param("myCalendarKey", Datastore.keyToString(key));
+            QueueFactory.getQueue("mycalendar-import").add(options);
         }

         LOGGER.info("END: " + this.getClass().getName());
diff --git a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportController.java b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportController.java
index 504c05d..545b421 100644
--- a/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportController.java
+++ b/src/main/java/org/ryu22e/nico2cal/controller/myCalendar/ImportController.java
@@ -1,7 +1,13 @@
 package org.ryu22e.nico2cal.controller.myCalendar;

+import java.io.IOException;
+import java.util.logging.Logger;
+
+import org.ryu22e.nico2cal.service.CalendarService;
 import org.slim3.controller.Controller;
 import org.slim3.controller.Navigation;
+import org.slim3.controller.validator.Validators;
+import org.slim3.datastore.Datastore;

 /**
  * Google Calendarに{@link org.ryu22e.nico2cal.model.Nicolive}の内容を個別の{@link org.ryu22e.nico2cal.model.MyCalendar}にインポートするコントローラー。
@@ -10,11 +16,34 @@ import org.slim3.controller.Navigation;
  */
 public final class ImportController extends Controller {

+    /**
+     *
+     */
+    public static final Logger LOGGER = Logger
+        .getLogger(ImportAllController.class.getName());
+
+    /**
+     *
+     */
+    private CalendarService calendarService = new CalendarService();
+
     /*
      * (non-Javadoc) {@inheritDoc}
      */
     @Override
     public Navigation run() throws Exception {
+        Validators v = new Validators(request);
+        v.add("myCalendarKey", v.required());
+        if (v.validate()) {
+            try {
+                calendarService.importToMyCalendar(Datastore
+                    .stringToKey(param("myCalendarKey")));
+            } catch (IllegalArgumentException e) {
+                LOGGER.warning(e.getMessage());
+            } catch (IOException e) {
+                LOGGER.warning(e.getMessage());
+            }
+        }
         return null;
     }
 }
diff --git a/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java b/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java
index ccdec55..6ab134a 100644
--- a/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java
+++ b/src/main/java/org/ryu22e/nico2cal/service/CalendarService.java
@@ -3,7 +3,6 @@ package org.ryu22e.nico2cal.service;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
@@ -376,7 +375,6 @@ public class CalendarService {
                         .query(n)
                         .filter(n.openTime.greaterThanOrEqual(d.toDate()))
                         .asList();
-            List<MyCalendarLog> myCalendarLogs = new ArrayList<MyCalendarLog>();
             for (Nicolive nicolive : nicolives) {
                 int count =
                         Datastore
@@ -413,13 +411,9 @@ public class CalendarService {
                     MyCalendarLog myCalendarLog = new MyCalendarLog();
                     myCalendarLog.setUser(myCalendar.getUser());
                     myCalendarLog.getNicolive().setModel(nicolive);
-                    myCalendarLogs.add(myCalendarLog);
+                    Datastore.putAsync(myCalendarLog);
                 }
             }
-
-            if (0 < myCalendarLogs.size()) {
-                Datastore.putAsync(myCalendarLogs);
-            }
         }
     }
 }