1 package com.daffodilwoods.daffodildb.server.sql99.ddl.schemadefinition; 2 3 import java.util.*; 4 5 import com.daffodilwoods.daffodildb.server.datadictionarysystem.*; 6 import com.daffodilwoods.daffodildb.server.serversystem.*; 7 import com.daffodilwoods.daffodildb.server.sql99.common.*; 8 import com.daffodilwoods.daffodildb.server.sql99.ddl.descriptors.*; 9 import com.daffodilwoods.daffodildb.server.sql99.ddl.utility.*; 10 import com.daffodilwoods.daffodildb.server.sql99.dql.listenerevents.*; 11 import com.daffodilwoods.daffodildb.server.sql99.dql.queryexpression.*; 12 import com.daffodilwoods.daffodildb.server.sql99.dql.resultsetmetadata.*; 13 import com.daffodilwoods.daffodildb.server.sql99.dql.tableexpression.fromclause.*; 14 import com.daffodilwoods.daffodildb.server.sql99.token.*; 15 import com.daffodilwoods.daffodildb.server.sql99.utils.*; 16 import com.daffodilwoods.daffodildb.utils.parser.*; 17 import com.daffodilwoods.database.general.*; 18 import com.daffodilwoods.database.resource.*; 19 20 public class viewdefinition implements SQLschemadefinitionstatement, schemaelement { 21 public SRESERVEDWORD1206543922tablename _OptSRESERVEDWORD1206543922tablename0; 22 public queryexpression _queryexpression1; 23 public SRESERVEDWORD1206543922 _SRESERVEDWORD12065439222; 24 public viewspecification _viewspecification3; 25 public tablename _tablename4; 26 public SRESERVEDWORD1206543922 _SRESERVEDWORD12065439225; 27 public SNONRESERVEDWORD136444255 _OptSNONRESERVEDWORD1364442556; 28 public SRESERVEDWORD1206543922 _SRESERVEDWORD12065439227; 29 30 private SchemaDescriptor schemaDescriptor; 31 private ArrayList columnDescriptors; 32 private int[][] privilegeTypes; 33 34 public void setSchemaDescriptor(_Descriptor schemaDes) throws DException { 35 schemaDescriptor = (SchemaDescriptor) schemaDes; 36 } 37 38 60 public Object run(Object object) throws DException { 61 _ServerSession currentSession = ( (_ServerSession) object); 62 boolean isIndependentStt = schemaDescriptor == null; 63 checkForINTOTableName(); 64 ViewDescriptor viewDescriptor = new ViewDescriptor(); 65 setViewName(currentSession, viewDescriptor); 66 if (isIndependentStt) { 67 validateUserPrivilege(currentSession); 68 } 69 setViewQuery(viewDescriptor, currentSession); 70 if (_OptSNONRESERVEDWORD1364442556 != null) { 71 setMaterializedTableName(viewDescriptor); 72 } 73 viewDescriptor.save(currentSession); 74 createPrivileges(currentSession, viewDescriptor, columnDescriptors, 75 privilegeTypes); 76 if (_OptSNONRESERVEDWORD1364442556 != null) { 77 createMaterializedTable(viewDescriptor, currentSession); 78 79 } 80 refreshDataDictionary(currentSession, viewDescriptor); 81 return null; 82 } 83 84 private void refreshDataDictionary(_ServerSession currentSession, 85 ViewDescriptor viewDescriptor) throws 86 DException { 87 if (viewDescriptor.materialized_table_name != null) { 88 DataDictionary dd = (DataDictionary) currentSession.getDataDictionary(); 89 ArrayList tablesUsed = viewDescriptor.tablesUsed; 90 QualifiedIdentifier materializedTable = new QualifiedIdentifier( 91 viewDescriptor.table_catalog, viewDescriptor.table_schema, 92 viewDescriptor.materialized_table_name); 93 if (tablesUsed != null) { 94 for (int i = 0; i < tablesUsed.size(); i++) { 95 String [] tableName = (String []) tablesUsed.get(i); 96 dd.addMaterializedTable(new QualifiedIdentifier(tableName[0], 97 tableName[1], tableName[2]), materializedTable); 98 } 99 } 100 } 101 } 102 103 private void checkForINTOTableName() throws DException { 104 if (_OptSRESERVEDWORD1206543922tablename0 != null && 105 _OptSNONRESERVEDWORD1364442556 == null) { 106 throw new DException("DSE5015", null); 107 } 108 } 109 110 private void setViewName(_ServerSession currentSession, 111 ViewDescriptor viewDescriptor) throws DException { 112 setTableDescriptor(currentSession, viewDescriptor); 113 checkSchema(viewDescriptor.tableDescriptor, currentSession); 114 viewDescriptor.setViewName(); 115 } 116 117 private void setTableDescriptor(_ServerSession currentSession, 118 ViewDescriptor viewDescriptor) throws 119 DException { 120 TableDescriptor tableDescriptor = new TableDescriptor(); 121 tableDescriptor.table_catalog = _tablename4.getCatalogName(); 122 tableDescriptor.table_schema = _tablename4.getSchemaName(); 123 tableDescriptor.table_name = _tablename4.getTableName(); 124 tableDescriptor.table_type = SqlKeywords.VIEW; 125 viewDescriptor.tableDescriptor = tableDescriptor; 126 } 127 128 private void checkSchema(TableDescriptor tableDescriptor, 129 _ServerSession currentSession) throws DException { 130 if (schemaDescriptor != null) { 131 if (tableDescriptor.table_schema != null && 132 (!tableDescriptor.table_schema.equalsIgnoreCase(schemaDescriptor. 133 schema_name))) { 134 throw new DException("DSE903", null); 135 } 136 tableDescriptor.table_schema = schemaDescriptor.schema_name; 137 if (tableDescriptor.table_catalog != null && 138 !tableDescriptor.table_catalog.equalsIgnoreCase(schemaDescriptor. 139 catalog_name)) { 140 throw new DException("DSE227", null); 141 } 142 tableDescriptor.table_catalog = schemaDescriptor.catalog_name; 143 } else { 144 if (tableDescriptor.table_catalog == null) { 145 tableDescriptor.table_catalog = currentSession.getCurrentCatalog(); 146 } 147 if (tableDescriptor.table_schema == null) { 148 tableDescriptor.table_schema = currentSession.getCurrentSchema(); 149 } 150 schemaDescriptor = new SchemaDescriptor(); 151 schemaDescriptor.catalog_name = tableDescriptor.table_catalog; 152 schemaDescriptor.schema_name = tableDescriptor.table_schema; 153 schemaDescriptor.load(currentSession); 154 } 155 } 156 157 private void validateUserPrivilege(_ServerSession currentSession) throws 158 DException { 159 String authorizationIdentifier = schemaDescriptor.schema_owner; 160 if (!currentSession.isEnabledAuthorizationIdentifier( 161 authorizationIdentifier, true)) { 162 throw new DException("DSE12", null); 163 } 164 } 165 166 175 176 177 private void setViewQuery(ViewDescriptor viewDescriptor, 178 _ServerSession currentSession) throws 179 DException { 180 viewDescriptor.view_definition = _queryexpression1.toString(); 181 if ( (viewDescriptor.view_definition.toLowerCase().indexOf("contains")) > 0) { 182 throw new DException("DSE8152", null); 183 } 184 if(!SystemTables.isSystemView(viewDescriptor.getViewName())){ 185 if (_queryexpression1.getOrderByclause() != null) { 186 throw new DException("DSE8207", null); 187 } 188 } 189 checkSemanticOfQuery(currentSession, viewDescriptor); 190 checkColumns(viewDescriptor, currentSession); 191 storeTablesIncluded(viewDescriptor); 192 storeColumnsIncluded(viewDescriptor); 193 viewDescriptor.is_updatable = SqlSchemaConstants.NO; 194 viewDescriptor.is_insertable_into = SqlSchemaConstants.NO; 195 } 196 197 210 211 private void checkSemanticOfQuery(_ServerSession currentSession, ViewDescriptor viewDescriptor) throws DException { 212 String currentSchema = currentSession.getCurrentSchema(); 213 try { 214 currentSession.setCurrentSchema(viewDescriptor.table_schema); 215 } catch (DException ex) { 216 throw new DException("DSE8166", new Object [] {viewDescriptor.table_schema}); 217 } 218 _Reference[] references = null; 219 try { 220 references = _queryexpression1.checkSemantic(currentSession, false); 221 } catch (DException ex) { 222 currentSession.setCurrentSchema(currentSchema); 223 throw ex; 224 } 225 currentSession.setCurrentSchema(currentSchema); 226 if (references != null && references.length != 0) { 227 for (int j = 0; j < references.length; j++) { 228 if (references[j].getReferenceType() == SimpleConstants.VARIABLECOLUMN) { 229 throw new DException("DSE8159", new Object [] {viewDescriptor.table_name}); 230 } 231 } 232 throw new DException("DSE256", 233 new Object [] {StaticClass.printArray(references)}); 234 } 235 } 236 237 private void storeTablesIncluded(ViewDescriptor viewDescriptor) throws 238 DException { 239 ArrayList tablesIncluded = new ArrayList(); 240 _queryexpression1.getTablesIncluded(tablesIncluded); 241 ArrayList tablesList = GeneralUtility.removeRedundentTables(viewDescriptor. 242 table_catalog, viewDescriptor.table_schema, tablesIncluded); 243 viewDescriptor.tablesUsed = tablesList; 244 } 245 246 private void storeColumnsIncluded(ViewDescriptor viewDescriptor) throws 247 DException { 248 ArrayList columnsIncluded = new ArrayList(); 249 _queryexpression1.getColumnsIncluded(columnsIncluded); 250 ArrayList columnsList = GeneralUtility.removeRedundentColumns( 251 viewDescriptor.table_catalog, viewDescriptor.table_schema, null, 252 columnsIncluded); 253 viewDescriptor.columnsUsed = columnsList; 254 } 255 256 257 private void checkColumns(ViewDescriptor viewDescriptor, 258 _ServerSession currentSession) throws 259 DException { 260 String [] columns = (String []) _viewspecification3.run(null); 261 ColumnDetails[] columnDetails = _queryexpression1.getSelectedColumns(); 262 privilegeTypes = getAllPrivilegesTypes(currentSession, columnDetails); 263 int columnCount = columnDetails.length; 264 if (columns != null && columnCount != columns.length) { 265 throw new DException("DSE752", null); 266 } 267 columnDescriptors = getColumnsDescriptors(columnDetails, 268 viewDescriptor, currentSession, 269 columns == null); 270 replaceColumnNameInDescriptors(viewDescriptor.tableDescriptor, 271 columnDescriptors, columns); 272 } 273 274 private void replaceColumnNameInDescriptors(TableDescriptor tableDescriptor, 275 ArrayList columnDescriptors, 276 String [] columns) throws 277 DException { 278 for (int i = 0, columnCount = columnDescriptors.size(); i < columnCount; i++) { 279 ColumnDescriptor columnDescriptor = (ColumnDescriptor) columnDescriptors. 280 get(i); 281 if (columns != null) { 282 columnDescriptor.column_name = columns[i]; } 284 columnDescriptor.dtd_identifier = columnDescriptor.table_name + "." + 285 columnDescriptor.column_name; 286 columnDescriptor.dataTypeDescriptor.dtd_identifier = columnDescriptor. 287 dtd_identifier; 288 try { 289 tableDescriptor.addColumnDescriptor(columnDescriptor); 290 } catch (DException ex) { 291 if (ex.getDseCode().equalsIgnoreCase("DSE250")) { 292 throw new DException("DSE7077", ex.getParameters()); 293 } 294 throw ex; 295 } 296 } 297 } 298 299 309 310 private ArrayList getColumnsDescriptors(ColumnDetails[] columnDetails, 311 ViewDescriptor viewDescriptor, 312 _ServerSession currentSession, 313 boolean columnsNotPresent) throws 314 DException { 315 ArrayList columnDescriptorsList = new ArrayList(); 316 for (int i = 0; i < columnDetails.length; i++) { 317 321 if (!columnDetails[i].isValidForView() && columnsNotPresent) { 322 throw new DException("DSE1090", null); 323 } 324 int columnType = columnDetails[i].getType(); 325 ColumnDescriptor columnDescriptor = new ColumnDescriptor(); 326 columnDescriptor.table_catalog = viewDescriptor.table_catalog; 327 columnDescriptor.table_schema = viewDescriptor.table_schema; 328 columnDescriptor.table_name = viewDescriptor.table_name; 329 intializeColumnProperties(columnDescriptor, columnDetails[i]); 330 DataTypeDescriptor dataTypeDes = columnDescriptor.dataTypeDescriptor; 331 dataTypeDes.object_catalog = columnDescriptor.table_catalog; 332 dataTypeDes.object_schema = columnDescriptor.table_schema; 333 dataTypeDes.object_name = columnDescriptor.table_name; 334 dataTypeDes.object_type = "Table"; 335 columnDescriptorsList.add(columnDescriptor); 336 } 337 return columnDescriptorsList; 338 } 339 340 private void intializeColumnProperties(ColumnDescriptor columnDescriptor, 341 ColumnDetails columnDetails) throws 342 DException { 343 DataTypeDescriptor dataTypeDes = new DataTypeDescriptor(); 344 columnDescriptor.dataTypeDescriptor = dataTypeDes; 345 columnDescriptor.column_name = columnDetails.getAppropriateColumn(); 346 int type = columnDetails.getDatatype(); 347 int scale = -1; 348 if (columnDetails.getReferenceType() == TypeConstants.REFERENCE) { 349 scale = columnDetails.getTableDetails(). 350 getColumnCharacteristics().getScale(columnDetails.getIndex()); 351 } 352 GeneralUtility.setDataTypeProperties(columnDetails.getSize(), dataTypeDes, 353 type, scale); 354 columnDescriptor.dataTypeDescriptor = dataTypeDes; 355 } 356 357 public void createMaterializedTable(ViewDescriptor viewDescriptor, 358 _ServerSession currentSession) throws 359 DException { 360 _SelectIterator iterator = getIteratorForViewQuery(currentSession, 361 viewDescriptor.view_definition); 362 QualifiedIdentifier matTable = new QualifiedIdentifier(viewDescriptor. 363 table_catalog, viewDescriptor.table_schema, 364 viewDescriptor.materialized_table_name); 365 createTableAndIndexes(viewDescriptor, currentSession, iterator, 366 matTable); 367 populateTableWithQueryResult(currentSession, iterator, matTable); 368 } 369 370 private void populateTableWithQueryResult(_ServerSession currentSession, 371 _SelectIterator iterator, 372 QualifiedIdentifier matTable) throws 373 DException { 374 iterator.beforeFirst(); 375 _ServerTable serverTable = currentSession.getServerTable(matTable); 376 while (true) { 377 Object [] data = iterator.fetchForward(50); 378 if (data == null) { 379 break; 380 } 381 for (int i = 0; i < data.length; i++) { 382 serverTable.insert( (Object []) data[i]); 383 } 384 } 385 } 386 387 private void createTableAndIndexes(ViewDescriptor viewDescriptor, 388 _ServerSession currentSession, 389 _SelectIterator iterator, 390 QualifiedIdentifier matTable) throws 391 DException { 392 AllColumnRowReader rowReader = (AllColumnRowReader) iterator.getRowReader(); 393 String query = rowReader.getQueryForTable(matTable); 394 tabledefinition td = (tabledefinition) Parser.parseQuery(query); 395 td.setSchemaDescriptor(schemaDescriptor); 396 td.run(currentSession); 397 String [] keyColumns = rowReader.getKeyColumns(); 398 String indexName = currentSession.getDataDictionary().generateIndexName(); 399 indexdefinition parsedObject = (indexdefinition) Parser.parseQuery( 400 QueryMaker.getCreateIndexQuery(matTable, Arrays.asList(keyColumns), 401 indexName)); 402 parsedObject.setIsSelfInitiated(false); 403 parsedObject.run(currentSession); 404 td.addToIndexList(indexName); 405 td.createTableAndIndexes(currentSession); 406 } 407 408 private _SelectIterator getIteratorForViewQuery(_ServerSession currentSession, 409 String viewQuery) throws 410 DException { 411 _SelectIterator iterator = (_SelectIterator) currentSession.execute( 412 viewQuery, 0, IteratorConstants.UPDATABLE); 413 return iterator; 414 } 415 416 private void setMaterializedTableName(ViewDescriptor viewDescriptor) throws 417 DException { 418 if (_OptSRESERVEDWORD1206543922tablename0 != null) { 419 String table_catalog = _OptSRESERVEDWORD1206543922tablename0. 420 getCatalogName(); 421 String table_schema = _OptSRESERVEDWORD1206543922tablename0.getSchemaName(); 422 String table_name = _OptSRESERVEDWORD1206543922tablename0.getObjectName(); 423 if (table_catalog != null && 424 !table_catalog.equalsIgnoreCase(viewDescriptor.table_catalog)) { 425 throw new DException("DSE895", null); 426 } 427 if (table_schema != null && 428 !table_schema.equalsIgnoreCase(viewDescriptor.table_schema)) { 429 throw new DException("DSE895", null); 430 } 431 viewDescriptor.materialized_table_name = table_name; 432 } else { 433 435 } 436 } 437 438 446 447 458 459 private int[][] getAllPrivilegesTypes(_ServerSession currentSession, 460 ColumnDetails[] viewColumnDetails) throws 461 DException { 462 _PrivilegeCharacteristics pc = currentSession.getDataDictionary(). 463 getPrivilegeCharacteristics(schemaDescriptor.schema_owner, _PrivilegeCharacteristics.AUTHORIZATION_ROLE); 464 int len = viewColumnDetails.length; 465 int[][] privilegesTypes = new int[len][2]; 466 for (int i = 0; i < len; i++) { 467 ColumnDetails cd = viewColumnDetails[i]; 468 privilegesTypes[i] = getGrantTypesOfUnderLyingColumns(cd, pc); 469 } 470 return privilegesTypes; 471 } 472 473 private int[] getPrivilegeType(ColumnDetails cd, _PrivilegeCharacteristics pc) throws 474 DException { 475 if (cd.getType() == ColumnDetails.CONSTANT) { 476 return new int[] { 477 _PrivilegeTable.RIGHTWITHGRANTOPTION, 478 _PrivilegeTable.RIGHTWITHGRANTOPTION}; 479 } 480 int columnIndex = cd.getColumnCharacteristics().getColumnIndex(cd.getColumn()); 481 QualifiedIdentifier tableName = cd.getTable().getQualifiedIdentifier(); 482 _PrivilegeTable pt = pc.getPrivilegeTable(tableName); 483 int selectPrivilegeType = pt.getColumnPrivilegesType(columnIndex, 484 _PrivilegeTable.SELECT); 485 if (selectPrivilegeType == _PrivilegeTable.NOACCESS) { 486 throw new DException( 487 "DSE8025", 488 new Object [] {cd.getColumn(), tableName}); 489 } 490 int referencePrivilegeType = pt.getColumnPrivilegesType(columnIndex, 491 _PrivilegeTable.REFERENCES); 492 return new int[] { 493 selectPrivilegeType, referencePrivilegeType}; 494 } 495 496 private int[] getGrantTypesOfUnderLyingColumns(ColumnDetails cd, 497 _PrivilegeCharacteristics pc) throws 498 DException { 499 ColumnDetails[] existingCDs = cd. 500 getCorresspondingColumnsInvolved(); 501 int selectGrantType = _PrivilegeTable.RIGHTWITHGRANTOPTION; 502 int referenceGrantType = _PrivilegeTable.RIGHTWITHGRANTOPTION; 503 if (existingCDs != null) { 504 for (int j = 0; j < existingCDs.length; j++) { 505 int[] abc = getPrivilegeType(existingCDs[j], pc); 506 selectGrantType = getPrivilegeType(abc[0], selectGrantType); 507 referenceGrantType = getPrivilegeType(abc[1], referenceGrantType); 508 } 509 } 510 return new int[] { 511 selectGrantType, referenceGrantType}; 512 } 513 514 private int getPrivilegeType(int currentGrantType, int previousGrantType) throws 515 DException { 516 if (previousGrantType == _PrivilegeTable.RIGHTWITHGRANTOPTION && 517 currentGrantType == _PrivilegeTable.ONLYRIGHT) { 518 previousGrantType = _PrivilegeTable.ONLYRIGHT; 519 } else if (currentGrantType == _PrivilegeTable.NOACCESS) { 520 previousGrantType = _PrivilegeTable.NOACCESS; 521 } 522 return previousGrantType; 523 } 524 525 private void createPrivileges(_ServerSession currentSession, 526 ViewDescriptor viewDescriptor, 527 ArrayList columnDescriptors, 528 int[][] privilegesTypes) throws DException { 529 int size = columnDescriptors.size(); 530 String grantee = schemaDescriptor.schema_owner; 531 boolean isAllRefPri = true; 532 boolean isAllSelectGrantable = true; 533 boolean isAllRefGrantable = true; 534 for (int i = 0; i < size; i++) { 535 ColumnDescriptor colDes = (ColumnDescriptor) columnDescriptors.get(i); 536 if (privilegesTypes[i][0] == _PrivilegeTable.RIGHTWITHGRANTOPTION) { 537 makeColumnPriDes(currentSession, colDes, grantee, SqlKeywords.SELECT, 538 SqlSchemaConstants.YES); 539 } else { 540 makeColumnPriDes(currentSession, colDes, grantee, SqlKeywords.SELECT, 541 SqlSchemaConstants.NO); 542 isAllSelectGrantable = false; 543 } 544 if (privilegesTypes[i][1] == _PrivilegeTable.RIGHTWITHGRANTOPTION) { 545 makeColumnPriDes(currentSession, colDes, grantee, 546 SqlKeywords.REFERENCES, 547 SqlSchemaConstants.YES); 548 } else if (privilegesTypes[i][1] == _PrivilegeTable.ONLYRIGHT) { 549 makeColumnPriDes(currentSession, colDes, grantee, 550 SqlKeywords.REFERENCES, 551 SqlSchemaConstants.NO); 552 isAllRefGrantable = false; 553 } else { 554 isAllRefPri = false; 555 isAllRefGrantable = false; 556 } 557 } 558 makeTablePriDes(currentSession, viewDescriptor.tableDescriptor, grantee, 559 SqlKeywords.SELECT, isAllSelectGrantable 560 ? SqlSchemaConstants.YES : SqlSchemaConstants.NO); 561 if (isAllRefPri) { 562 makeTablePriDes(currentSession, viewDescriptor.tableDescriptor, grantee, 563 SqlKeywords.REFERENCES, isAllRefGrantable 564 ? SqlSchemaConstants.YES : SqlSchemaConstants.NO); 565 } 566 } 567 568 private void makeColumnPriDes(_ServerSession currentSession, 569 ColumnDescriptor colDes, String grantee, 570 String privilegeType, String isGrantable) throws 571 DException { 572 ColumnPrivilegeDescriptor cpd = new ColumnPrivilegeDescriptor(); 573 cpd.object_catalog = colDes.table_catalog; 574 cpd.object_schema = colDes.table_schema; 575 cpd.object_name = colDes.table_name; 576 cpd.column_name = colDes.column_name; 577 cpd.grantee = grantee; 578 cpd.grantor = SqlSchemaConstants.SYSTEM; 579 cpd.is_grantable = isGrantable; 580 cpd.privilege_type = privilegeType; 581 cpd.save(currentSession); 582 } 583 584 private void makeTablePriDes(_ServerSession currentSession, 585 TableDescriptor tableDes, String grantee, 586 String privilegeType, String isGrantable) throws 587 DException { 588 TablePrivilegesDescriptor tpd = new TablePrivilegesDescriptor(); 589 tpd.object_catalog = tableDes.table_catalog; 590 tpd.object_schema = tableDes.table_schema; 591 tpd.object_name = tableDes.table_name; 592 tpd.grantee = grantee; 593 tpd.grantor = SqlSchemaConstants.SYSTEM; 594 tpd.is_grantable = isGrantable; 595 tpd.privilege_type = privilegeType; 596 tpd.save(currentSession); 597 } 598 599 public String toString() { 600 StringBuffer sb = new StringBuffer (); 601 sb.append(" "); 602 sb.append(_SRESERVEDWORD12065439227); 603 sb.append(" "); 604 if (_OptSNONRESERVEDWORD1364442556 != null) { 605 sb.append(_OptSNONRESERVEDWORD1364442556); 606 } 607 sb.append(" "); 608 sb.append(_SRESERVEDWORD12065439225); 609 sb.append(" "); 610 sb.append(_tablename4); 611 sb.append(" "); 612 sb.append(_viewspecification3); 613 sb.append(" "); 614 sb.append(_SRESERVEDWORD12065439222); 615 sb.append(" "); 616 sb.append(_queryexpression1); 617 sb.append(" "); 618 if (_OptSRESERVEDWORD1206543922tablename0 != null) { 619 sb.append(_OptSRESERVEDWORD1206543922tablename0); 620 } 621 return sb.toString(); 622 } 623 624 public Object clone() throws CloneNotSupportedException { 625 return this; 626 } 627 628 651 } 652 | Popular Tags |