public synchronized ArticlesIndex getIndex(OperationObserver observer) {
    if (index == null) {
      boolean imported = importFromResource();
      File indexFile = getIndexFile();
      observer.onOperationInfoChanged(OperationObserver.LOADING_CACHE, indexFile.getAbsolutePath());
      if (!indexFile.exists()) {
        log.info("Article index file does not exist:", indexFile);
        index = new ArticlesIndex();
        return index;
      }
      try {
        index = JsonMapper.deserialize(indexFile, ArticlesIndex.class, typeResolver);
        log.info("Article index loaded:", index.getArticlesCount(), "articles");
      } catch (Exception ex) {
        log.error("Article indes loading failed:", ex);
        indexFile.delete();
        return getIndex(observer);
      }
      if (imported) {
        viewed.addAll(index.getArticles());
      } else {
        for (ArticleRef article : index.getArticles()) {
          article.repairTitle();
        }
      }
    }

    return index;
  }
 public Article loadArticle(ArticleRef ref, OperationObserver observer) throws ParseException {
   String html = articlePagesCache.loadFromCache(ref.getPageRef(), observer);
   if (html != null) {
     Article article = TestDe.parseArticle(ref, html);
     if (!article.containsLockedSubArticles()) return article;
     if (loginDataProvider.getLoginData() == null) return article;
     if (!TestDe.http.isInternetAvailable()) return article;
     articlePagesCache.delete(ref.getPageRef());
   }
   loginIfAvailable(observer);
   html = articlePagesCache.load(ref.getPageRef(), observer);
   return TestDe.parseArticle(ref, html);
 }
 public synchronized void addAll(Collection<ArticleRef> articleRefs) {
   for (ArticleRef articleRef : articleRefs) {
     pageIds.add(articleRef.getPageId());
   }
   save();
 }
 public synchronized void remove(ArticleRef articleRef) {
   pageIds.remove(articleRef.getPageId());
   save();
 }
 public synchronized void add(ArticleRef articleRef) {
   pageIds.add(articleRef.getPageId());
   save();
 }
 public boolean contains(ArticleRef articleRef) {
   if (articleRef == null) return false;
   return pageIds.contains(articleRef.getPageId());
 }
 public void clearArticle(ArticleRef articleRef) {
   articlePagesCache.delete(articleRef.getPageRef());
 }