001
002package gudusoft.gsqlparser.dlineage.dataflow.model;
003
004import gudusoft.gsqlparser.ESqlClause;
005import gudusoft.gsqlparser.TSourceToken;
006import gudusoft.gsqlparser.dlineage.util.Pair3;
007import gudusoft.gsqlparser.nodes.TObjectName;
008import gudusoft.gsqlparser.nodes.TParseTreeNode;
009import gudusoft.gsqlparser.util.SQLUtil;
010
011import java.util.ArrayList;
012import java.util.List;
013
014public class TableColumnRelationshipElement implements RelationshipElement<TableColumn> {
015
016    private TableColumn column;
017
018    private String tableAlias;
019
020    private Integer columnIndex;
021
022    private ESqlClause relationLocation;
023
024    // Where THIS relation referenced the column (e.g. the operand in an ON or
025    // WHERE clause). The wrapped TableColumn is shared between the definition
026    // site and every reference, so its own position cannot carry the
027    // per-reference coordinate. Null when the reference site is unknown or has
028    // no real source token. Deliberately excluded from equals/hashCode.
029    private Pair3<Long, Long, String> referenceStartPosition;
030
031    private Pair3<Long, Long, String> referenceEndPosition;
032
033    private List<Transform> transforms = new ArrayList<Transform>();
034
035    public TableColumnRelationshipElement(TableColumn column) {
036        this.column = column;
037        if (column.getColumnObject() != null && column.getColumnObject().getTableString() != null) {
038            if (column.getTable().getAliasList().contains(column.getColumnObject().getTableString())) {
039                this.tableAlias = column.getColumnObject().getTableString();
040            } else {
041                this.tableAlias = column.getTable().getCurrentAlias();
042            }
043        } else {
044            this.tableAlias = column.getTable().getCurrentAlias();
045        }
046    }
047
048    public TableColumnRelationshipElement(TableColumn column, int index) {
049        this.column = column;
050        this.columnIndex = index;
051        if (column.getColumnObject().getTableString() != null) {
052            if (column.getTable().getAliasList().contains(column.getColumnObject().getTableString())) {
053                this.tableAlias = column.getColumnObject().getTableString();
054            } else {
055                this.tableAlias = column.getTable().getCurrentAlias();
056            }
057        } else {
058            this.tableAlias = column.getTable().getCurrentAlias();
059        }
060    }
061
062    public TableColumnRelationshipElement(TableColumn column,
063                                          ESqlClause relationLocation) {
064        this.column = column;
065        this.relationLocation = relationLocation;
066        if (column.getColumnObject() != null && column.getColumnObject().getTableString() != null) {
067            if (column.getTable().getAliasList().contains(column.getColumnObject().getTableString())) {
068                this.tableAlias = column.getColumnObject().getTableString();
069            } else {
070                this.tableAlias = column.getTable().getCurrentAlias();
071            }
072        } else {
073            this.tableAlias = column.getTable().getCurrentAlias();
074        }
075    }
076
077    public TableColumnRelationshipElement(TableColumn column, ESqlClause relationLocation,
078                                          TObjectName referenceObject) {
079        this(column, relationLocation);
080        setReferencePosition(referenceObject);
081    }
082
083    /**
084     * Records the span of the object name this relation was built from, so the
085     * serialized source can point at the reference site (the ON/WHERE operand)
086     * instead of the shared column model's definition site. Ignores synthesized
087     * object names, which have no real source token (their tokens sit at
088     * line 1, column 1).
089     */
090    public void setReferencePosition(TObjectName referenceObject) {
091        if (referenceObject == null || referenceObject.getStartToken() == null
092                || referenceObject.getEndToken() == null) {
093            return;
094        }
095        TSourceToken startToken = referenceObject.getStartToken();
096        TSourceToken endToken = referenceObject.getEndToken();
097        if (startToken.lineNo <= 0 || (startToken.lineNo == 1 && startToken.columnNo == 1)) {
098            return;
099        }
100        this.referenceStartPosition = new Pair3<Long, Long, String>(startToken.lineNo, startToken.columnNo,
101                ModelBindingManager.getGlobalHash());
102        this.referenceEndPosition = new Pair3<Long, Long, String>(endToken.lineNo,
103                endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(),
104                ModelBindingManager.getGlobalHash());
105    }
106
107    public Pair3<Long, Long, String> getReferenceStartPosition() {
108        return referenceStartPosition;
109    }
110
111    public Pair3<Long, Long, String> getReferenceEndPosition() {
112        return referenceEndPosition;
113    }
114
115    @Override
116    public TableColumn getElement() {
117        return column;
118    }
119
120    public ESqlClause getRelationLocation() {
121        return relationLocation;
122    }
123
124    @Override
125    public int hashCode() {
126        final int prime = 31;
127        int result = 1;
128        result = prime
129                * result
130                + ((column == null) ? 0 : column.hashCode());
131        result = prime
132                * result
133                + ((relationLocation == null) ? 0
134                : relationLocation.hashCode());
135        return result;
136    }
137
138    @Override
139    public boolean equals(Object obj) {
140        if (this == obj)
141            return true;
142        if (obj == null)
143            return false;
144        if (getClass() != obj.getClass())
145            return false;
146        TableColumnRelationshipElement other = (TableColumnRelationshipElement) obj;
147        if (column == null) {
148            if (other.column != null)
149                return false;
150        } else if (!column.equals(other.column))
151            return false;
152        if (relationLocation != other.relationLocation)
153            return false;
154        return true;
155    }
156
157    public Integer getColumnIndex() {
158        return columnIndex;
159    }
160
161    @Override
162    public List<Transform> getTransforms() {
163        return transforms;
164    }
165
166    public void addTransform(String type, TParseTreeNode code) {
167        if (ModelBindingManager.getGlobalOption() != null && !ModelBindingManager.getGlobalOption().isTransform()) {
168            return;
169        }
170        Transform transform = new Transform();
171        transform.setType(type);
172        transform.setCode(code);
173        transforms.add(transform);
174    }
175
176    public String getTableAlias() {
177        return tableAlias;
178    }
179}