private static void addAttributeNodes(String fieldName, EntityGraph<?> graph) { int pos = fieldName.indexOf(GRAPH_DELIMETER); if (pos < 0) { graph.addAttributeNodes(fieldName); return; } String subgraphName = fieldName.substring(0, pos); Subgraph<?> subGraph = graph.addSubgraph(subgraphName); String nextFieldName = fieldName.substring(pos + 1); pos = nextFieldName.indexOf(GRAPH_DELIMETER); while (pos > 0) { subgraphName = nextFieldName.substring(0, pos); subGraph = graph.addSubgraph(subgraphName); nextFieldName = nextFieldName.substring(pos + 1); pos = nextFieldName.indexOf(GRAPH_DELIMETER); } subGraph.addAttributeNodes(nextFieldName); }
/** * I'm using NULL-OBJECT pattern here, for attributes that not existing in the EntityGraph, * a predefined NULL-ATTRIBUTE-NODE is pushed to the stack. * * and for an not existing sub graph, a predefined NULL-SUBGRAPH is pushed to the stack. * * So, whenever we're start visiting an attribute, there will be a attribute node pushed to the attribute stack, * and a subgraph node pushed to the graph stack. * * when we're finish visiting an attribute, these two will be poped from each stack. */ @Override public boolean startingAttribute(AttributeDefinition attributeDefinition) { Map<String, AttributeNodeImplementor> attributeMap = attributeMapStack.peekLast(); final String attrName = attributeDefinition.getName(); AttributeNodeImplementor attributeNode = NON_EXIST_ATTRIBUTE_NODE; GraphNodeImplementor subGraphNode = NON_EXIST_SUBGRAPH_NODE; //the attribute is in the EntityGraph, so, let's continue if ( attributeMap.containsKey( attrName ) ) { attributeNode = attributeMap.get( attrName ); //here we need to check if there is a subgraph (or sub key graph if it is an indexed attribute ) Map<Class, Subgraph> subGraphs = attributeNode.getSubgraphs(); Class javaType = attributeDefinition.getType().getReturnedClass(); if ( !subGraphs.isEmpty() && subGraphs.containsKey( javaType ) ) { subGraphNode = (GraphNodeImplementor) subGraphs.get( javaType ); } } attributeStack.addLast( attributeNode ); graphStack.addLast( subGraphNode ); return super.startingAttribute( attributeDefinition ); }
private <T> Subgraph<Object> applyFetchPaths(EntityGraph<T> graph, MetaAttributePath fetchPath) { if (fetchPath.length() >= 2) { // ensure parent is fetched MetaAttributePath parentPath = fetchPath.subPath(0, fetchPath.length() - 1); Subgraph<Object> parentGraph = applyFetchPaths(graph, parentPath); return parentGraph.addSubgraph(fetchPath.toString()); } else { return graph.addSubgraph(fetchPath.toString()); } }
@Override public void startingCollectionElements( final CollectionElementDefinition elementDefinition) { AttributeNodeImplementor attributeNode = attributeStack.peekLast(); GraphNodeImplementor subGraphNode = NON_EXIST_SUBGRAPH_NODE; Map<Class, Subgraph> subGraphs = attributeNode.getSubgraphs(); Class javaType = elementDefinition.getType().getReturnedClass(); if ( !subGraphs.isEmpty() && subGraphs.containsKey( javaType ) ) { subGraphNode = (GraphNodeImplementor) subGraphs.get( javaType ); } graphStack.addLast( subGraphNode ); super.startingCollectionElements( elementDefinition ); }
@Override public void startingCollectionIndex(final CollectionIndexDefinition indexDefinition) { AttributeNodeImplementor attributeNode = attributeStack.peekLast(); GraphNodeImplementor subGraphNode = NON_EXIST_SUBGRAPH_NODE; Map<Class, Subgraph> subGraphs = attributeNode.getKeySubgraphs(); Class javaType = indexDefinition.getType().getReturnedClass(); if ( !subGraphs.isEmpty() && subGraphs.containsKey( javaType ) ) { subGraphNode = (GraphNodeImplementor) subGraphs.get( javaType ); } graphStack.addLast( subGraphNode ); super.startingCollectionIndex( indexDefinition ); }
private Subgraph<Object> applyFetchPaths(EntityGraph<T> graph, MetaAttributePath fetchPath) { if (fetchPath.length() >= 2) { // ensure parent is fetched MetaAttributePath parentPath = fetchPath.subPath(0, fetchPath.length() - 1); Subgraph<Object> parentGraph = applyFetchPaths(graph, parentPath); return parentGraph.addSubgraph(fetchPath.toString()); } else { return graph.addSubgraph(fetchPath.toString()); } }
/** * Builds an subgraph and connects it with the upper graph. * * @param subgraph * current subgraph without any elements (graph is already * connected to upper-graph) * @param graphName * name of the entity-graph * @param upperElem * Element which references to the subgraph * @param subgraphList * List with all defined subgraph-nodes * @param doc * Document which is needed for the compilation of the xpath * @return a new build subgraph */ private Subgraph<?> buildSubgraph(final Subgraph<?> subgraph, final String graphName, final Element upperElem, final NodeList subgraphList, final Document doc) { // searches for the right subgraph for (int j = 0; j < subgraphList.getLength(); ++j) { final Element subgraphElem = (Element) subgraphList.item(j); if (subgraphElem.getAttribute("name").equals(upperElem.getAttribute("subgraph"))) { final String attributesSubgraphListString = "//named-entity-graph[@name='" + graphName + "']/subgraph[@name='" + subgraphElem.getAttribute("name") + "']/named-attribute-node"; NodeList attributesSubgraphList = null; try { attributesSubgraphList = (NodeList) xPath.compile(attributesSubgraphListString).evaluate(doc, XPathConstants.NODESET); } catch (final XPathExpressionException e) { LOGGER.warn("Exception in BuildEntityGraph::buildSubgraph, full stack trace follows: ", e); } // reads all attributes of the subgraph for (int k = 0; k < attributesSubgraphList.getLength(); ++k) { final Element attributeSubgraphElem = (Element) attributesSubgraphList.item(k); // attributes of subgraph if ("".equals(attributeSubgraphElem.getAttribute("subgraph"))) { // adds the attributes to the subgraph subgraph.addAttributeNodes(attributeSubgraphElem.getAttribute("name")); } // references to other subgraphs else { Subgraph<?> deeperSubgraph = null; deeperSubgraph = subgraph.addSubgraph(attributeSubgraphElem.getAttribute("name")); buildSubgraph(deeperSubgraph, graphName, attributeSubgraphElem, subgraphList, doc); } } } } return subgraph; }
@Override public Map<Class, Subgraph> getSubgraphs() { return Collections.emptyMap(); }
@Override public Map<Class, Subgraph> getKeySubgraphs() { return Collections.emptyMap(); }
/** * Builds an entity graph from a XML file. * * @param graphName * name of the entity graph * @param classType * entity graph with rootElement of classType * @return result generated entity graph with rootElement of classType - can * be null if an error occurs during entity graph initialization */ @Override public <T> EntityGraph<?> generateEntityGraphXPath(final EntityManager em, final String graphName, final Class<T> classType) { EntityGraph<?> graph = null; try { URL centralMappingFilePath = JEntityGraphDataMapper.class.getResource(FilePaths.CENTRAL_XML_NAME.path()); File centralRules; centralRules = new File(centralMappingFilePath.toURI()); final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); final DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); final Document doc = dBuilder.parse(centralRules); doc.getDocumentElement().normalize(); xPath = XPathFactory.newInstance().newXPath(); // list of attribute-nodes from the root class of the selected // entity graph final String attributeRootNodeListString = "//named-entity-graph[@name='" + graphName + "']/named-attribute-node"; final NodeList attributeRootNodeList = (NodeList) xPath.compile(attributeRootNodeListString).evaluate(doc, XPathConstants.NODESET); // list of all subgraphs final String subgraphListString = "//named-entity-graph[@name='" + graphName + "']/subgraph"; final NodeList subgraphList = (NodeList) xPath.compile(subgraphListString).evaluate(doc, XPathConstants.NODESET); // create EntityGraph graph = em.createEntityGraph(classType); // reads all named-attribute-nodes below the named-entity-graph for (int i = 0; i < attributeRootNodeList.getLength(); ++i) { final Element nodeElem = (Element) attributeRootNodeList.item(i); // adds the attributes to the graph if ("".equals(nodeElem.getAttribute("subgraph"))) { graph.addAttributeNodes(nodeElem.getAttribute("name")); } // reference to a subgraph else { // create subgraph with a reference to the upper class final Subgraph<?> subgraph = graph.addSubgraph(nodeElem.getAttribute("name")); buildSubgraph(subgraph, graphName, nodeElem, subgraphList, doc); } } } catch (XPathExpressionException | ParserConfigurationException | SAXException | IOException | URISyntaxException e) { LOGGER.warn("Exception in BuildEntityGraph::generateEntityGraphXPath, full stack trace follows: ", e); } return graph; }