001package org.nasdanika.models.gitlab.util;
002
003import java.io.ByteArrayInputStream;
004import java.io.ByteArrayOutputStream;
005import java.io.IOException;
006import java.io.InputStream;
007import java.io.OutputStream;
008import java.util.Collections;
009import java.util.List;
010import java.util.Map;
011
012import org.eclipse.emf.common.util.URI;
013import org.eclipse.emf.ecore.resource.URIHandler;
014import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
015import org.gitlab4j.api.GitLabApi;
016import org.gitlab4j.api.GitLabApiException;
017import org.gitlab4j.api.RepositoryApi;
018import org.gitlab4j.api.RepositoryFileApi;
019import org.gitlab4j.api.models.TreeItem;
020import org.nasdanika.common.Util;
021import org.nasdanika.models.gitlab.GitLabFactory;
022import org.nasdanika.models.gitlab.Tree;
023
024/**
025 * A very simple implementation of {@link URIHandler} to retrieve content from GitLab using REST API
026 * URI format: <code>gitlab://projectid/ref/path</code>
027 */
028public class GitLabURIHandler implements URIHandler {
029        
030        public static final String GITLAB_URI_SCHEME = "gitlab";
031        
032        protected RepositoryFileApi repositoryFileApi;
033        protected GitLabApi gitLabApi;
034        protected RepositoryApi repositoryApi;
035        
036        public GitLabURIHandler(GitLabApi gitLabApi) {
037                this.gitLabApi = gitLabApi;
038                this.repositoryFileApi = gitLabApi.getRepositoryFileApi();
039                this.repositoryApi = gitLabApi.getRepositoryApi();
040        }
041        
042        @Override
043        public boolean canHandle(URI uri) {
044                return GITLAB_URI_SCHEME.equals(uri.scheme());
045        }
046
047        @Override
048        public InputStream createInputStream(URI uri, Map<?, ?> options) throws IOException {
049                if (Util.isBlank(uri.lastSegment())) {
050                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
051                        XMIResourceImpl resource = new XMIResourceImpl(uri);
052                        try (baos) {
053                                Tree tree = GitLabFactory.eINSTANCE.createTree();
054                                resource.getContents().add(tree);
055                                List<TreeItem> treeItems = repositoryApi.getTree(getProjectIdOrPath(uri), getPath(uri), getRef(uri));
056                                for (TreeItem treeItem: treeItems) {
057                                        switch (treeItem.getType()) {
058                                        case TREE:
059                                                org.nasdanika.models.gitlab.Tree subTree = GitLabFactory.eINSTANCE.createTree();
060                                                subTree.setId(treeItem.getId());
061                                                subTree.setName(treeItem.getName());
062                                                subTree.setPath(treeItem.getPath());
063                                                tree.getTreeItems().add(subTree);
064                                                break;
065                                        case BLOB:
066                                                org.nasdanika.models.gitlab.Blob blob = GitLabFactory.eINSTANCE.createBlob();
067                                                blob.setId(treeItem.getId());
068                                                blob.setName(treeItem.getName());
069                                                blob.setPath(treeItem.getPath());
070                                                tree.getTreeItems().add(blob);
071                                                break;
072                                        case COMMIT:
073                                                break;
074                                        default:
075                                                break;
076                                        
077                                        }
078                                }
079                        } catch (GitLabApiException e) {
080                                throw new IOException(e);
081                        } 
082                        
083                        resource.save(baos, options);
084                        return new ByteArrayInputStream(baos.toByteArray());
085                }
086                
087                try {
088                        return repositoryFileApi.getRawFile(
089                                        getProjectIdOrPath(uri), 
090                                        getRef(uri),
091                                        getPath(uri));
092                } catch (GitLabApiException e) {
093                        throw new IOException(e);
094                }
095        }
096        
097        /**
098         * This method returns URI authority parsed as Long. Override as needed
099         * @param uri
100         * @return
101         */
102        protected Object getProjectIdOrPath(URI uri) {
103                try {
104                        return Long.parseLong(uri.authority());
105                } catch (NumberFormatException e) {
106                        return uri.authority();
107                }
108        }
109                        
110        /**
111         * This method returns the first (0) URI segment
112         * @param uri
113         * @return
114         */
115        protected String getRef(URI uri) {
116                return uri.segment(0);
117        }
118        
119        protected String getPath(URI uri) {
120                return uri.path().substring(uri.segment(0).length() + 2);
121        }
122
123        @Override
124        public OutputStream createOutputStream(URI uri, Map<?, ?> options) throws IOException {
125                throw new UnsupportedOperationException();
126        }
127
128        @Override
129        public void delete(URI uri, Map<?, ?> options) throws IOException {
130                throw new UnsupportedOperationException();
131        }
132
133        @Override
134        public Map<String, ?> contentDescription(URI uri, Map<?, ?> options) throws IOException {
135                return Collections.emptyMap();
136        }
137
138        @Override
139        public boolean exists(URI uri, Map<?, ?> options) {
140                return true; // Need a better way
141        }
142
143        @Override
144        public Map<String, ?> getAttributes(URI uri, Map<?, ?> options) {
145                return Collections.emptyMap();
146        }
147
148        @Override
149        public void setAttributes(URI uri, Map<String, ?> attributes, Map<?, ?> options) throws IOException {
150                throw new UnsupportedOperationException();              
151        }
152
153}