package org.openehr.designer.web;

import com.google.common.collect.Maps;
import org.openehr.designer.repository.ArchetypeRepository;
import org.openehr.designer.repository.TemplateRepository;
import org.openehr.designer.repository.github.GithubArchetypeRepository;
import org.openehr.designer.repository.github.GithubTemplateRepository;

import java.util.Map;
import java.util.Objects;

/**
 * Created by Denko on 10/28/2015.
 */
public class RepositoryProvider {
    public static Map<RepoKey, GithubTemplateRepository> userToTemplateRepositoryMap = Maps.newConcurrentMap();
    public static Map<RepoKey, GithubArchetypeRepository> userToArchetypeRepositoryMap = Maps.newConcurrentMap();


    public TemplateRepository getTemplateRepository(SessionContext conf) {
        return getTemplateRepository(conf, conf.getGithubRepository());
    }

    public ArchetypeRepository getArchetypeRepository(SessionContext conf) {
        return getArchetypeRepository(conf, conf.getGithubRepository());
    }

    public TemplateRepository getTemplateRepository(SessionContext conf, String repositoryName) {
        return userToTemplateRepositoryMap.computeIfAbsent(new RepoKey(conf.getUsername(), repositoryName), (u) -> {
            GithubTemplateRepository r = new GithubTemplateRepository();
            r.init(conf.getUsername(), conf.getGithubToken(), repositoryName);
            return r;
        });
    }

    public ArchetypeRepository getArchetypeRepository(SessionContext conf, String repositoryName) {

        return userToArchetypeRepositoryMap.computeIfAbsent(new RepoKey(conf.getUsername(), repositoryName), (u) -> {
            GithubArchetypeRepository r = new GithubArchetypeRepository();
            r.init(conf.getUsername(), conf.getGithubToken(), repositoryName);
            return r;
        });
    }

    private static final class RepoKey {
        final String username;
        final String repositoryName;

        RepoKey(String username, String repositoryName) {
            this.username = username;
            this.repositoryName = repositoryName;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            RepoKey key = (RepoKey) o;
            return Objects.equals(username, key.username) &&
                    Objects.equals(repositoryName, key.repositoryName);
        }

        static RepoKey from(SessionContext ctx) {
            return new RepoKey(ctx.getUsername(), ctx.getGithubRepository());
        }

        @Override
        public int hashCode() {
            return Objects.hash(username, repositoryName);
        }
    }
}

@@ -58,19 +58,63 @@
 on.c
-ollect.Maps
+ache.Cache;%0Aimport com.google.common.cache.CacheBuilder
 ;%0Aim
@@ -380,30 +380,8 @@
 y;%0A%0A
-import java.util.Map;%0A
 impo
@@ -401,16 +401,140 @@
 Objects;
+%0Aimport java.util.concurrent.Callable;%0Aimport java.util.concurrent.ExecutionException;%0Aimport java.util.concurrent.TimeUnit;
 %0A%0A/**%0A *
@@ -614,35 +614,37 @@
   public static 
-Map
+Cache
 %3CRepoKey, Github
@@ -692,38 +692,173 @@
 oryMap =
- Maps.newConcurrentMap
+%0A            CacheBuilder.%3CRepoKey, GithubTemplateRepository%3EnewBuilder()%0A                    .expireAfterAccess(1, TimeUnit.DAYS)%0A                    .build
 ();%0A    
@@ -871,19 +871,21 @@
  static 
-Map
+Cache
 %3CRepoKey
@@ -947,30 +947,166 @@
 ap =
- Maps.newConcurrentMap
+%0A            CacheBuilder.%3CRepoKey, GithubArchetypeRepository%3EnewBuilder()%0A                    .expireAfterAccess(1, TimeUnit.DAYS)%0A                    .build
 ();%0A
@@ -1410,32 +1410,409 @@
 tory());%0A    %7D%0A%0A
+    private %3CK, V%3E V computeIfAbsent(Cache%3CK, V%3E cache, K key, Callable%3CV%3E supplier) %7B%0A        try %7B%0A            return cache.get(key, supplier);%0A        %7D catch (ExecutionException e) %7B%0A            if (e.getCause() instanceof RuntimeException) %7B%0A                throw (RuntimeException) e.getCause();%0A            %7D%0A            throw new RuntimeException(e);%0A        %7D%0A%0A    %7D%0A%0A
     public Templ
@@ -1904,24 +1904,40 @@
      return 
+computeIfAbsent(
 userToTempla
@@ -1951,33 +1951,18 @@
 itoryMap
-.computeIfAbsent(
+, 
 new Repo
@@ -1995,33 +1995,32 @@
 positoryName), (
-u
 ) -%3E %7B%0A         
@@ -2319,16 +2319,32 @@
  return 
+computeIfAbsent(
 userToAr
@@ -2367,25 +2367,10 @@
 yMap
-.computeIfAbsent(
+, 
 new 
@@ -2415,17 +2415,16 @@
 Name), (
-u
 ) -%3E %7B%0A 

Use cache for repositories