/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde 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.eigenbase.rel;
import java.io.*;
import java.util.*;
import org.eigenbase.sql.*;
import org.eigenbase.util.Pair;
import org.eigenbase.util.XmlOutput;
/**
* Callback for a relational expression to dump in XML format.
*/
public class RelXmlWriter extends RelWriterImpl {
//~ Instance fields --------------------------------------------------------
private final XmlOutput xmlOutput;
boolean generic = true;
//~ Constructors -----------------------------------------------------------
// TODO jvs 23-Dec-2005: honor detail level. The current inheritance
// structure makes this difficult without duplication; need to factor
// out the filtering of attributes before rendering.
public RelXmlWriter(PrintWriter pw, SqlExplainLevel detailLevel) {
super(pw, detailLevel, true);
xmlOutput = new XmlOutput(pw);
xmlOutput.setGlob(true);
xmlOutput.setCompact(false);
}
//~ Methods ----------------------------------------------------------------
protected void explain_(
RelNode rel,
List<Pair<String, Object>> values) {
if (generic) {
explainGeneric(rel, values);
} else {
explainSpecific(rel, values);
}
}
/**
* Generates generic XML (sometimes called 'element-oriented XML'). Like
* this:
*
* <blockquote>
* <code>
* <RelNode id="1" type="Join"><br/>
* <Property name="condition">EMP.DEPTNO =
* DEPT.DEPTNO</Property><br/>
* <Inputs><br/>
* <RelNode id="2" type="Project"><br/>
* <Property name="expr1">x +
* y</Property><br/>
* <Property
* name="expr2">45</Property><br/>
* </RelNode><br/>
* <RelNode id="3" type="TableAccess"><br/>
* <Property
* name="table">SALES.EMP</Property><br/>
* </RelNode><br/>
* </Inputs><br/>
* </RelNode><br/>
* </code>
* </blockquote>
*
* @param rel Relational expression
* @param values List of term-value pairs
*/
private void explainGeneric(
RelNode rel,
List<Pair<String, Object>> values) {
String relType = rel.getRelTypeName();
xmlOutput.beginBeginTag("RelNode");
xmlOutput.attribute("type", relType);
//xmlOutput.attribute("id", rel.getId() + "");
xmlOutput.endBeginTag("RelNode");
final List<RelNode> inputs = new ArrayList<RelNode>();
for (Pair<String, Object> pair : values) {
if (pair.right instanceof RelNode) {
inputs.add((RelNode) pair.right);
continue;
}
if (pair.right == null) {
continue;
}
xmlOutput.beginBeginTag("Property");
xmlOutput.attribute("name", pair.left);
xmlOutput.endBeginTag("Property");
xmlOutput.cdata(pair.right.toString());
xmlOutput.endTag("Property");
}
xmlOutput.beginTag("Inputs", null);
spacer.add(2);
for (RelNode input : inputs) {
input.explain(this);
}
spacer.subtract(2);
xmlOutput.endTag("Inputs");
xmlOutput.endTag("RelNode");
}
/**
* Generates specific XML (sometimes called 'attribute-oriented XML'). Like
* this:
*
* <pre>
* <Join condition="EMP.DEPTNO = DEPT.DEPTNO">
* <Project expr1="x + y" expr2="42">
* <TableAccess table="SALES.EMPS">
* </Join>
* </pre>
*
* @param rel Relational expression
* @param values List of term-value pairs
*/
private void explainSpecific(
RelNode rel,
List<Pair<String, Object>> values) {
String tagName = rel.getRelTypeName();
xmlOutput.beginBeginTag(tagName);
xmlOutput.attribute("id", rel.getId() + "");
for (Pair<String, Object> value : values) {
if (value.right instanceof RelNode) {
continue;
}
xmlOutput.attribute(
value.left,
value.right.toString());
}
xmlOutput.endBeginTag(tagName);
spacer.add(2);
for (RelNode input : rel.getInputs()) {
input.explain(this);
}
spacer.subtract(2);
}
}
// End RelXmlWriter.java