{"action":"created","comment":{"url":"https://api.github.com/repos/ModeShape/modeshape/pulls/comments/63846945","id":63846945,"diff_hunk":"@@ -0,0 +1,346 @@\n+/*\n+ * ModeShape (http://www.modeshape.org)\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *       http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+package org.modeshape.sequencer.epub;\n+\n+import java.io.BufferedOutputStream;\n+import java.io.ByteArrayInputStream;\n+import java.io.ByteArrayOutputStream;\n+import java.io.File;\n+import java.io.FileInputStream;\n+import java.io.FileOutputStream;\n+import java.io.IOException;\n+import java.io.InputStream;\n+import java.util.ArrayList;\n+import java.util.Arrays;\n+import java.util.HashMap;\n+import java.util.Iterator;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.zip.ZipEntry;\n+import java.util.zip.ZipInputStream;\n+\n+import javax.xml.namespace.NamespaceContext;\n+import javax.xml.parsers.DocumentBuilder;\n+import javax.xml.parsers.DocumentBuilderFactory;\n+import javax.xml.xpath.XPath;\n+import javax.xml.xpath.XPathConstants;\n+import javax.xml.xpath.XPathExpression;\n+import javax.xml.xpath.XPathFactory;\n+\n+import org.modeshape.common.util.IoUtil;\n+import org.modeshape.sequencer.epub.EpubMetadataProperty.AlternateScript;\n+import org.w3c.dom.Document;\n+import org.w3c.dom.Node;\n+import org.w3c.dom.NodeList;\n+\n+/**\n+ * Utility for extracting Metadata from EPUB format.\n+ */\n+public class EpubMetadata {\n+\n+    static final String[] MIME_TYPE_STRINGS = { \"application/epub+zip\" };\n+\n+    // The XML namespace for the Dublin Core schema.\n+    static final String DUBLIN_CORE_PREFIX = \"dc\";\n+    static final String DUBLIN_CORE_URI = \"http://purl.org/dc/elements/1.1/\";\n+\n+    private List<EpubMetadataProperty> title = new ArrayList<>();\n+    private List<EpubMetadataProperty> creator = new ArrayList<>();\n+    private List<EpubMetadataProperty> contributor = new ArrayList<>();\n+    private List<EpubMetadataProperty> language = new ArrayList<>();\n+    private List<EpubMetadataProperty> identifier = new ArrayList<>();\n+    private List<EpubMetadataProperty> description = new ArrayList<>();\n+    private List<EpubMetadataProperty> publisher = new ArrayList<>();\n+    private List<EpubMetadataProperty> rights = new ArrayList<>();\n+    private List<EpubMetadataProperty> date = new ArrayList<>();\n+    private List<EpubMetadataProperty> alternateScript = new ArrayList<>();\n+\n+    private InputStream in;\n+\n+    public EpubMetadata( InputStream inputStream ) {\n+        this.in = inputStream;\n+    }\n+\n+    /*\n+     * Check that given file is supported by this sequencer.\n+     * The sequencer first examines the container to get the list of all rootfiles.\n+     * Then it process each rootfile and extracts the metadata.\n+     */\n+    public boolean check() throws Exception {\n+        // we need to create a copy of the file, because the container file\n+        // might be at the end of the stream.\n+        File fileCopy = File.createTempFile(\"modeshape-sequencer-epub\", \".tmp\");\n+        IoUtil.write(in, new BufferedOutputStream(new FileOutputStream(fileCopy)));\n+\n+        ZipInputStream zipStream = new ZipInputStream(new FileInputStream(fileCopy));\n+        List<String> rootfiles = getRootfiles(zipStream);\n+        zipStream.close();\n+\n+        zipStream = new ZipInputStream(new FileInputStream(fileCopy));\n+        if (!rootfiles.isEmpty()) {\n+            ZipEntry entry = null;\n+            while ((entry = zipStream.getNextEntry()) != null) {\n+                String entryName = entry.getName();\n+                if (rootfiles.contains(entryName)) {\n+                    checkRootfile(zipStream, entry);\n+                }\n+            }\n+        } else {\n+            throw new IllegalArgumentException(\"No rootfile package found in given EPUB file.\");\n+        }\n+\n+        zipStream.close();\n+        // try to delete the file immediately or on JVM exit\n+        boolean deleted = false;\n+        try {\n+            deleted = fileCopy.delete();\n+        } catch (SecurityException e) {\n+            // ignore\n+        }\n+        if (!deleted) {\n+            fileCopy.deleteOnExit();\n+        }\n+\n+        return true;\n+    }\n+\n+    /**\n+     * Process the EPUB package and extract the metadata fields.\n+     */\n+    private boolean checkRootfile( ZipInputStream zipStream,\n+                                   ZipEntry entry ) throws Exception {\n+        List<EpubMetadataProperty> properties = new ArrayList<>();\n+        Map<String, EpubMetadataProperty> propertiesWithId = new HashMap<>();\n+\n+        ByteArrayOutputStream content = getZipEntryContent(zipStream, entry);\n+\n+        // get metadata elements\n+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();\n+        factory.setNamespaceAware(true);\n+        DocumentBuilder builder = factory.newDocumentBuilder();\n+        Document doc = builder.parse(new ByteArrayInputStream(content.toByteArray()));\n+\n+        XPathFactory xPathfactory = XPathFactory.newInstance();\n+        XPath xpath = xPathfactory.newXPath();\n+        xpath.setNamespaceContext(new SimpleNSC(DUBLIN_CORE_PREFIX, DUBLIN_CORE_URI));\n+        XPathExpression expr = xpath.compile(\"//\" + DUBLIN_CORE_PREFIX + \":*\");\n+        NodeList metadata = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);\n+\n+        for (int i = 0; i < metadata.getLength(); i++) {\n+            EpubMetadataProperty property = new EpubMetadataProperty();\n+\n+            Node node = metadata.item(i);\n+            property.setName(node.getLocalName());\n+            property.setValue(node.getTextContent());\n+\n+            Node nodeId = node.getAttributes().getNamedItem(\"id\");\n+            if (nodeId != null) {\n+                String id = nodeId.getTextContent();\n+                if (!propertiesWithId.containsKey(id)) {\n+                    propertiesWithId.put(id, property);\n+                }\n+            } else {\n+                properties.add(property);\n+            }\n+        }\n+\n+        // read <meta> elements which can refine the properties\n+        NodeList metadataRefines = doc.getElementsByTagName(\"meta\");\n+        for (int i = 0; i < metadataRefines.getLength(); i++) {\n+            Node node = metadataRefines.item(i);\n+            Node refines = node.getAttributes().getNamedItem(\"refines\");\n+            if (refines != null) {\n+                String refinesId = refines.getTextContent().substring(1);\n+                if (propertiesWithId.containsKey(refinesId)) {\n+                    EpubMetadataProperty property = propertiesWithId.get(refinesId);\n+\n+                    Node schemeAttribute = node.getAttributes().getNamedItem(\"scheme\");\n+                    if (schemeAttribute != null) {\n+                        property.setScheme(schemeAttribute.getTextContent());\n+                    }\n+\n+                    String propertyName = node.getAttributes().getNamedItem(\"property\").getTextContent();\n+                    if (propertyName.equals(\"title-type\")) {\n+                        property.setTitleType(node.getTextContent());\n+                    } else if (propertyName.equals(\"identifier-type\")) {\n+                        property.setIdentifierType(node.getTextContent());\n+                    } else if (propertyName.equals(\"metadata-authority\")) {\n+                        property.setMetadataAuthority(node.getTextContent());\n+                    } else if (propertyName.equals(\"role\")) {\n+                        property.setRole(node.getTextContent());\n+                    } else if (propertyName.equals(\"display-seq\")) {\n+                        property.setDisplaySeq(Long.parseLong(node.getTextContent()));\n+                    } else if (propertyName.equals(\"group-position\")) {\n+                        property.setGroupPosition(Long.parseLong(node.getTextContent()));\n+                    } else if (propertyName.equals(\"file-as\")) {\n+                        property.setFileAs(node.getTextContent());\n+                    } else if (propertyName.equals(\"alternate-script\")) {\n+                        Node languageAttribute = node.getAttributes().getNamedItem(\"xml:lang\");\n+                        if (languageAttribute != null) {\n+                            property.setAlternateScript(new AlternateScript(node.getTextContent(), languageAttribute.getTextContent()));\n+                        }\n+                    }\n+                }\n+            }\n+        }\n+\n+        properties.addAll(propertiesWithId.values());\n+        for (EpubMetadataProperty prop : properties) {\n+            String propertyName = prop.getName();\n+            if (propertyName.equals(\"identifier\")) {\n+                getIdentifier().add(prop);\n+            } else if (propertyName.equals(\"title\")) {\n+                getTitle().add(prop);\n+            } else if (propertyName.equals(\"language\")) {\n+                getLanguage().add(prop);\n+            } else if (propertyName.equals(\"contributor\")) {\n+                getContributor().add(prop);\n+            } else if (propertyName.equals(\"creator\")) {\n+                getCreator().add(prop);\n+            } else if (propertyName.equals(\"description\")) {\n+                getDescription().add(prop);\n+            } else if (propertyName.equals(\"publisher\")) {\n+                getPublisher().add(prop);\n+            } else if (propertyName.equals(\"rights\")) {\n+                getRights().add(prop);\n+            } else if (propertyName.equals(\"date\")) {\n+                getDate().add(prop);\n+            }\n+        }\n+\n+        return true;\n+    }\n+\n+    /**\n+     * Parse the container file to get the list of all rootfile packages.\n+     */\n+    private List<String> getRootfiles( ZipInputStream zipStream ) throws Exception {\n+        List<String> rootfiles = new ArrayList<String>();\n+        ZipEntry entry = null;\n+        while ((entry = zipStream.getNextEntry()) != null) {\n+            String entryName = entry.getName();\n+            if (entryName.endsWith(\"META-INF/container.xml\")) {\n+                ByteArrayOutputStream content = getZipEntryContent(zipStream, entry);\n+\n+                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();\n+                DocumentBuilder builder = factory.newDocumentBuilder();\n+                Document doc = builder.parse(new ByteArrayInputStream(content.toByteArray()));\n+\n+                XPathFactory xPathfactory = XPathFactory.newInstance();\n+                XPath xpath = xPathfactory.newXPath();\n+                XPathExpression expr = xpath.compile(\"/container/rootfiles/rootfile\");\n+                NodeList rootfileNodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);\n+\n+                for (int i = 0; i < rootfileNodes.getLength(); i++) {\n+                    Node node = rootfileNodes.item(i);\n+                    rootfiles.add(node.getAttributes().getNamedItem(\"full-path\").getNodeValue());\n+                }\n+                break;\n+            }\n+        }\n+        return rootfiles;\n+    }\n+\n+    /**\n+     * Read the content of the ZipEntry without closing the stream.\n+     */\n+    private ByteArrayOutputStream getZipEntryContent(\n+            ZipInputStream zipStream,\n+            ZipEntry entry ) throws IOException {\n+        ByteArrayOutputStream content = new ByteArrayOutputStream();\n+        byte[] bytes = new byte[(int) entry.getSize()];\n+        int read;\n+        while ((read = zipStream.read(bytes, 0, bytes.length)) != -1) {\n+            content.write(bytes, 0, read);\n+        }\n+        content.flush();\n+        return content;\n+    }\n+\n+    public List<EpubMetadataProperty> getTitle() {\n+        return title;\n+    }\n+\n+    public List<EpubMetadataProperty> getCreator() {\n+        return creator;\n+    }\n+\n+    public List<EpubMetadataProperty> getContributor() {\n+        return contributor;\n+    }\n+\n+    public List<EpubMetadataProperty> getLanguage() {\n+        return language;\n+    }\n+\n+    public List<EpubMetadataProperty> getIdentifier() {\n+        return identifier;\n+    }\n+\n+    public List<EpubMetadataProperty> getDescription() {\n+        return description;\n+    }\n+\n+    public List<EpubMetadataProperty> getPublisher() {\n+        return publisher;\n+    }\n+\n+    public List<EpubMetadataProperty> getRights() {\n+        return rights;\n+    }\n+\n+    public List<EpubMetadataProperty> getDate() {\n+        return date;\n+    }\n+\n+    public List<EpubMetadataProperty> getAlternateScript() {\n+        return alternateScript;\n+    }\n+\n+    /**\n+     * Simple NamespaceContext which can resolve single namespace.\n+     */\n+    private class SimpleNSC implements NamespaceContext {","path":"sequencers/modeshape-sequencer-epub/src/main/java/org/modeshape/sequencer/epub/EpubMetadata.java","position":316,"original_position":316,"commit_id":"3cc21f071ddb57bc7f06281c60e61e485126859d","original_commit_id":"3cc21f071ddb57bc7f06281c60e61e485126859d","user":{"login":"hchiorean","id":995683,"avatar_url":"https://avatars.githubusercontent.com/u/995683?v=3","gravatar_id":"","url":"https://api.github.com/users/hchiorean","html_url":"https://github.com/hchiorean","followers_url":"https://api.github.com/users/hchiorean/followers","following_url":"https://api.github.com/users/hchiorean/following{/other_user}","gists_url":"https://api.github.com/users/hchiorean/gists{/gist_id}","starred_url":"https://api.github.com/users/hchiorean/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hchiorean/subscriptions","organizations_url":"https://api.github.com/users/hchiorean/orgs","repos_url":"https://api.github.com/users/hchiorean/repos","events_url":"https://api.github.com/users/hchiorean/events{/privacy}","received_events_url":"https://api.github.com/users/hchiorean/received_events","type":"User","site_admin":false},"body":"there's already a `org.modeshape.common.xml.SimpleNamespaceContext` in `modeshape-common`. Perhaps we can use that here instead of having this inner class.","created_at":"2016-05-19T09:22:40Z","updated_at":"2016-05-19T09:22:41Z","html_url":"https://github.com/ModeShape/modeshape/pull/1560#discussion_r63846945","pull_request_url":"https://api.github.com/repos/ModeShape/modeshape/pulls/1560","_links":{"self":{"href":"https://api.github.com/repos/ModeShape/modeshape/pulls/comments/63846945"},"html":{"href":"https://github.com/ModeShape/modeshape/pull/1560#discussion_r63846945"},"pull_request":{"href":"https://api.github.com/repos/ModeShape/modeshape/pulls/1560"}}},"pull_request":{"url":"https://api.github.com/repos/ModeShape/modeshape/pulls/1560","id":70659450,"html_url":"https://github.com/ModeShape/modeshape/pull/1560","diff_url":"https://github.com/ModeShape/modeshape/pull/1560.diff","patch_url":"https://github.com/ModeShape/modeshape/pull/1560.patch","issue_url":"https://api.github.com/repos/ModeShape/modeshape/issues/1560","number":1560,"state":"open","locked":false,"title":"MODE-2551 Adds EPUB 3.0 sequencer","user":{"login":"RobSis","id":1384639,"avatar_url":"https://avatars.githubusercontent.com/u/1384639?v=3","gravatar_id":"","url":"https://api.github.com/users/RobSis","html_url":"https://github.com/RobSis","followers_url":"https://api.github.com/users/RobSis/followers","following_url":"https://api.github.com/users/RobSis/following{/other_user}","gists_url":"https://api.github.com/users/RobSis/gists{/gist_id}","starred_url":"https://api.github.com/users/RobSis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RobSis/subscriptions","organizations_url":"https://api.github.com/users/RobSis/orgs","repos_url":"https://api.github.com/users/RobSis/repos","events_url":"https://api.github.com/users/RobSis/events{/privacy}","received_events_url":"https://api.github.com/users/RobSis/received_events","type":"User","site_admin":false},"body":"New pull request against the master branch. \r\n\r\nFirst review was done here:\r\nhttps://github.com/ModeShape/modeshape/pull/1501","created_at":"2016-05-19T09:11:19Z","updated_at":"2016-05-19T09:22:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8d513cbfc2fcaea459125466cb3fd447993b4d79","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ModeShape/modeshape/pulls/1560/commits","review_comments_url":"https://api.github.com/repos/ModeShape/modeshape/pulls/1560/comments","review_comment_url":"https://api.github.com/repos/ModeShape/modeshape/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ModeShape/modeshape/issues/1560/comments","statuses_url":"https://api.github.com/repos/ModeShape/modeshape/statuses/3cc21f071ddb57bc7f06281c60e61e485126859d","head":{"label":"RobSis:mode-2551-5.0","ref":"mode-2551-5.0","sha":"3cc21f071ddb57bc7f06281c60e61e485126859d","user":{"login":"RobSis","id":1384639,"avatar_url":"https://avatars.githubusercontent.com/u/1384639?v=3","gravatar_id":"","url":"https://api.github.com/users/RobSis","html_url":"https://github.com/RobSis","followers_url":"https://api.github.com/users/RobSis/followers","following_url":"https://api.github.com/users/RobSis/following{/other_user}","gists_url":"https://api.github.com/users/RobSis/gists{/gist_id}","starred_url":"https://api.github.com/users/RobSis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RobSis/subscriptions","organizations_url":"https://api.github.com/users/RobSis/orgs","repos_url":"https://api.github.com/users/RobSis/repos","events_url":"https://api.github.com/users/RobSis/events{/privacy}","received_events_url":"https://api.github.com/users/RobSis/received_events","type":"User","site_admin":false},"repo":{"id":36926575,"name":"modeshape","full_name":"RobSis/modeshape","owner":{"login":"RobSis","id":1384639,"avatar_url":"https://avatars.githubusercontent.com/u/1384639?v=3","gravatar_id":"","url":"https://api.github.com/users/RobSis","html_url":"https://github.com/RobSis","followers_url":"https://api.github.com/users/RobSis/followers","following_url":"https://api.github.com/users/RobSis/following{/other_user}","gists_url":"https://api.github.com/users/RobSis/gists{/gist_id}","starred_url":"https://api.github.com/users/RobSis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RobSis/subscriptions","organizations_url":"https://api.github.com/users/RobSis/orgs","repos_url":"https://api.github.com/users/RobSis/repos","events_url":"https://api.github.com/users/RobSis/events{/privacy}","received_events_url":"https://api.github.com/users/RobSis/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/RobSis/modeshape","description":"ModeShape is a distributed, hierarchical, transactional, and consistent data store with support for queries, full-text search, events, versioning, references, and flexible and dynamic schemas. It is very fast, highly available, extremely scalable, and it is 100% open source and written in Java. Clients use the JSR-283 standard Java API for content repositories (aka, JCR) or ModeShape's REST API, and can query content through JDBC and SQL.","fork":true,"url":"https://api.github.com/repos/RobSis/modeshape","forks_url":"https://api.github.com/repos/RobSis/modeshape/forks","keys_url":"https://api.github.com/repos/RobSis/modeshape/keys{/key_id}","collaborators_url":"https://api.github.com/repos/RobSis/modeshape/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/RobSis/modeshape/teams","hooks_url":"https://api.github.com/repos/RobSis/modeshape/hooks","issue_events_url":"https://api.github.com/repos/RobSis/modeshape/issues/events{/number}","events_url":"https://api.github.com/repos/RobSis/modeshape/events","assignees_url":"https://api.github.com/repos/RobSis/modeshape/assignees{/user}","branches_url":"https://api.github.com/repos/RobSis/modeshape/branches{/branch}","tags_url":"https://api.github.com/repos/RobSis/modeshape/tags","blobs_url":"https://api.github.com/repos/RobSis/modeshape/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/RobSis/modeshape/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/RobSis/modeshape/git/refs{/sha}","trees_url":"https://api.github.com/repos/RobSis/modeshape/git/trees{/sha}","statuses_url":"https://api.github.com/repos/RobSis/modeshape/statuses/{sha}","languages_url":"https://api.github.com/repos/RobSis/modeshape/languages","stargazers_url":"https://api.github.com/repos/RobSis/modeshape/stargazers","contributors_url":"https://api.github.com/repos/RobSis/modeshape/contributors","subscribers_url":"https://api.github.com/repos/RobSis/modeshape/subscribers","subscription_url":"https://api.github.com/repos/RobSis/modeshape/subscription","commits_url":"https://api.github.com/repos/RobSis/modeshape/commits{/sha}","git_commits_url":"https://api.github.com/repos/RobSis/modeshape/git/commits{/sha}","comments_url":"https://api.github.com/repos/RobSis/modeshape/comments{/number}","issue_comment_url":"https://api.github.com/repos/RobSis/modeshape/issues/comments{/number}","contents_url":"https://api.github.com/repos/RobSis/modeshape/contents/{+path}","compare_url":"https://api.github.com/repos/RobSis/modeshape/compare/{base}...{head}","merges_url":"https://api.github.com/repos/RobSis/modeshape/merges","archive_url":"https://api.github.com/repos/RobSis/modeshape/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/RobSis/modeshape/downloads","issues_url":"https://api.github.com/repos/RobSis/modeshape/issues{/number}","pulls_url":"https://api.github.com/repos/RobSis/modeshape/pulls{/number}","milestones_url":"https://api.github.com/repos/RobSis/modeshape/milestones{/number}","notifications_url":"https://api.github.com/repos/RobSis/modeshape/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/RobSis/modeshape/labels{/name}","releases_url":"https://api.github.com/repos/RobSis/modeshape/releases{/id}","deployments_url":"https://api.github.com/repos/RobSis/modeshape/deployments","created_at":"2015-06-05T10:20:45Z","updated_at":"2016-05-13T17:10:07Z","pushed_at":"2016-05-19T09:12:29Z","git_url":"git://github.com/RobSis/modeshape.git","ssh_url":"git@github.com:RobSis/modeshape.git","clone_url":"https://github.com/RobSis/modeshape.git","svn_url":"https://github.com/RobSis/modeshape","homepage":"http://www.modeshape.org","size":132130,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ModeShape:master","ref":"master","sha":"73086b7289270827c2e5d95ddec8fc4107a8a3f1","user":{"login":"ModeShape","id":148023,"avatar_url":"https://avatars.githubusercontent.com/u/148023?v=3","gravatar_id":"","url":"https://api.github.com/users/ModeShape","html_url":"https://github.com/ModeShape","followers_url":"https://api.github.com/users/ModeShape/followers","following_url":"https://api.github.com/users/ModeShape/following{/other_user}","gists_url":"https://api.github.com/users/ModeShape/gists{/gist_id}","starred_url":"https://api.github.com/users/ModeShape/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ModeShape/subscriptions","organizations_url":"https://api.github.com/users/ModeShape/orgs","repos_url":"https://api.github.com/users/ModeShape/repos","events_url":"https://api.github.com/users/ModeShape/events{/privacy}","received_events_url":"https://api.github.com/users/ModeShape/received_events","type":"Organization","site_admin":false},"repo":{"id":1244027,"name":"modeshape","full_name":"ModeShape/modeshape","owner":{"login":"ModeShape","id":148023,"avatar_url":"https://avatars.githubusercontent.com/u/148023?v=3","gravatar_id":"","url":"https://api.github.com/users/ModeShape","html_url":"https://github.com/ModeShape","followers_url":"https://api.github.com/users/ModeShape/followers","following_url":"https://api.github.com/users/ModeShape/following{/other_user}","gists_url":"https://api.github.com/users/ModeShape/gists{/gist_id}","starred_url":"https://api.github.com/users/ModeShape/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ModeShape/subscriptions","organizations_url":"https://api.github.com/users/ModeShape/orgs","repos_url":"https://api.github.com/users/ModeShape/repos","events_url":"https://api.github.com/users/ModeShape/events{/privacy}","received_events_url":"https://api.github.com/users/ModeShape/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ModeShape/modeshape","description":"ModeShape is a distributed, hierarchical, transactional, and consistent data store with support for queries, full-text search, events, versioning, references, and flexible and dynamic schemas. It is very fast, highly available, extremely scalable, and it is 100% open source and written in Java. Clients use the JSR-283 standard Java API for content repositories (aka, JCR) or ModeShape's REST API, and can query content through JDBC and SQL.","fork":false,"url":"https://api.github.com/repos/ModeShape/modeshape","forks_url":"https://api.github.com/repos/ModeShape/modeshape/forks","keys_url":"https://api.github.com/repos/ModeShape/modeshape/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ModeShape/modeshape/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ModeShape/modeshape/teams","hooks_url":"https://api.github.com/repos/ModeShape/modeshape/hooks","issue_events_url":"https://api.github.com/repos/ModeShape/modeshape/issues/events{/number}","events_url":"https://api.github.com/repos/ModeShape/modeshape/events","assignees_url":"https://api.github.com/repos/ModeShape/modeshape/assignees{/user}","branches_url":"https://api.github.com/repos/ModeShape/modeshape/branches{/branch}","tags_url":"https://api.github.com/repos/ModeShape/modeshape/tags","blobs_url":"https://api.github.com/repos/ModeShape/modeshape/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ModeShape/modeshape/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ModeShape/modeshape/git/refs{/sha}","trees_url":"https://api.github.com/repos/ModeShape/modeshape/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ModeShape/modeshape/statuses/{sha}","languages_url":"https://api.github.com/repos/ModeShape/modeshape/languages","stargazers_url":"https://api.github.com/repos/ModeShape/modeshape/stargazers","contributors_url":"https://api.github.com/repos/ModeShape/modeshape/contributors","subscribers_url":"https://api.github.com/repos/ModeShape/modeshape/subscribers","subscription_url":"https://api.github.com/repos/ModeShape/modeshape/subscription","commits_url":"https://api.github.com/repos/ModeShape/modeshape/commits{/sha}","git_commits_url":"https://api.github.com/repos/ModeShape/modeshape/git/commits{/sha}","comments_url":"https://api.github.com/repos/ModeShape/modeshape/comments{/number}","issue_comment_url":"https://api.github.com/repos/ModeShape/modeshape/issues/comments{/number}","contents_url":"https://api.github.com/repos/ModeShape/modeshape/contents/{+path}","compare_url":"https://api.github.com/repos/ModeShape/modeshape/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ModeShape/modeshape/merges","archive_url":"https://api.github.com/repos/ModeShape/modeshape/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ModeShape/modeshape/downloads","issues_url":"https://api.github.com/repos/ModeShape/modeshape/issues{/number}","pulls_url":"https://api.github.com/repos/ModeShape/modeshape/pulls{/number}","milestones_url":"https://api.github.com/repos/ModeShape/modeshape/milestones{/number}","notifications_url":"https://api.github.com/repos/ModeShape/modeshape/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ModeShape/modeshape/labels{/name}","releases_url":"https://api.github.com/repos/ModeShape/modeshape/releases{/id}","deployments_url":"https://api.github.com/repos/ModeShape/modeshape/deployments","created_at":"2011-01-12T02:30:46Z","updated_at":"2016-05-07T06:06:33Z","pushed_at":"2016-05-19T09:12:30Z","git_url":"git://github.com/ModeShape/modeshape.git","ssh_url":"git@github.com:ModeShape/modeshape.git","clone_url":"https://github.com/ModeShape/modeshape.git","svn_url":"https://github.com/ModeShape/modeshape","homepage":"http://www.modeshape.org","size":137325,"stargazers_count":155,"watchers_count":155,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":161,"mirror_url":null,"open_issues_count":2,"forks":161,"open_issues":2,"watchers":155,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ModeShape/modeshape/pulls/1560"},"html":{"href":"https://github.com/ModeShape/modeshape/pull/1560"},"issue":{"href":"https://api.github.com/repos/ModeShape/modeshape/issues/1560"},"comments":{"href":"https://api.github.com/repos/ModeShape/modeshape/issues/1560/comments"},"review_comments":{"href":"https://api.github.com/repos/ModeShape/modeshape/pulls/1560/comments"},"review_comment":{"href":"https://api.github.com/repos/ModeShape/modeshape/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ModeShape/modeshape/pulls/1560/commits"},"statuses":{"href":"https://api.github.com/repos/ModeShape/modeshape/statuses/3cc21f071ddb57bc7f06281c60e61e485126859d"}}}}