📄 sqltranslation.java
字号:
//// This file is part of the OpenNMS(R) Application.//// OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc. All rights reserved.// OpenNMS(R) is a derivative work, containing both original code, included code and modified// code that was published under the GNU General Public License. Copyrights for modified // and included code are below.//// OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.//// Modifications://// 2003 Aug 01: Created a proper Join for rules. Bug #752// 2003 Jan 31: Cleaned up some unused imports.// 2002 Oct 30: Changed some filter code for notifications.// 2002 Oct 15: Corrected filters on services.// // Original code base Copyright (C) 1999-2001 Oculan Corp. All rights reserved.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details. //// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // For more information contact: // OpenNMS Licensing <license@opennms.org>// http://www.opennms.org/// http://www.opennms.com///package org.opennms.netmgt.filter;import java.io.IOException;import java.lang.reflect.UndeclaredThrowableException;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.StringTokenizer;import org.exolab.castor.xml.MarshalException;import org.exolab.castor.xml.ValidationException;import org.opennms.netmgt.config.DatabaseSchemaConfigFactory;import org.opennms.netmgt.config.filter.Table;import org.opennms.netmgt.filter.analysis.DepthFirstAdapter;import org.opennms.netmgt.filter.node.AAndRule;import org.opennms.netmgt.filter.node.ACompareExprPart;import org.opennms.netmgt.filter.node.AExprParensExpr;import org.opennms.netmgt.filter.node.AGtrThanEqualExprPart;import org.opennms.netmgt.filter.node.AGtrThanExprPart;import org.opennms.netmgt.filter.node.AIdentExprPart;import org.opennms.netmgt.filter.node.AIntegerCompareRight;import org.opennms.netmgt.filter.node.AIntegerOctet;import org.opennms.netmgt.filter.node.AIpaddrIpIdent;import org.opennms.netmgt.filter.node.AIplikeExprPart;import org.opennms.netmgt.filter.node.ALessThanEqualExprPart;import org.opennms.netmgt.filter.node.ALessThanExprPart;import org.opennms.netmgt.filter.node.ALikeExprPart;import org.opennms.netmgt.filter.node.ATildelikeExprPart;import org.opennms.netmgt.filter.node.ANotEqualExprPart;import org.opennms.netmgt.filter.node.ANotExprPart;import org.opennms.netmgt.filter.node.AOctetListOctet;import org.opennms.netmgt.filter.node.AOctetRangeListOctet;import org.opennms.netmgt.filter.node.AOctetRangeOctet;import org.opennms.netmgt.filter.node.AOrRule;import org.opennms.netmgt.filter.node.AStarOctet;import org.opennms.netmgt.filter.node.AStringCompareRight;import org.opennms.netmgt.filter.node.Start;/** * This class is responsible for mapping the different parts of the filter * expressions into the SQL equivalent. As pieces of the expression are parsed * the from and where clauses will be built. This information will be passed on * to a SQLConstruct object by the parser when the expression has been fully * parsed. * * @author <A HREF="mailto:jason@opennms.org">Jason Johns </A> * @author <A HREF="mailto:weave@oculan.com">Weave </A> * @author <A HREF="http://www.opennms.org/">OpenNMS </A> * */public class SQLTranslation extends DepthFirstAdapter { private DatabaseSchemaConfigFactory m_schemaFactory = DatabaseSchemaConfigFactory.getInstance(); /** * Constant to identify a virtual column for determining if an interface * supports a service */ public static final String VIRTUAL_COLUMN_PREFIX = "is"; /** * Constant to identify a virtual column for determining if an interface * supports a service */ public static final String VIRTUAL_NOT_COLUMN_PREFIX = "notis"; /** * The list of tables required to create the approriate SQL statement */ private List m_tables; /** * The list of columns to be returned by the SQL. */ private List m_selectList; /** * A modifier on the selectList (like 'DISTINCT') */ private String m_selectModifier; /** * The from part of the clause */ private StringBuffer m_from; /** * The where part of the clause */ private StringBuffer m_where; /** * The last ip address, this rebuild on a call to inAipaddr */ private StringBuffer m_ipaddr; /** * The starting node of the parse tree */ private Start m_node; // Statically load the configuration resource. // static { try { DatabaseSchemaConfigFactory.init(); } catch (MarshalException ex) { throw new UndeclaredThrowableException(ex); } catch (ValidationException ex) { throw new UndeclaredThrowableException(ex); } catch (IOException ex) { throw new UndeclaredThrowableException(ex); } } /** * This method is used to build the join condtions to be added to the where * clause of a complete select statement. A join condition will only be * built between two tables if the table being looked at has a <join> * reference indicating a join condition between itself and the driver * table. * * @return The completed join clause for the WHERE clause */ private String constructJoin() { StringBuffer joinBuf = new StringBuffer(); Iterator i = m_tables.iterator(); while (i.hasNext()) { Table t = (Table) i.next(); String expr = m_schemaFactory.constructJoinExprForTable(t); if (expr != null && !"".equals(expr)) { joinBuf.append(" AND "); joinBuf.append(expr); } } return joinBuf.toString(); } /** * Validate the identifier by ensuring it is references in the schema. Also * checks for 'virtual columns' be checking the prefix. If it is this turns * into a reference to the 'serviceName' column of the service table and the * appropriate join. */ private String validateIdent(String ident) { String expr = null; Table tableForIdent = m_schemaFactory.findTableByVisableColumn(ident); if (tableForIdent != null) expr = addColumnToStatement(tableForIdent, ident); if (expr == null && ident.startsWith(VIRTUAL_COLUMN_PREFIX)) { String serviceName = ident.substring(VIRTUAL_COLUMN_PREFIX.length()); // should check against some form of // service identifier table, but for now I'm // removing this check since it's just used // internally // tableForIdent = m_schemaFactory.findTableByVisableColumn("serviceName"); if (tableForIdent != null) expr = addColumnToStatement(tableForIdent, "serviceName"); if (expr != null) expr = expr + " = '" + serviceName + '\''; } if (expr == null && ident.startsWith(VIRTUAL_NOT_COLUMN_PREFIX)) { String serviceName = ident.substring(VIRTUAL_NOT_COLUMN_PREFIX.length()); // should check against some form of // service identifier table, but for now I'm // removing this check since it's just used // internally // tableForIdent = m_schemaFactory.findTableByVisableColumn("serviceName"); if (tableForIdent != null) expr = addColumnToStatement(tableForIdent, "serviceName"); if (expr != null) expr = "ifservices.ipaddr not in (select ipaddr from ifservices,service where service.serviceName ='"+ serviceName + "' and service.serviceID = ifServices.serviceid)"; } if (expr == null) { throw new FilterParseException("The token " + ident + " is an illegal column value."); } return expr; } /** * Adds a column to the statement. This means insuring that this column is * valid, its table is listed in the m_tables list as well as any * intermediate tables necessary to join this table to the primary table. It * returns the tablename.colname used to reference this column in the SQL. * * @param colName * the name of the column to add * @return the 'tablename.column' expression used to reference the column in * SQL. */ private String addColumnToStatement(String colName) { Table t = m_schemaFactory.findTableByVisableColumn(colName); if (t == null) throw new FilterParseException("Could not find the column '" + colName + "' in the database schema"); return addColumnToStatement(t, colName).toString(); } /** * Adds a column to the statement. The column is assumed to be in the passed * in table. This means insuring that this column is valid, its table is * listed in the m_tables list as well as any intermediate tables necessary * to join this table to the primary table. It returns the tablename.colname * used to reference this column in the SQL. * * @param t * A Table that must contain the column colName * @param colName * the name of the column to add * @return the 'tablename.column' expression used to reference the column in * SQL. * * @param t * @param colName * @return a string represtenting the part of the where portion of the * clause for this column */ private String addColumnToStatement(Table t, String colName) { String[] joinTableNames = m_schemaFactory.getJoinTablesForTable(t); for (int i = 0; i < joinTableNames.length; i++) { Table joinTable = m_schemaFactory.getTableByName(joinTableNames[i]); if (joinTable == null) throw new FilterParseException("Unable to locate visable table for " + joinTableNames[i] + " referrenced in join for table " + t.getName()); if (!m_tables.contains(joinTable)) { if (m_tables.size() == 0) m_from.append(joinTable.getName()); else m_from.append(", ").append(joinTable.getName()); m_tables.add(joinTable); } } return t.getName() + "." + colName; } /** * This method removes any double quote characters from the start and end of * a string and replaces them with single quotes. * * @param string * the string to replace quote characters in * */ private String convertString(String string) { // for a string we need to change any encapsulating double // quotes to single quotes // StringBuffer buffer = new StringBuffer(string); buffer.setCharAt(0, '\''); buffer.setCharAt(buffer.length() - 1, '\''); return buffer.toString(); } /** * This method checks to ensure that a number appearing in an IP address is * within the 0-255 range. * * @param octet * an integer from an ip octet * * @exception java.lang.IndexOutOfBoundsException */ public void checkIPNum(String octet) { try { int ipnum = Integer.parseInt(octet); if (ipnum < 0 || ipnum > 255) throw new IndexOutOfBoundsException("The specified IP octet is not valid, value = " + octet); } catch (NumberFormatException e) { throw new IndexOutOfBoundsException("The specified IP octet is not valid, value = " + octet); } } /** * Default constructor, initalizes the data structures */ public SQLTranslation(Start node) { m_node = node; m_selectList = new ArrayList(); m_from = new StringBuffer(" FROM "); m_where = new StringBuffer(" WHERE ("); m_tables = new ArrayList(m_schemaFactory.getTableCount()); setDefaultTranslation(); } private String buildSelectClause() { StringBuffer clause = new StringBuffer("SELECT "); clause.append(m_selectModifier).append(" "); for (int i = 0; i < m_selectList.size(); i++) { clause.append((String) m_selectList.get(i)).append(i < m_selectList.size() - 1 ? ", " : ""); } return clause.toString(); } /** * Initializes the pieces of the SQL statement to perform a default query to * select distinct ip addresses based the query that is built from the rest * of the rule. */ public void setDefaultTranslation() { m_selectModifier = "DISTINCT"; m_selectList.clear(); m_selectList.add(addColumnToStatement("ipAddr")); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -