package org.teiid.translator.document; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.teiid.language.Join.JoinType; class DocumentJoinNode extends DocumentNode { private DocumentNode left; private DocumentNode right; private JoinType type; public DocumentJoinNode(DocumentNode left, JoinType joinType, DocumentNode right) { this.left = left; this.right = right; this.type = joinType; } public List<Map<String, Object>> mergeTuples(List<Map<String, Object>> leftRows, Document parentDocument) { List<Map<String, Object>> joinedRows = new ArrayList<Map<String,Object>>(); List<? extends Document> rightDocuments = parentDocument .getChildDocuments(this.right.getName()); if (rightDocuments == null) { if (this.type.equals(JoinType.LEFT_OUTER_JOIN)) { for (Map<String, Object> leftRow:leftRows) { LinkedHashMap<String, Object> row = new LinkedHashMap<String, Object>(); row.putAll(leftRow); joinedRows.add(row); } if (this.joinNode != null) { // do further joins, only span up to sibiling or child. In this case // there can be only sibiling joinedRows = this.joinNode.mergeTuples(joinedRows, parentDocument); } } } else { for (Map<String, Object> leftRow:leftRows) { for (Document rightDocument : rightDocuments) { Map<String, Object> rightRow = rightDocument.getProperties(); LinkedHashMap<String, Object> row = new LinkedHashMap<String, Object>(); if (this.type.equals(JoinType.INNER_JOIN)) { if (rightRow != null && !rightRow.isEmpty()) { row.putAll(leftRow); row.putAll(rightRow); } } else if (this.type.equals(JoinType.LEFT_OUTER_JOIN)) { row.putAll(leftRow); if (rightRow != null && !rightRow.isEmpty()) { row.putAll(rightRow); } } joinedRows.add(row); } if (this.joinNode != null) { // do further joins, only span up to sibiling or child for (Document rightDocument : rightDocuments) { joinedRows = this.joinNode.mergeTuples(joinedRows, rightDocument); } } } } return joinedRows; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(this.left); sb.append(this.type); sb.append(this.right); return sb.toString(); } }