/* * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com) * * Licensed 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 jef.database.meta; import jef.database.Condition; import jef.database.DbUtils; import jef.database.Field; import jef.database.MetadataContainer; import jef.database.QueryAlias; import jef.database.query.Join; import jef.database.query.JoinElement; import jef.database.query.JpqlExpression; import jef.database.query.LazyQueryBindField; import jef.database.query.Query; import jef.database.query.RefField; /** * 描述一个连接键对 * * @author Administrator * */ public class JoinKey extends Condition { private static final long serialVersionUID = 1L; private boolean isValueField; // 右侧是Field private boolean isSimple; // 简单模式 private Query<?> leftLock; // 左侧固定查询对象 private Query<?> rightLock; // 右侧固定查询对象 // 左右翻转 public JoinKey flip() { if (isSimple) { JoinKey r = new JoinKey((Field) this.value, this.operator, this.field); r.rightLock = this.leftLock; r.leftLock = this.rightLock; return r; } else { return this; } } public Query<?> getLeftLock() { return leftLock; } public Query<?> getRightLock() { return rightLock; } /** * 给定Field和外连接信息,构造连接 * * @param left * @param right */ public JoinKey(Field left, Field right) { this(left, Operator.EQUALS, right); } public JoinKey(Field field, Operator operator, Object value) { this.field = field; this.value = value; this.operator = operator; init(); } private void init() { // 处理左侧锁定 if (field instanceof RefField) { if (((RefField) field).isBind()) { this.leftLock = ((RefField) field).getInstanceQuery(null); } field = ((RefField) field).getField(); } else if (field instanceof JpqlExpression) { JpqlExpression jpql = (JpqlExpression) field; if (jpql.isBind()) { this.leftLock = jpql.getInstanceQuery(null); } } isValueField = (value instanceof Field); if (isValueField) { // 处理右侧锁定 if (value instanceof RefField) { if (((RefField) value).isBind()) { this.rightLock = ((RefField) value).getInstanceQuery(null); } value = ((RefField) value).getField(); } else if (value instanceof JpqlExpression) { if (((JpqlExpression) value).isBind()) { this.rightLock = ((JpqlExpression) value).getInstanceQuery(null); } } if (!(field instanceof JpqlExpression)) { if ((value instanceof Enum || value instanceof TupleField) && Operator.EQUALS == operator) { isSimple = true; } } } } public boolean isValueField() { return isValueField; } public boolean isSimple() { return isSimple; } public Field getLeft() { return field; } /** * 得到Join关系右边的字段 * * @return */ public Field getRightAsField() { if (isValueField) { return (Field) value; } else { return null; } } public ITableMetadata getLeftTableMeta() { if (leftLock != null) { return leftLock.getMeta(); } return DbUtils.getTableMeta(this.field); } public ITableMetadata getRightTableMeta() { if (rightLock != null) { return rightLock.getMeta(); } ITableMetadata meta = null; if (this.value instanceof LazyQueryBindField) { meta = ((LazyQueryBindField) value).getMeta(); } else if (value instanceof Field) { meta = DbUtils.getTableMeta((Field) value); } return meta; } public void findAndLockLeft(Join left) { if (leftLock != null) return; ITableMetadata meta = DbUtils.getTableMeta(this.field); if (meta == null) return; for (QueryAlias qa : ((Join) left).allElements()) { if (qa.getQuery().getMeta() == meta) { this.leftLock = qa.getQuery(); return; } } } public int validate(JoinElement left, Query<?> obj) { if (validateLeft(left)) { return validateRight(obj) ? 1 : 0; } if (validateLeft(obj)) { return (validateRight(left) || validateRight(obj)) ? -1 : 0; } return 0; } public int validate(ITableMetadata left, ITableMetadata obj) { if (validateLeft(left)) { return validateRight(obj) ? 1 : 0; } if (validateLeft(obj)) { return (validateRight(left) || validateRight(obj)) ? -1 : 0; } return 0; } private boolean validateRight(ITableMetadata obj) { if (rightLock != null) { return obj == rightLock.getMeta(); } else { ITableMetadata meta = null; if (this.value instanceof MetadataContainer) { meta = ((MetadataContainer) value).getMeta(); } else if (value instanceof Field && value instanceof Enum) { meta = DbUtils.getTableMeta((Field) value); } return meta==null || meta==obj || meta.getThisType().isAssignableFrom(obj.getThisType()); } } private boolean validateLeft(ITableMetadata left) { if (leftLock != null) { return left == leftLock.getMeta(); } else if (field == null) {// 纯表达式 return true; } else { // 这里从Field获得meta,但有风险,有可能会得到实际用的left的一个父类Meta ITableMetadata meta = DbUtils.getTableMeta(this.field); return meta == null || meta == left || meta.getThisType().isAssignableFrom(left.getThisType()); } } private boolean validateLeft(JoinElement q) { if (leftLock != null) { if (q == leftLock) { return true; } if (q instanceof Join) { for (QueryAlias qa : ((Join) q).allElements()) { if (qa.getQuery() == leftLock) { return true; } } } } else if (field == null) {// 纯表达式 return true; } else { // 这里从Field获得meta,但有风险,实际用的meta可能是这个meta的子类。 ITableMetadata meta = DbUtils.getTableMeta(this.field); if (meta == null) return true; if (q instanceof Query<?>) { return isMatch(meta, ((Query<?>) q).getMeta()); } if (q instanceof Join) { for (QueryAlias qa : ((Join) q).allElements()) { if (isMatch(meta, qa.getQuery().getMeta())) { return true; } } } } return false; } private boolean isMatch(ITableMetadata meta, ITableMetadata meta2) { if (meta == meta2) return true; return meta.getThisType().isAssignableFrom(meta2.getThisType()); } private boolean validateRight(JoinElement q) { if (rightLock != null) { if (q == rightLock) { return true; } if (q instanceof Join) { for (QueryAlias qa : ((Join) q).allElements()) { if (qa.getQuery() == rightLock) { return true; } } } } else { ITableMetadata meta = null; if (this.value instanceof MetadataContainer) { meta = ((MetadataContainer) value).getMeta(); } else if (value instanceof Field && value instanceof Enum) { meta = DbUtils.getTableMeta((Field) value); } if (meta == null) return true; if (q instanceof Query<?>) { return isMatch(meta, ((Query<?>) q).getMeta()); } if (q instanceof Join) { for (QueryAlias qa : ((Join) q).allElements()) { if (isMatch(meta, qa.getQuery().getMeta())) { return true; } } } } return false; } }