001package gudusoft.gsqlparser.dlineage.dataflow.model.xml; 002 003import java.util.Comparator; 004import java.util.LinkedHashSet; 005import java.util.Set; 006 007import javax.xml.bind.annotation.XmlAttribute; 008import javax.xml.bind.annotation.XmlElement; 009import javax.xml.bind.annotation.XmlElementWrapper; 010import javax.xml.bind.annotation.XmlTransient; 011import javax.xml.bind.annotation.XmlType; 012 013import gudusoft.gsqlparser.TSourceToken; 014import gudusoft.gsqlparser.dlineage.dataflow.model.ModelBindingManager; 015import gudusoft.gsqlparser.dlineage.dataflow.model.Transform; 016import gudusoft.gsqlparser.dlineage.util.DlineageUtil; 017import gudusoft.gsqlparser.dlineage.util.Pair3; 018import gudusoft.gsqlparser.util.SQLUtil; 019 020@XmlType(propOrder = { "id", "name", "column", "value", "source_id", "source_name", "column_type", "parent_id", "parent_name", "parent_alias", 021 "coordinate", "clauseType", "source", "type", "transforms", "candidateParents"}) 022public class sourceColumn { 023 024 private String id; 025 026 private String name; 027 028 private String column; 029 030 private String value; 031 032 private String source_id; 033 034 private String source_name; 035 036 private String column_type; 037 038 private String parent_id; 039 040 private String parent_name; 041 042 private String parent_alias; 043 044 private String coordinate; 045 046 private String clauseType; 047 048 private String source; 049 050 private String type; 051 052 private Set<transform> transforms; 053 054 private Set<candidateTable> candidateParents; 055 056 @XmlTransient 057 private Boolean struct; 058 059 private String dedupCoordinate; 060 061 @XmlElementWrapper(name="candidateTables") 062 @XmlElement(name="candidateTable", required = false) 063 public Set<candidateTable> getCandidateParents() { 064 if (ModelBindingManager.getGlobalOption()!=null && !ModelBindingManager.getGlobalOption().isShowCandidateTable()) { 065 return null; 066 } 067 return candidateParents; 068 } 069 070 public void setCandidateParents(Set<candidateTable> candidateParents) { 071 if (ModelBindingManager.getGlobalOption()!=null && !ModelBindingManager.getGlobalOption().isShowCandidateTable()) { 072 return; 073 } 074 this.candidateParents = candidateParents; 075 } 076 077 public void addCandidateParent(candidateTable candidateParent) { 078 if (ModelBindingManager.getGlobalOption()!=null && !ModelBindingManager.getGlobalOption().isShowCandidateTable()) { 079 return; 080 } 081 if(candidateParent == null) 082 return; 083 if(candidateParents == null) { 084 candidateParents = new LinkedHashSet<candidateTable>(); 085 } 086 candidateParents.add(candidateParent); 087 } 088 089 @XmlElementWrapper(name="transforms") 090 @XmlElement(name="transform", required = false) 091 public Set<transform> getTransforms() { 092 if (ModelBindingManager.getGlobalOption()!=null && !ModelBindingManager.getGlobalOption().isTransform()) { 093 return null; 094 } 095 return transforms; 096 } 097 098 public void setTransforms(Set<transform> transforms) { 099 if (ModelBindingManager.getGlobalOption()!=null && !ModelBindingManager.getGlobalOption().isTransform()) { 100 return; 101 } 102 this.transforms = transforms; 103 } 104 105 public void addTransform(Transform transform) { 106 if (ModelBindingManager.getGlobalOption()!=null && !ModelBindingManager.getGlobalOption().isTransform()) { 107 return; 108 } 109 if(transform == null) 110 return; 111 if(transforms == null) { 112 transforms = new LinkedHashSet<transform>(); 113 } 114 115 transform t = new transform(); 116 if (transform.getCode() != null) { 117 if (ModelBindingManager.getGlobalOption().isTransformCoordinate()) { 118 TSourceToken startToken = transform.getCode().getStartToken(); 119 TSourceToken endToken = transform.getCode().getEndToken(); 120 Pair3<Long, Long, String> startPosition = new Pair3<Long, Long, String>(startToken.lineNo, 121 startToken.columnNo, ModelBindingManager.getGlobalHash()); 122 Pair3<Long, Long, String> endPosition = new Pair3<Long, Long, String>(endToken.lineNo, 123 endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash()); 124 t.setCoordinate(convertCoordinate(startPosition) + "," + convertCoordinate(endPosition)); 125 } 126 t.setCode(transform.getCode().toString()); 127 } else if (!SQLUtil.isEmpty(transform.getCodeString())) { 128 if (ModelBindingManager.getGlobalOption().isTransformCoordinate()) { 129 TSourceToken startToken = transform.getStartToken(); 130 TSourceToken endToken = transform.getEndToken(); 131 Pair3<Long, Long, String> startPosition = new Pair3<Long, Long, String>(startToken.lineNo, 132 startToken.columnNo, ModelBindingManager.getGlobalHash()); 133 Pair3<Long, Long, String> endPosition = new Pair3<Long, Long, String>(endToken.lineNo, 134 endToken.columnNo + SQLUtil.endTrim(endToken.getAstext()).length(), ModelBindingManager.getGlobalHash()); 135 t.setCoordinate(convertCoordinate(startPosition) + "," + convertCoordinate(endPosition)); 136 } 137 t.setCode(transform.getCodeString()); 138 } 139 t.setType(transform.getType()); 140 transforms.add(t); 141 } 142 143 public void addTransform(transform transform) { 144 if (ModelBindingManager.getGlobalOption()!=null && !ModelBindingManager.getGlobalOption().isTransform()) { 145 return; 146 } 147 if(transform == null) 148 return; 149 if(transforms == null) { 150 transforms = new LinkedHashSet<transform>(); 151 } 152 transforms.add(transform); 153 } 154 155 private Pair3<Long, Long, Integer> convertCoordinate(Pair3<Long, Long, String> position) { 156 return new Pair3<Long, Long, Integer>(position.first, position.second, 157 ModelBindingManager.getGlobalSqlInfo().getIndexOf(position.third)); 158 } 159 160 @XmlAttribute(required = false) 161 public String getCoordinate() { 162// if (ModelBindingManager.getGlobalOption()!=null && ModelBindingManager.getGlobalOption().isIgnoreCoordinate()) { 163// return null; 164// } 165 return coordinate; 166 } 167 168 public void setCoordinate(String coordinate) { 169// if (ModelBindingManager.getGlobalOption()!=null && ModelBindingManager.getGlobalOption().isIgnoreCoordinate()) { 170// return; 171// } 172 this.coordinate = coordinate; 173 } 174 175 @XmlAttribute(required = false) 176 public String getColumn() { 177 return column; 178 } 179 180 public void setColumn(String column) { 181 this.column = column; 182 } 183 184 @XmlAttribute(required = false) 185 public String getId() { 186 return id; 187 } 188 189 public void setId(String id) { 190 this.id = id; 191 } 192 193 @XmlAttribute(name = "parent_id", required = false) 194 public String getParent_id() { 195 return parent_id; 196 } 197 198 public void setParent_id(String parent_id) { 199 this.parent_id = parent_id; 200 } 201 202 @XmlAttribute(name = "parent_name", required = false) 203 public String getParent_name() { 204 return parent_name; 205 } 206 207 public void setParent_name(String parent_name) { 208 this.parent_name = parent_name; 209 } 210 211 @XmlAttribute(name = "parent_alias", required = false) 212 public String getParent_alias() { 213 return parent_alias; 214 } 215 216 public void setParent_alias(String parent_alias) { 217 this.parent_alias = parent_alias; 218 } 219 220 @XmlAttribute(required = false) 221 public String getValue() { 222 return value; 223 } 224 225 public void setValue(String value) { 226 this.value = value; 227 } 228 229 @XmlAttribute(name = "source_name", required = false) 230 public String getSource_name() { 231 return source_name; 232 } 233 234 public void setSource_name(String source_name) { 235 this.source_name = source_name; 236 } 237 238 @XmlAttribute(name = "source_id", required = false) 239 public String getSource_id() { 240 return source_id; 241 } 242 243 public void setSource_id(String source_id) { 244 this.source_id = source_id; 245 } 246 247 @XmlAttribute(required = false) 248 public String getClauseType() { 249 return clauseType; 250 } 251 252 public void setClauseType(String clauseType) { 253 this.clauseType = clauseType; 254 } 255 256 @XmlAttribute(name = "column_type", required = false) 257 public String getColumn_type() { 258 return column_type; 259 } 260 261 public void setColumn_type(String column_type) { 262 this.column_type = column_type; 263 } 264 265 @XmlAttribute(required = false) 266 public String getSource() { 267 return source; 268 } 269 270 public void setSource(String source) { 271 this.source = source; 272 } 273 274 @XmlAttribute(required = false) 275 public String getType() { 276 return type; 277 } 278 279 public void setType(String type) { 280 this.type = type; 281 } 282 283 @Override 284 public int hashCode() { 285 final int prime = 31; 286 int result = 1; 287 String columnName = getColumnName(this); 288 result = prime * result + ((columnName == null) ? 0 : columnName.hashCode()); 289 result = prime * result + ((coordinate == null) ? 0 : coordinate.hashCode()); 290 result = prime * result + ((parent_id == null) ? 0 : parent_id.hashCode()); 291 return result; 292 } 293 294 private String getColumnName(sourceColumn column) { 295 if ("constant".equals(column.getColumn_type())) { 296 return column.column; 297 } 298 if (ModelBindingManager.getGlobalVendor() != null) { 299 return DlineageUtil.getIdentifierNormalColumnName(column.column); 300 } 301 return column.column; 302 } 303 304 @Override 305 public boolean equals(Object obj) { 306 if (this == obj) 307 return true; 308 if (obj == null) 309 return false; 310 if (getClass() != obj.getClass()) 311 return false; 312 sourceColumn other = (sourceColumn) obj; 313 if (column == null) { 314 if (other.column != null) 315 return false; 316 } else if (!getColumnName(this).equals(getColumnName(other))) 317 return false; 318 if (coordinate == null) { 319 if (other.coordinate != null) 320 return false; 321 } else if (coordinate.hashCode() != other.coordinate.hashCode()) 322 return false; 323 if (parent_id == null) { 324 if (other.parent_id != null) 325 return false; 326 } else if (!parent_id.equals(other.parent_id)) 327 return false; 328 return true; 329 } 330 331 @XmlAttribute(required = false) 332 public String getName() { 333 return name; 334 } 335 336 public void setName(String name) { 337 this.name = name; 338 } 339 340 @XmlTransient 341 public Boolean isStruct() { 342 return struct; 343 } 344 345 public void setStruct(Boolean struct) { 346 this.struct = struct; 347 } 348 349 public String toDedupKey() { 350 StringBuilder sb = new StringBuilder(128); 351 appendDedupKey(sb); 352 return sb.toString(); 353 } 354 355 public long toDedupHash() { 356 StringBuilder sb = new StringBuilder(128); 357 appendDedupKey(sb); 358 return SQLUtil.hash64(sb); 359 } 360 361 /** 362 * The coordinate this source would have carried before reference-site 363 * publishing — the column model's definition span. The table-merge pass 364 * stamps it in for its dedup steps (equals/hashCode and toDedupHash include 365 * the coordinate), so sources and relations keep collapsing exactly as they 366 * did when every reference was rendered with the model span, then restores 367 * the published reference-site coordinate on the survivors. Never 368 * serialized. 369 */ 370 @XmlTransient 371 public String getDedupCoordinate() { 372 return dedupCoordinate; 373 } 374 375 public void setDedupCoordinate(String dedupCoordinate) { 376 this.dedupCoordinate = dedupCoordinate; 377 } 378 379 void appendDedupKey(StringBuilder sb) { 380 if (name != null) { sb.append("name=").append(name).append('|'); } 381 if (column != null) { sb.append("column=").append(column).append('|'); } 382 if (parent_id != null) { sb.append("parent_id=").append(parent_id).append('|'); } 383 if (source_id != null) { sb.append("source_id=").append(source_id).append('|'); } 384 if (value != null) { sb.append("value=").append(value).append('|'); } 385 if (source_name != null) { sb.append("source_name=").append(source_name).append('|'); } 386 if (column_type != null) { sb.append("column_type=").append(column_type).append('|'); } 387 if (parent_name != null) { sb.append("parent_name=").append(parent_name).append('|'); } 388 if (parent_alias != null) { sb.append("parent_alias=").append(parent_alias).append('|'); } 389 if (coordinate != null) { sb.append("coordinate=").append(coordinate).append('|'); } 390 if (clauseType != null) { sb.append("clauseType=").append(clauseType).append('|'); } 391 if (source != null) { sb.append("source=").append(source).append('|'); } 392 if (type != null) { sb.append("type=").append(type).append('|'); } 393 if (transforms != null && !transforms.isEmpty()) { 394 sb.append("transforms=["); 395 transforms.stream().sorted(Comparator.comparing(transform::getType, Comparator.nullsFirst(Comparator.<String>naturalOrder()))) 396 .forEach(t -> { sb.append('{'); t.appendDedupKey(sb); sb.append("},"); }); 397 sb.setLength(sb.length() - 1); 398 sb.append("]|"); 399 } 400 if (candidateParents != null && !candidateParents.isEmpty()) { 401 sb.append("candidateParents=["); 402 candidateParents.stream().sorted(Comparator.comparing(candidateTable::getId, Comparator.nullsFirst(Comparator.<String>naturalOrder()))) 403 .forEach(c -> { sb.append('{'); c.appendDedupKey(sb); sb.append("},"); }); 404 sb.setLength(sb.length() - 1); 405 sb.append("]|"); 406 } 407 } 408}