metamodel-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kaspersorensen <...@git.apache.org>
Subject [GitHub] metamodel pull request: Neo4j module (query-only)
Date Sun, 01 Nov 2015 15:27:43 GMT
Github user kaspersorensen commented on a diff in the pull request:

    https://github.com/apache/metamodel/pull/69#discussion_r43583679
  
    --- Diff: neo4j/src/main/java/org/apache/metamodel/neo4j/Neo4jDataContext.java ---
    @@ -0,0 +1,336 @@
    +/**
    + * Licensed to the Apache Software Foundation (ASF) under one
    + * or more contributor license agreements.  See the NOTICE file
    + * distributed with this work for additional information
    + * regarding copyright ownership.  The ASF licenses this file
    + * to you under the Apache License, Version 2.0 (the
    + * "License"); you may not use this file except in compliance
    + * with the License.  You may obtain a copy of the License at
    + *
    + *   http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing,
    + * software distributed under the License is distributed on an
    + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    + * KIND, either express or implied.  See the License for the
    + * specific language governing permissions and limitations
    + * under the License.
    + */
    +package org.apache.metamodel.neo4j;
    +
    +import java.util.ArrayList;
    +import java.util.List;
    +
    +import org.apache.http.HttpHost;
    +import org.apache.http.client.methods.HttpGet;
    +import org.apache.http.impl.client.CloseableHttpClient;
    +import org.apache.http.impl.client.HttpClientBuilder;
    +import org.apache.metamodel.MetaModelException;
    +import org.apache.metamodel.MetaModelHelper;
    +import org.apache.metamodel.QueryPostprocessDataContext;
    +import org.apache.metamodel.UpdateScript;
    +import org.apache.metamodel.UpdateableDataContext;
    +import org.apache.metamodel.data.DataSet;
    +import org.apache.metamodel.data.DocumentSource;
    +import org.apache.metamodel.query.FilterItem;
    +import org.apache.metamodel.query.SelectItem;
    +import org.apache.metamodel.schema.Column;
    +import org.apache.metamodel.schema.MutableSchema;
    +import org.apache.metamodel.schema.MutableTable;
    +import org.apache.metamodel.schema.Schema;
    +import org.apache.metamodel.schema.Table;
    +import org.apache.metamodel.schema.builder.DocumentSourceProvider;
    +import org.apache.metamodel.util.SimpleTableDef;
    +import org.json.JSONArray;
    +import org.json.JSONException;
    +import org.json.JSONObject;
    +import org.slf4j.Logger;
    +import org.slf4j.LoggerFactory;
    +
    +/**
    + * DataContext implementation for Neo4j
    + */
    +public class Neo4jDataContext extends QueryPostprocessDataContext implements UpdateableDataContext,
    +        DocumentSourceProvider {
    +
    +    public static final Logger logger = LoggerFactory.getLogger(Neo4jDataContext.class);
    +
    +    public static final String SCHEMA_NAME = "neo4j";
    +
    +    public static final int DEFAULT_PORT = 7474;
    +
    +    public static final String RELATIONSHIP_PREFIX = "rel_";
    +
    +    public static final String RELATIONSHIP_COLUMN_SEPARATOR = "#";
    +
    +    private final SimpleTableDef[] _tableDefs;
    +
    +    private final Neo4jRequestWrapper _requestWrapper;
    +
    +    private final HttpHost _httpHost;
    +
    +    public Neo4jDataContext(String hostname, int port, String username, String password,
SimpleTableDef... tableDefs) {
    +        _httpHost = new HttpHost(hostname, port);
    +        final CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    +        _requestWrapper = new Neo4jRequestWrapper(httpClient, _httpHost, username, password);
    +        _tableDefs = tableDefs;
    +    }
    +
    +    public Neo4jDataContext(String hostname, int port, String username, String password)
{
    +        _httpHost = new HttpHost(hostname, port);
    +        final CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    +        _requestWrapper = new Neo4jRequestWrapper(httpClient, _httpHost, username, password);
    +        _tableDefs = detectTableDefs();
    +    }
    +
    +    public Neo4jDataContext(String hostname, int port, CloseableHttpClient httpClient)
{
    +        _httpHost = new HttpHost(hostname, port);
    +        _requestWrapper = new Neo4jRequestWrapper(httpClient, _httpHost);
    +        _tableDefs = detectTableDefs();
    +    }
    +
    +    public Neo4jDataContext(String hostname, int port, CloseableHttpClient httpClient,
SimpleTableDef... tableDefs) {
    +        _httpHost = new HttpHost(hostname, port);
    +        _requestWrapper = new Neo4jRequestWrapper(httpClient, _httpHost);
    +        _tableDefs = tableDefs;
    +    }
    +
    +    @Override
    +    protected String getDefaultSchemaName() throws MetaModelException {
    +        return SCHEMA_NAME;
    +    }
    +
    +    @Override
    +    protected Schema getMainSchema() throws MetaModelException {
    +        MutableSchema schema = new MutableSchema(getMainSchemaName());
    +        for (SimpleTableDef tableDef : _tableDefs) {
    +            MutableTable table = tableDef.toTable().setSchema(schema);
    +            schema.addTable(table);
    +        }
    +        return schema;
    +    }
    +
    +    @Override
    +    protected String getMainSchemaName() throws MetaModelException {
    +        return SCHEMA_NAME;
    +    }
    +
    +    public SimpleTableDef[] detectTableDefs() {
    +        List<SimpleTableDef> tableDefs = new ArrayList<SimpleTableDef>();
    +
    +        String labelsJsonString = _requestWrapper.executeRestRequest(new HttpGet("/db/data/labels"));
    +
    +        JSONArray labelsJsonArray;
    +        try {
    +            labelsJsonArray = new JSONArray(labelsJsonString);
    +            for (int i = 0; i < labelsJsonArray.length(); i++) {
    +                String label = labelsJsonArray.getString(i);
    +
    +                List<JSONObject> nodesPerLabel = getAllNodesPerLabel(label);
    +
    +                List<String> propertiesPerLabel = new ArrayList<String>();
    +                for (JSONObject node : nodesPerLabel) {
    +                    List<String> propertiesPerNode = getAllPropertiesPerNode(node);
    +                    for (String property : propertiesPerNode) {
    +                        if (!propertiesPerLabel.contains(property)) {
    +                            propertiesPerLabel.add(property);
    +                        }
    +                    }
    +                }
    +
    +                List<String> relationshipPropertiesPerLabel = new ArrayList<String>();
    +                for (JSONObject node : nodesPerLabel) {
    +                    Integer nodeId = (Integer) node.getJSONObject("metadata").get("id");
    +                    List<JSONObject> relationshipsPerNode = getOutgoingRelationshipsPerNode(nodeId);
    +                    for (JSONObject relationship : relationshipsPerNode) {
    +                        // Add the relationship as a column in the table
    +                        String relationshipName = relationship.getString("type");
    +                        String relationshipNameProperty = RELATIONSHIP_PREFIX + relationshipName;
    +                        if (!relationshipPropertiesPerLabel.contains(relationshipNameProperty))
{
    +                            relationshipPropertiesPerLabel.add(relationshipNameProperty);
    +                        }
    +
    +                        // Add all the relationship properties as table columns
    +                        List<String> propertiesPerRelationship = getAllPropertiesPerRelationship(relationship);
    +                        relationshipPropertiesPerLabel.addAll(propertiesPerRelationship);
    +                    }
    +                }
    +                propertiesPerLabel.addAll(relationshipPropertiesPerLabel);
    +
    +                // Do not add a table if label has no nodes (empty tables are
    +                // considered non-existent)
    +                if (!nodesPerLabel.isEmpty()) {
    +                    SimpleTableDef tableDef = new SimpleTableDef(label,
    +                            propertiesPerLabel.toArray(new String[propertiesPerLabel.size()]));
    +                    tableDefs.add(tableDef);
    +                }
    +            }
    +            return tableDefs.toArray(new SimpleTableDef[tableDefs.size()]);
    +        } catch (JSONException e) {
    +            logger.error("Error occured in parsing JSON while detecting the schema: ",
e);
    +            throw new IllegalStateException(e);
    +        }
    +    }
    +
    +    private List<String> getAllPropertiesPerRelationship(JSONObject relationship)
{
    +        List<String> propertyNames = new ArrayList<String>();
    +        try {
    +            String relationshipName = RELATIONSHIP_PREFIX + relationship.getJSONObject("metadata").getString("type");
    +            JSONObject relationshipPropertiesJSONObject = relationship.getJSONObject("data");
    +            if (relationshipPropertiesJSONObject.length() > 0) {
    +                JSONArray relationshipPropertiesNamesJSONArray = relationshipPropertiesJSONObject.names();
    +                for (int i = 0; i < relationshipPropertiesNamesJSONArray.length();
i++) {
    +                    String propertyName = relationshipName + RELATIONSHIP_COLUMN_SEPARATOR
    +                            + relationshipPropertiesNamesJSONArray.getString(i);
    +                    if (!propertyNames.contains(propertyName)) {
    +                        propertyNames.add(propertyName);
    +                    }
    +                }
    +            }
    +            return propertyNames;
    +        } catch (JSONException e) {
    +            logger.error("Error occured in parsing JSON while getting relationship properties:
", e);
    +            throw new IllegalStateException(e);
    +        }
    +    }
    +
    +    private List<JSONObject> getOutgoingRelationshipsPerNode(Integer nodeId) {
    +        List<JSONObject> outgoingRelationshipsPerNode = new ArrayList<JSONObject>();
    +
    +        String outgoingRelationshipsPerNodeJsonString = _requestWrapper.executeRestRequest(new
HttpGet("/db/data/node/"
    +                + nodeId + "/relationships/out"));
    +
    +        JSONArray outgoingRelationshipsPerNodeJsonArray;
    +        try {
    +            outgoingRelationshipsPerNodeJsonArray = new JSONArray(outgoingRelationshipsPerNodeJsonString);
    +            for (int i = 0; i < outgoingRelationshipsPerNodeJsonArray.length(); i++)
{
    +                JSONObject relationship = outgoingRelationshipsPerNodeJsonArray.getJSONObject(i);
    +                if (!outgoingRelationshipsPerNode.contains(relationship)) {
    +                    outgoingRelationshipsPerNode.add(relationship);
    +                }
    +            }
    +            return outgoingRelationshipsPerNode;
    +        } catch (JSONException e) {
    +            logger.error("Error occured in parsing JSON while detecting outgoing relationships
for node: " + nodeId, e);
    +            throw new IllegalStateException(e);
    +        }
    +    }
    +
    +    private List<JSONObject> getAllNodesPerLabel(String label) {
    +        List<JSONObject> allNodesPerLabel = new ArrayList<JSONObject>();
    +
    +        String allNodesForLabelJsonString = _requestWrapper.executeRestRequest(new HttpGet("/db/data/label/"
+ label
    +                + "/nodes"));
    +
    +        JSONArray allNodesForLabelJsonArray;
    +        try {
    +            allNodesForLabelJsonArray = new JSONArray(allNodesForLabelJsonString);
    +            for (int i = 0; i < allNodesForLabelJsonArray.length(); i++) {
    +                JSONObject node = allNodesForLabelJsonArray.getJSONObject(i);
    +                allNodesPerLabel.add(node);
    +            }
    +            return allNodesPerLabel;
    +        } catch (JSONException e) {
    +            logger.error("Error occured in parsing JSON while detecting the nodes for
a label: " + label, e);
    +            throw new IllegalStateException(e);
    +        }
    +    }
    +
    +    private List<String> getAllPropertiesPerNode(JSONObject node) {
    +        List<String> properties = new ArrayList<String>();
    +        properties.add("_id");
    +
    +        String propertiesEndpoint;
    +        try {
    +            propertiesEndpoint = node.getString("properties");
    +
    +            String allPropertiesPerNodeJsonString = _requestWrapper.executeRestRequest(new
HttpGet(propertiesEndpoint));
    +
    +            JSONObject allPropertiesPerNodeJsonObject = new JSONObject(allPropertiesPerNodeJsonString);
    +            for (int j = 0; j < allPropertiesPerNodeJsonObject.length(); j++) {
    +                JSONArray propertiesJsonArray = allPropertiesPerNodeJsonObject.names();
    +                for (int k = 0; k < propertiesJsonArray.length(); k++) {
    +                    String property = propertiesJsonArray.getString(k);
    +                    properties.add(property);
    +                }
    +            }
    +            return properties;
    +        } catch (JSONException e) {
    +            logger.error("Error occured in parsing JSON while detecting the properties
of a node: " + node, e);
    +            throw new IllegalStateException(e);
    +        }
    +    }
    +
    +    @Override
    +    protected DataSet materializeMainSchemaTable(Table table, Column[] columns, int firstRow,
int maxRows) {
    +        if ((columns != null) && (columns.length > 0)) {
    +            Neo4jDataSet dataSet = null;
    +            try {
    +                String selectQuery = Neo4jCypherQueryBuilder.buildSelectQuery(table,
columns, firstRow, maxRows);
    +                String responseJSONString = _requestWrapper.executeCypherQuery(selectQuery);
    +                JSONObject resultJSONObject = new JSONObject(responseJSONString);
    +                final SelectItem[] selectItems = MetaModelHelper.createSelectItems(columns);
    +                dataSet = new Neo4jDataSet(selectItems, resultJSONObject);
    +            } catch (JSONException e) {
    +                logger.error("Error occured in parsing JSON while materializing the schema:
", e);
    +                throw new IllegalStateException(e);
    +            }
    +
    +            return dataSet;
    +        } else {
    +            logger.error("Encountered null or empty columns array for materializing main
schema table.");
    +            throw new IllegalArgumentException("Columns cannot be null or empty array");
    +        }
    +    }
    +
    +    @Override
    +    protected DataSet materializeMainSchemaTable(Table table, Column[] columns, int maxRows)
{
    +        return materializeMainSchemaTable(table, columns, 1, maxRows);
    +    }
    +
    +    @Override
    +    protected org.apache.metamodel.data.Row executePrimaryKeyLookupQuery(Table table,
List<SelectItem> selectItems,
    +            Column primaryKeyColumn, Object keyValue) {
    +        return null;
    --- End diff --
    
    If we don't have an implementation here then I suggest not overriding it since it does
nothing.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

Mime
View raw message