Project

General

Profile

marshal5.diff

Igor Skornyakov, 11/11/2022 07:23 AM

Download (124 KB)

View differences:

src/com/goldencode/p2j/persist/AbstractTempTable.java 2022-11-11 09:09:20 +0000
56 56
**     CA  20220920 Buffer implicit deletion performed on temp-table delete must use a ProcedureManager to 
57 57
**                  delete it instead of handle.delete.
58 58
**     IAS 20221003 Fixed error message for error 3131
59
**     IAS 20221111 Added setter for the 'schemaMarshalLevel', fixed one for the 'namespaceURI'.
59 60
*/
60 61

  
61 62
/*
......
882 883
   }
883 884
   
884 885
   /**
886
    * Set the current {@code SCHEMA-MARSHAL} level. Refer to {@code SM_DEFAULT}, {@code SM_NONE},
887
    * {@code SM_MIN}, and {@code SM_FULL} static constants for details. 
888
    */
889
   public void setSchemaMarshalLevel(int schemaMarshalLevel)
890
   {
891
      this.schemaMarshal = schemaMarshalLevel;
892
   }
893

  
894
   /**
885 895
    * Implements the {@code NO-SCHEMA-MARSHAL} attribute getter.
886 896
    * 
887 897
    * @return  {@code true} when {@code SCHEMA-MARSHAL} attribute is set to {@code "NONE"}.
......
2314 2324
   @Override
2315 2325
   public void namespaceURI(character uri)
2316 2326
   {
2317
      namespaceURI(uri.toJavaType());
2327
      namespaceURI(uri.isUnknown() ? "" : uri.toJavaType());
2318 2328
   }
2319 2329
   
2320 2330
   /**
src/com/goldencode/p2j/persist/DataSet.java 2022-11-11 12:01:57 +0000
92 92
**                  an APPEND option.
93 93
**     CA  20220918 Automatically delete top-nav queries created dynamically by the DATASET.
94 94
**     CA  20221031 Added JMX instrumentation for DATASET[-HANDLE] parameter processing.
95
**     IAS 20221108 Fixed support for SCHEMA-MARSHAL == NONE.
95 96
*/
96 97

  
97 98
/*
......
151 152

  
152 153
import com.goldencode.p2j.jmx.*;
153 154
import com.goldencode.p2j.persist.TemporaryBuffer.CopyTableMode;
155
import com.goldencode.p2j.persist.orm.*;
154 156
import com.goldencode.p2j.persist.serial.*;
155 157
import com.goldencode.p2j.security.*;
156 158
import com.goldencode.p2j.util.*;
......
673 675
                  wrapper = dsSrc.getDatasetWrapper().getTableWrapper(k - 1);
674 676
               }
675 677
               
678
               if (dsSrc.isRemoteParameter()  && !wrapper.isReceivedSchema())
679
               {
680
                  RecordBuffer rb = ((BufferReference) targetDmo).buffer();
681
                  DmoMeta meta = rb.getDmoInfo();
682
                  Iterator<Property> props = meta.getFields(false);
683
                  List<PropertyDefinition> pdl = new ArrayList<>();
684
                  props.forEachRemaining(p -> pdl.add(new PropertyDefinition(p)));
685
                  wrapper.setProperties(pdl);
686
               }
676 687
               TemporaryBuffer.insertAllRows(
677 688
                     wrapper,
678 689
                     (Temporary) targetDmo,
......
851 862
         {
852 863
            if (dsParam.isByReference() || dsParam.isRemoteParameter())
853 864
            {
865
               // check if all tables contain schema.
866
               if (!dsParam.getDatasetWrapper().getTableDefs().stream().
867
                        allMatch(DsTableDefinition::isReceivedSchema))
868
               {
869
                  // A NO-SCHEMA-MARSHAL table cannot be used as a parameter where the receiving side
870
                  // does not have a pre-prepared schema
871
                  ErrorManager.recordOrThrowError(12323);
872
               }
854 873
               // if [dsParam] is remote, the dataset was rehydrated when [dsParam] was created
855 874
               // do not copy now for 2nd time. Since it is an [input] param we can use the 
856 875
               // dataset handle directly.
......
3899 3918
      List<BufferImpl> localBuffers = new ArrayList<>(bufs.length);
3900 3919
      for (Buffer buf : bufs)
3901 3920
      {
3921
         if (buf == null)
3922
         {
3923
            continue;
3924
         }
3902 3925
         BufferImpl bufRef = ((BufferImpl) buf).ref();
3903 3926
         if (initClass == null)
3904 3927
         {
src/com/goldencode/p2j/persist/DataSetContainer.java 2022-11-11 09:10:40 +0000
2 2
** Module   : DataSetContainer.java
3 3
** Abstract : A container used to serialize a dataset and send it to a remote side. 
4 4
**
5
** Copyright (c) 2019-2021, Golden Code Development Corporation.
5
** Copyright (c) 2019-2022, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- ---------------------------------Description----------------------------------
8 8
** 001 OM  20190708 Created initial version.
......
10 10
**     CA  20190812 Added toString().
11 11
** 002 SVL 20210614 Added copyRows parameter.
12 12
**     SVL 20210701 Added clearRows.
13
** 003 IAS 20221111 Added 'xmlNodeName', 'nsURI', and 'nsPrefix' fields. 
13 14
*/
14 15

  
15 16
/*
......
92 93
   /** The definitions for all relations between the tables in the dataset. */
93 94
   private List<DsRelationDefinition> relationDefinitions = null;
94 95
   
96
   /** The XML namespace for this dataset. */
97
   private String xmlns = null;
98
   
99
   /** The XML prefix for this dataset. */
100
   private String xmlPrefix = null;
101
   
102
   /** The XML-NODE-NAME attribute for this dataset. */
103
   private String xmlNodeName = null;
104

  
95 105
   /**
96 106
    * Default c'tor, explicitly added to allow instances of this class to be created on 
97 107
    * deserialization. Not for public use.
......
257 267
      
258 268
      setStructureName(ds.name().toStringMessage());
259 269
      
270
      character tmp = ds.namespaceURI();
271
      this.xmlns = tmp.isUnknown() ? "" : tmp.toJavaType();
272
      tmp = ds.namespacePrefix();
273
      this.xmlPrefix = ds.namespacePrefix().toJavaType(); 
274
      tmp = ds.getXmlNodeName();
275
      this.xmlNodeName = ds.getXmlNodeName().toJavaType();
276
      
260 277
      // prepare relation data
261 278
      int relCnt = ds.getNumRelations().intValue();
262 279
      relationDefinitions = new ArrayList<>(relCnt);
......
276 293
   }
277 294

  
278 295
   /**
296
    * Get the XML namespace of the DATASET.
297
    * @return XML namespace of the DATASET
298
    */
299
   public String namespaceURI()
300
   {
301
      return xmlns;
302
   }
303

  
304
   /**
305
    * Get the XML prefix of the DATASET.
306
    * @return XML prefix of the DATASET
307
    */
308
   public String namespacePrefix()
309
   {
310
      return xmlPrefix;
311
   }
312

  
313
   /**
314
    * Get the XML node name of the DATASET.
315
    * @return XML node name of the DATASET
316
    */
317
   public String getXmlNodeName()
318
   {
319
      return xmlNodeName;
320
   }
321

  
322
   /**
279 323
    * Delete row data.
280 324
    */
281 325
   public void clearRows()
src/com/goldencode/p2j/persist/DataSetParameter.java 2022-11-11 09:17:33 +0000
39 39
**                  INPUT-OUTPUT mode, and the DATASET-HANDLE, DATASET, TABLE-HANDLE or TABLE versions.
40 40
**     CA  20220727 Fixed OO dataset/table parameters (at the method definition and method call) when there is
41 41
**                  an APPEND option.
42
**     IAS 20221108 Fixed support for SCHEMA-MARSHAL == NONE. Re-worked indexes (de)serialization.
43
**     IAS 20221111 Fixed support of relations' for SCHEMA-MARSHAL == NONE and issues with 
44
**                  processing 'schemaMarshalLevel', 'xmlNodeName', 'nsURI', and 'nsPrefix'. 
42 45
*/
43 46

  
44 47
/*
......
324 327
   {
325 328
      BufferManager.registerScopeable(null);
326 329
      
330
      this.originalDataSet = (DataSet)dsHandle.getResource();
327 331
      this.dataset = dsHandle;
328 332
      this.options = options; // TODO: check default value for mode if ParameterOption.NONE is passed in
329 333
      this.input   = input;
......
533 537
      DataSet.create(dataset);
534 538
      DataSet newDS = (DataSet) dataset.getResource();
535 539
      newDS.name(wrapper.getDatasetName());
540
      newDS.namespaceURI(wrapper.namespaceURI());
541
      newDS.namespacePrefix(wrapper.namespacePrefix());
542
      newDS.setXmlNodeName(wrapper.getXmlNodeName());
536 543
      
537 544
      List<DsTableDefinition> tableDefs = wrapper.getTableDefs();
545
      Set<String> tablesWithoutSchema = new HashSet<>();
538 546
      if (tableDefs != null && !tableDefs.isEmpty())
539 547
      {
540 548
         BufferImpl[] buffs = new BufferImpl[tableDefs.size()];
541 549
         for (int k = 0; k < tableDefs.size(); k++)
542 550
         {
543 551
            DsTableDefinition tableDef = tableDefs.get(k);
544
            
552
            if (!tableDef.isReceivedSchema())
553
            {
554
               tablesWithoutSchema.add(tableDef.getName());
555
               continue;
556
            }
545 557
            if (!tableDef.isBeforeTable())
546 558
            {
547 559
               Iterator<PropertyDefinition> props = tableDef.propertyIterator();
548 560
               String idx = tableDef.getIndexes();
549 561
               String xmlns = tableDef.getXmlns();
550 562
               String prefix = tableDef.getXmlPrefix();
551
               buffs[k] = TempTableBuilder.createRemoteTable(tableDef.getName(), props, idx, xmlns, prefix);
563
               List<IndexDefinition> indexDefs = tableDef.getIndexDefs();
564
               TempTableBuilder ttb = new TempTableBuilder(); 
565
               if (indexDefs != null)
566
               {
567
                  buffs[k] = ttb.createRemoteTable(tableDef.getName(), 
568
                           props, () -> indexDefs.stream().forEach(ix -> ix.addTo(ttb)), 
569
                           xmlns, prefix, tableDef.getSchemaMarshalLevel());
570
               }
571
               else
572
               {
573
                  buffs[k] = ttb.createRemoteTable(tableDef.getName(), 
574
                           props, idx, xmlns, prefix, tableDef.getSchemaMarshalLevel());
575
               }
552 576
               
553 577
               if (tableDef.isAfterTable() && tableDef.getPeerDef() != null)
554 578
               {
......
574 598
      {
575 599
         for (DsRelationDefinition relDef : relationsDefs)
576 600
         {
601
            if (tablesWithoutSchema.contains(relDef.getParentBuffer()) ||
602
                tablesWithoutSchema.contains(relDef.getChildBuffer()))
603
            {
604
               continue;
605
            }
577 606
            handle hRel = newDS.addRelation(
578 607
                  newDS.bufferHandle(relDef.getParentBuffer()),
579 608
                  newDS.bufferHandle(relDef.getChildBuffer()),
src/com/goldencode/p2j/persist/DatasetWrapper.java 2022-11-11 09:20:49 +0000
17 17
**                  (so that relations, schema, etc is done on the server-side).
18 18
**     CA  20221102 Added a static serialization ID - required when enabling AOP method tracing (see 
19 19
**                  p2j.aspects.ltw.MethodTraceAspect).
20
*/
21

  
20
**     IAS 20221108 Fixed support for SCHEMA-MARSHAL == NONE.
21
**     IAS 20221111 Added 'xmlNodeName', 'nsURI', and 'nsPrefix' fields and fixed 
22
**                  'schemaMarshalLevel' support.
22 23
/*
23 24
** This program is free software: you can redistribute it and/or modify
24 25
** it under the terms of the GNU Affero General Public License as
......
121 122
   /** The name of the DataSet. */
122 123
   private String dsName = null;
123 124
   
125
   /** The XML namespace for this dataset. */
126
   private String xmlns = null;
127
   
128
   /** The XML prefix for this dataset. */
129
   private String xmlPrefix = null;
130
   
131
   /** The XML-NODE-NAME attribute for this dataset. */
132
   private String xmlNodeName = null;
133

  
124 134
   /** Flag indicating if the source is a JSON dataset. */
125 135
   private boolean fromJson;
126 136
   
......
172 182
   public DatasetWrapper(DataSetContainer resource)
173 183
   {
174 184
      this.resource = resource;
185
      this.xmlns = resource.namespaceURI();
186
      this.xmlPrefix = resource.namespacePrefix();
187
      this.xmlNodeName = resource.getXmlNodeName();
175 188
   }
176 189

  
177 190
   /**
......
184 197
    */
185 198
   public DatasetWrapper(boolean fromJson, DataSetContainer resource)
186 199
   {
187
      this.resource = resource;
200
      this(resource);
188 201
      this.fromJson = fromJson;
189 202
   }
190 203
   
......
260 273
   {
261 274
      return resource;
262 275
   }
276

  
277
   /**
278
    * Get the XML namespace of the DATASET.
279
    * @return XML namespace of the DATASET
280
    */
281
   public String namespaceURI()
282
   {
283
      return xmlns;
284
   }
285

  
286
   /**
287
    * Get the XML prefix of the DATASET.
288
    * @return XML prefix of the DATASET
289
    */
290
   public String namespacePrefix()
291
   {
292
      return xmlPrefix;
293
   }
294

  
295
   /**
296
    * Get the XML node name of the DATASET.
297
    * @return XML node name of the DATASET
298
    */
299
   public String getXmlNodeName()
300
   {
301
      return xmlNodeName;
302
   }
263 303
   
264 304
   /**
265 305
    * Returns the list of table definitions for the temp-tables from this {@code DataSet}.
......
437 477

  
438 478
         writeString(out, dsName);
439 479
      }
480
      writeString(out, xmlns);
481
      writeString(out, xmlPrefix);
482
      writeString(out, xmlNodeName);
440 483
      
441 484
      // write properties
442 485
      if (resource != null)
......
504 547
      }
505 548
      
506 549
      dsName = readString(in);
550
      xmlns = readString(in);
551
      xmlPrefix = readString(in);
552
      xmlNodeName = readString(in);
507 553
      
508 554
      int n = in.readInt(); 
509 555
      if (n != 0)
......
566 612
      {
567 613
         TableWrapper tw = new TableWrapper(fromJson, res);
568 614
         tw.setTableName(tdef.getName());
615
         tw.setSchemaMarshalLevel(tdef.getSchemaMarshalLevel());
569 616
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
570 617
         ObjectOutputStream oos = new ObjectOutputStream(baos);
571 618
         tw.writeExternal(oos);
572 619
         oos.close();
573 620
         tw = new TableWrapper();
574 621
         tw.readExternal(new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())));
575
         
622
         tw.receivedSchema = tdef.receivedSchema;
576 623
         if (bres != null)
577 624
         {
578 625
            TableWrapper btw = new TableWrapper(bres);
src/com/goldencode/p2j/persist/DsTableDefinition.java 2022-11-11 11:52:54 +0000
2 2
** Module   : DsTableDefinition.java
3 3
** Abstract : A container for a DataSet Table metadata.
4 4
**
5
** Copyright (c) 2019-2021, Golden Code Development Corporation.
5
** Copyright (c) 2019-2022, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
8 8
** 001 OM  20130708 Created initial version.
......
20 20
**     OM  20210309 Do not use DmoMeta as key in TableMapper because temp-tables share the same DmoMeta.
21 21
**     SVL 20210614 Added copyRows parameter.
22 22
**     SVL 20210701 Added clearRows.
23
**     IAS 20221108 Fixed support for SCHEMA-MARSHAL == NONE. Re-worked (de)serialization.
24
**     IAS 20221111 Fixed 'schemaMarshalLevel', 'xmlNodeName', 'nsURI', and 'nsPrefix' support.
23 25
*/
24 26

  
25 27
/*
......
79 81

  
80 82
import java.io.*;
81 83
import java.util.*;
84
import java.util.stream.*;
85

  
82 86
import com.goldencode.p2j.util.*;
83 87
import static com.goldencode.p2j.persist.AbstractTempTable.*;
84 88
import static com.goldencode.util.NativeTypeSerializer.*;
......
90 94
public class DsTableDefinition
91 95
implements Externalizable
92 96
{
97
   /** Flag indicating that table schema was received */  
98
   boolean receivedSchema = false;
99

  
93 100
   /** The name of this table. */
94 101
   private String name;
95 102
   
......
126 133
   /** The ERROR-STRING attribute for this table definition. */
127 134
   private String errorString = null;
128 135
   
136
   /** List of indexes' descriptors */
137
   private List<IndexDefinition> indexDefs = null;
138

  
129 139
   /**
130 140
    * A string with all indexes of this table definition encoded as a {@code String}.
131 141
    * 
......
136 146
   
137 147
   /**
138 148
    * The SCHEMA-MARSHAL level for the serialized temp-table. It is never {@code SM_DEFAULT} when object is to
139
    * be serialized. Always {@code SM_DEFAULT} for a read object.
149
    * be serialized. 
140 150
    */
141
   private final int schemaMarshalLevel;
151
   private int schemaMarshalLevel;
142 152
   
143 153
   /**
144 154
    * Default c'tor, explicitly added to allow instances of this class to be created on 
......
186 196
      switch (sml)
187 197
      {
188 198
         case SM_FULL:
199
         case SM_MIN:
200
            this.errorString = defBuff.errorString().toStringMessage();
201
            // no break, fall through
189 202
         case SM_DEFAULT:
190 203
            // full table schema is serialized with table parameter
204
            character tmp = parentTable.namespaceURI(); 
205
            this.xmlns = tmp.isUnknown() ? "" : tmp.toJavaType(); 
206
            this.xmlPrefix = parentTable.namespacePrefix().toJavaType(); 
207
            this.xmlNodeName = parentTable.namespacePrefix().toJavaType();
191 208
            this.indexes = TableMapper.getLegacyIndexInfo(parentTable);
192 209
            this.numIndexes = this.indexes.split("\\.").length;
193
            this.xmlns = parentTable.namespaceURI().toStringMessage();
194
            this.xmlPrefix = parentTable.namespacePrefix().toStringMessage();
195
            this.xmlNodeName = parentTable.getXmlNodeName().toStringMessage();
196
            // no break, fall through
197
            
198
         case SM_MIN:
199
            // marshals:
200
            //    field names, data types, and extents;
201
            //    temp-table ERROR-STRING
202
            // does NOT marshal:
203
            //    index descriptions
204
            //    field information (label, help, field validation expression, and so on (?))
205
            this.errorString = defBuff.errorString().toStringMessage();
210
            this.indexDefs = TableMapper.getLegacyIndexes(parentTable).map(lif -> new IndexDefinition(lif)).
211
                     collect(Collectors.toList());
206 212
            // no break, fall through
207 213
         
208 214
         case SM_NONE:
......
267 273
   }
268 274
   
269 275
   /**
276
    * The SCHEMA-MARSHAL level for the serialized temp-table. 
277
    */
278
   public int getSchemaMarshalLevel()
279
   {
280
      return schemaMarshalLevel;
281
   }
282
   
283
   /**
270 284
    * Sets the name of this table.
271 285
    *
272 286
    * @param   name
......
277 291
      this.name = name;
278 292
   }
279 293
   
294
   /** 
295
    * Check that table schema was received.
296
    * 
297
    * @return <code>true</code> if table schema was received.
298
    */
299
   public boolean isReceivedSchema() 
300
   {
301
      return receivedSchema;
302
   }
303

  
280 304
   /**
281 305
    * Check whether this is a definition of an AFTER-TABLE.
282 306
    * 
......
386 410
   }
387 411
   
388 412
   /**
413
    * Get List of indexes' descriptors.
414
    * @return the List of indexes' descriptors.
415
    */
416
   public List<IndexDefinition> getIndexDefs()
417
   {
418
      return indexDefs;
419
   }
420

  
421
   /**
389 422
    * Sets the XML namespace for this table definition.
390 423
    * 
391 424
    * @param   xmlns
......
502 535
               "A custom result set must not be specified when calling this method!");
503 536
      }
504 537
      
505
      return new ArrayList<>(properties);
538
      return properties != null ? new ArrayList<>(properties) : Collections.emptyList();
506 539
   }
507 540
   
508 541
   /**
......
562 595
   public final void writeExternal(ObjectOutput out)
563 596
   throws IOException
564 597
   {
598
      boolean writeSchema = schemaMarshalLevel != SM_NONE;
599
      out.writeByte(schemaMarshalLevel);
565 600
      writeString(out, name);
566 601
      out.writeByte(tableType);
567
      out.writeByte(numIndexes);
568
      writeString(out, indexes);
569
      writeString(out, xmlns);
570
      writeString(out, xmlPrefix);
571
      writeString(out, xmlNodeName);
572
      writeString(out, errorString);
573
      
574
      // write properties as a byte(1) separated list, ended with a byte(0)
575
      Set<Integer> blobProps = null;
602
      if (writeSchema)
603
      {
604
         out.writeByte(numIndexes);
605
         writeString(out,indexes);
606
         writeList(out, indexDefs);
607
         writeString(out,xmlns);
608
         writeString(out,xmlPrefix);
609
      }
610

  
611
      // write properties
612
      Set<Integer> blobProps = new HashSet<>();
613
      Set<Integer> objectProps = new HashSet<>();
576 614
      if (resultSet != null)
577 615
      {
578 616
         int idx = 0;
579 617
         while (resultSet.hasMoreProperties())
580 618
         {
581 619
            PropertyDefinition property = resultSet.nextProperty();
582
            property.setMarshalLevel(schemaMarshalLevel);
583
            out.writeByte(1);
584
            property.writeExternal(out);
585
            
620
            if (writeSchema)
621
            {
622
               property.setMarshalLevel(schemaMarshalLevel);
623
               out.writeByte(1);
624
               property.writeExternal(out);
625
            }
626

  
586 627
            if (property.getType() == blob.class)
587 628
            {
588
               if (blobProps == null)
589
               {
590
                  blobProps = new HashSet<>();
591
               }
592 629
               blobProps.add(idx);
593 630
            }
631
            else if (object.class.isAssignableFrom(property.getType()))
632
            {
633
               objectProps.add(idx);
634
            }
594 635
            idx = idx + 1;
595 636
         }
596 637
      }
597
      out.writeByte(0);
638
      if (writeSchema)
639
      {
640
         out.writeByte(0);
641
      }
642
      writeIntSet(out, blobProps);
643
      writeIntSet(out, objectProps);
598 644
      
599 645
      // write data 
600 646
      if (resultSet != null)
......
647 693
   throws IOException,
648 694
          ClassNotFoundException
649 695
   {
696
      schemaMarshalLevel = in.readByte(); 
697
      receivedSchema = schemaMarshalLevel != SM_NONE;
650 698
      name = readString(in);
651 699
      tableType = in.readByte();
652
      numIndexes = in.readByte();
653
      indexes = readString(in);
654
      xmlns = readString(in);
655
      xmlPrefix = readString(in);
656
      xmlNodeName = readString(in);
657
      errorString = readString(in);
658
      
659
      // read meta info separated by byte(1). The list ends with a byte(0).
660
      properties = new ArrayList<>();
661
      Set<Integer> blobProps = null;
662
      int idx = 0;
663
      boolean moreProperties = (in.readByte() == 1); 
664
      while (moreProperties) 
700
      if (receivedSchema)
665 701
      {
666
         PropertyDefinition pd = new PropertyDefinition();
667
         pd.readExternal(in);
668
         properties.add(pd);
669
         
670
         // check if there are more to read:
671
         moreProperties = (in.readByte() == 1);
672

  
673
         if (pd.getType() == blob.class)
702
         numIndexes = in.readByte();
703
         indexes = readString(in);
704
         indexDefs = readList(in, () -> new IndexDefinition());
705
         xmlns = readString(in);
706
         xmlPrefix = readString(in);
707
         properties = new ArrayList<>();
708
         while (in.readByte() != 0)
674 709
         {
675
            if (blobProps == null)
676
            {
677
               blobProps = new HashSet<>();
678
            }
679
            blobProps.add(idx);
710
            PropertyDefinition pd = new PropertyDefinition();
711
            pd.readExternal(in);
712
            properties.add(pd);
713
            
680 714
         }
681
         idx = idx + 1;
682 715
      }
683 716
      
717
      Set<Integer> blobProps = readIntSet(in);
718
      Set<Integer> objectProps = readIntSet(in);
719
      
684 720
      // read data
685 721
      rows = new ArrayList<>();
686 722
      rowsMeta = new ArrayList<>();
src/com/goldencode/p2j/persist/DynamicTablesHelper.java 2022-11-02 07:54:50 +0000
79 79
**     OM  20220914 Use MAX-WIDTH to generate custom sized varchar columns.
80 80
**     IAS 20221006 Added RAW type to the switch in the 'generateSchemaAst'.
81 81
**     IAS 20221013 Fixed setting of "serialize-name" and "serialize-hidden annotations".
82
**     IAS 20221014 Fixed 'column-codepage' support.
82 83
*/
83 84

  
84 85
/*
......
831 832
         {
832 833
            tableField.putAnnotation("col_lab", field.getColumnLabel());
833 834
         }
834
         
835
         if (field.getCodePage() != null)
835
         String cp = field.getCodePage();
836
         if (cp != null && !cp.trim().equals(""))
836 837
         {
837
            tableField.putAnnotation("codePage", field.getCodePage());
838
            tableField.putAnnotation("column-codepage", cp);
838 839
         }
839 840

  
840 841
         if (field.isSerializeHidden())
src/com/goldencode/p2j/persist/IndexDefinition.java 2022-11-04 14:40:16 +0000
1
/*
2
** Module   : IndexDefinition.java
3
** Abstract : A container for a table index metadata.
4
**
5
** Copyright (c) 2022, Golden Code Development Corporation.
6
**
7
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
8
** 001 IAS 20221104 Created initial version.
9
*/
10

  
11
/*
12
** This program is free software: you can redistribute it and/or modify
13
** it under the terms of the GNU Affero General Public License as
14
** published by the Free Software Foundation, either version 3 of the
15
** License, or (at your option) any later version.
16
**
17
** This program is distributed in the hope that it will be useful,
18
** but WITHOUT ANY WARRANTY; without even the implied warranty of
19
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
** GNU Affero General Public License for more details.
21
**
22
** You may find a copy of the GNU Affero GPL version 3 at the following
23
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
24
** 
25
** Additional terms under GNU Affero GPL version 3 section 7:
26
** 
27
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
28
**   terms apply to the works covered under the License.  These additional terms
29
**   are non-permissive additional terms allowed under Section 7 of the GNU
30
**   Affero GPL version 3 and may not be removed by you.
31
** 
32
**   0. Attribution Requirement.
33
** 
34
**     You must preserve all legal notices or author attributions in the covered
35
**     work or Appropriate Legal Notices displayed by works containing the covered
36
**     work.  You may not remove from the covered work any author or developer
37
**     credit already included within the covered work.
38
** 
39
**   1. No License To Use Trademarks.
40
** 
41
**     This license does not grant any license or rights to use the trademarks
42
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
43
**     of Golden Code Development Corporation. You are not authorized to use the
44
**     name Golden Code, FWD, or the names of any author or contributor, for
45
**     publicity purposes without written authorization.
46
** 
47
**   2. No Misrepresentation of Affiliation.
48
** 
49
**     You may not represent yourself as Golden Code Development Corporation or FWD.
50
** 
51
**     You may not represent yourself for publicity purposes as associated with
52
**     Golden Code Development Corporation, FWD, or any author or contributor to
53
**     the covered work, without written authorization.
54
** 
55
**   3. No Misrepresentation of Source or Origin.
56
** 
57
**     You may not represent the covered work as solely your work.  All modified
58
**     versions of the covered work must be marked in a reasonable way to make it
59
**     clear that the modified work is not originating from Golden Code Development
60
**     Corporation or FWD.  All modified versions must contain the notices of
61
**     attribution required in this license.
62
*/
63

  
64

  
65
package com.goldencode.p2j.persist;
66

  
67
import static com.goldencode.util.NativeTypeSerializer.*; 
68
import java.io.*;
69
import java.util.*;
70
import java.util.stream.*;
71

  
72
import com.goldencode.p2j.persist.TableMapper.*;
73
import com.goldencode.p2j.util.*;
74

  
75
/**
76
 * Container for a table index metadata. Used to send the metadata of a
77
 * DMO to a remote side, when remote appserver calls are involved.
78
 */
79
public class IndexDefinition
80
implements Externalizable
81
{
82
   /** The legacy name of this index. */
83
   private String legacyName;
84
   
85
   /**
86
    * Determine if the index is a primary index: the one with the "primary" annotation or, if
87
    * there is no such one, the first in the definition order.
88
    */
89
   private boolean effectivePrimary;
90
   
91
   /** Determine if the index is an unique index. */
92
   private boolean unique;
93
   
94
   /** Determine if the index is a word-index index. */
95
   private boolean word;
96
   
97
   /** Index components (fields with sorting directions). */
98
   private List<IndexComponentDefinition> components;
99

  
100
   /**
101
    * Default c'tor
102
    */
103
   public IndexDefinition()
104
   {
105
      
106
   }
107

  
108
   /**
109
    * Constructor 
110
    * @param lii
111
    *        ORM index info
112
    *        
113
    */
114
   public IndexDefinition(LegacyIndexInfo lii)
115
   {
116
      this.legacyName = lii.getLegacyName();
117
      this.effectivePrimary = lii.isEffectivePrimary();
118
      this.unique = lii.isUnique();
119
      this.word = lii.isWord();
120
      this.components = lii.indexComponents().map(lici -> new IndexComponentDefinition(lici)).
121
                                              collect(Collectors.toList());
122
   }
123
   
124
   /**
125
    * Add index to the <code>TableBuilder</code>
126
    * @param tb
127
    *        <code>TableBuilder</code> instance.
128
    */
129
   public void addTo(TempTableBuilder tb)
130
   {
131
      
132
      tb.addNewIndex(new character(legacyName),
133
                     new logical(unique),
134
                     new logical(effectivePrimary),
135
                     new logical(word));
136
      components.stream().forEach(
137
               c -> tb.addFieldToIndex(legacyName, 
138
                                       c.fieldLegacyName, 
139
                                       c.effectiveDescending ? "desc" : "asc"));
140
   }
141
   
142
   /**
143
    * Read the index definition from the specified input source.
144
    * 
145
    * @param    in
146
    *           The input source from which the index definition will be read.
147
    *
148
    * @throws   IOException
149
    *           In case of I/O errors.
150
    *
151
    * @throws  ClassNotFoundException
152
    *          If the class of property could not be found/loaded.
153
    */
154
   @Override
155
   public void readExternal(ObjectInput in) 
156
   throws IOException, 
157
          ClassNotFoundException
158
   {
159
      legacyName = readString(in);
160
      byte flags = in.readByte();
161
      effectivePrimary = (flags & 1) != 0;
162
      unique = (flags & 2) != 0;
163
      word = (flags & 4) != 0;
164
      components = readList(in, () -> new IndexComponentDefinition());
165
   }
166

  
167
   /**
168
    * Send the index definition to the specified output destination.
169
    * 
170
    * @param    out
171
    *           The output destination to which the index definition will be sent.
172
    *
173
    * @throws   IOException
174
    *           In case of I/O errors.
175
    */
176
   @Override
177
   public void writeExternal(ObjectOutput out) 
178
   throws IOException
179
   {
180
      writeString(out, legacyName);
181
      out.writeByte((effectivePrimary ? 1 : 0) | (unique ? 2 : 0) | (word ? 1 : 0));
182
      writeList(out, components);
183
   }
184

  
185
   /** A container with an index component information. */
186
   public static class IndexComponentDefinition
187
   implements Externalizable
188
   {
189
      /** The legacy name of the field participating in the index. */
190
      private String fieldLegacyName;
191
      
192
      /** Determines if this component has descending sorting. */
193
      private boolean effectiveDescending;
194
      
195
      /**
196
       * Default c'tor
197
       */
198
      public IndexComponentDefinition()
199
      {
200
         
201
      }
202
      /**
203
       * Constructor
204
       * @param lici
205
       *        DMO ORM index component info.
206
       */
207
      public IndexComponentDefinition(LegacyIndexComponentInfo lici)
208
      {
209
         this.fieldLegacyName = lici.fieldLegacyName;
210
         this.effectiveDescending = lici.effectiveDescending;
211
      }
212
      
213

  
214
      
215
      /**
216
       * Read the index definition from the specified input source.
217
       * 
218
       * @param    in
219
       *           The input source from which the index component definition will be read.
220
       *
221
       * @throws   IOException
222
       *           In case of I/O errors.
223
       *
224
       * @throws  ClassNotFoundException
225
       *          If the class of property could not be found/loaded.
226
       */
227
      @Override
228
      public void readExternal(ObjectInput in) 
229
      throws IOException, 
230
             ClassNotFoundException
231
      {
232
         fieldLegacyName = readString(in);
233
         effectiveDescending = in.readByte() != 0;
234
      }
235

  
236
      /**
237
       * Send the index definition to the specified output destination.
238
       * 
239
       * @param    out
240
       *           The output destination to which the index component definition will be sent.
241
       *
242
       * @throws   IOException
243
       *           In case of I/O errors.
244
       */
245
      @Override
246
      public void writeExternal(ObjectOutput out) 
247
               throws IOException
248
      {
249
         writeString(out, fieldLegacyName);
250
         out.writeByte(effectiveDescending ? 1 : 0);
251
      }
252
   }
253
}
src/com/goldencode/p2j/persist/PropertyDefinition.java 2022-11-11 11:51:27 +0000
17 17
**     SVL 20201030 Added format, label and columnLabel fields.
18 18
**     OM  20201120 Added SCHEMA-MARSHAL implementation.
19 19
**     CA  20220909 Always marshal the schema, otherwise the remote side will not be able to rebuild the table.
20
**     IAS 20221029 Added support for missed properties.
21
**     IAS 20221102 Re-worked serialization for SCHEMA-MARSHAL == NONE.
20 22
*/
21 23

  
22 24
/*
......
76 78

  
77 79
import java.io.*;
78 80
import java.util.*;
81

  
82
import com.goldencode.p2j.persist.orm.*;
83
import com.goldencode.p2j.util.*;
84

  
79 85
import static com.goldencode.p2j.persist.AbstractTempTable.*;
80 86
import static com.goldencode.util.NativeTypeSerializer.*; 
81 87

  
......
117 123
   
118 124
   /** The column label of this property. */
119 125
   private String columnLabel;
120
   
126

  
127
   /** HELP attribute of this field. */
128
   private String help;
129
   
130
   /** INITIAL attribute of this field. */
131
   private String initial;
132

  
133
   /** Flag indicating the field should not be included in serialized output. */
134
   private boolean serializeHidden;
135
   
136
   /** Flag indicating the field is case-sensitive. */
137
   private boolean caseSensitive;
138

  
139
   /** Node type of field in XML output. */
140
   private String xmlNodeType;
141
   
142
   /** Code page of the CLOB field. */
143
   private String codePage;
144

  
121 145
   /**
122 146
    * The SCHEMA-MARSHAL level for the parent  temp-table. It is never {@code SM_DEFAULT} when object is to
123 147
    * be serialized. Always {@code SM_DEFAULT} for a read object.
......
303 327
      this.label = label;
304 328
      this.columnLabel = columnLabel;
305 329
   }
306
   
330

  
331
   /**
332
    * Create a new property definition.
333
    *
334
    * @param    prop
335
    *           The ORM field <code>Property</code>.
336
    */           
337
   public PropertyDefinition(Property prop)
338
   {
339
      this.name = prop.name;
340
      verifyType(prop._fwdType);
341
      this.type = prop._fwdType;
342
      int extent = prop.index > 0 ? 0 : prop.extent;
343
      this.extent = extent == 0 ? NO_EXTENT : extent;
344
      this.legacyName = prop.legacy;
345
      this.format = prop.format;
346
      this.label = prop.label;
347
      this.columnLabel = prop.columnLabel;
348
      this.help = prop.help;
349
      this.initial = prop.initial;
350
      this.serializeHidden = prop.serializeHidden;
351
      this.caseSensitive = prop.caseSensitive;
352
      this.xmlNodeType = prop.xmlNodeType;
353
      this.codePage = prop.codePage;
354
   }
307 355
   /**
308 356
    * Get the type of this property.
309 357
    * 
......
385 433
   }
386 434

  
387 435
   /**
436
    * Get help text of this property.
437
    *
438
    * @return help text of this property.
439
    */
440
   public String getHelp()
441
   {
442
      return help;
443
   }
444

  
445
   /**
446
    * Get initial value of this property.
447
    *
448
    * @return initial value of this property.
449
    */
450
   public String getInitial()
451
   {
452
      return initial;
453
   }
454

  
455
   /**
456
    * Get 'serialize hidden' flag of this property.
457
    *
458
    * @return 'serialize hidden' flag of this property.
459
    */
460
   public boolean isSerializeHidden()
461
   {
462
      return serializeHidden;
463
   }
464

  
465
   /**
466
    * Get 'case-sensitive' flag of this property.
467
    *
468
    * @return 'case-sensitive' flag of this property.
469
    */
470
   public boolean isCaseSensitive()
471
   {
472
      return caseSensitive;
473
   }
474

  
475
   
476
   /**
477
    * Get XML node type of this property.
478
    *
479
    * @return XML node type of this property.
480
    */
481
   public String getXmlNodeType()
482
   {
483
      return xmlNodeType;
484
   }
485

  
486
   /**
487
    * Get code page of this property.
488
    *
489
    * @return code page of this property.
490
    */
491
   public String getCodePage()
492
   {
493
      return codePage;
494
   }
495

  
496
   /**
388 497
    * Send the property definition to the specified output destination.
389 498
    * 
390 499
    * @param    out
......
396 505
   public final void writeExternal(ObjectOutput out)
397 506
   throws IOException
398 507
   {
508
      if (schemaMarshalLevel == SM_NONE)
509
      {
510
         throw new IllegalStateException("Should not be called if schemaMarshalLevel == SM_NONE");
511
      }
399 512
      boolean full = schemaMarshalLevel == SM_FULL || schemaMarshalLevel == SM_DEFAULT;
400
      // we can't omit the schema-related field information, as otherwise the remote side will not be able to
401
      // recreate the temp-table.
402
      boolean none = false; // schemaMarshalLevel == SM_NONE;
403 513
      
404
      writeString(out, none ? null : name);
405
      writeString(out, (type == null || none) ? null : type.getName());
406
      out.writeInt(none ? 0 : extent);
407
      writeString(out, none ? null : legacyName);
408
      writeString(out, full ? format : null);
409
      writeString(out, full ? label : null);
410
      writeString(out, full ? columnLabel : null);
514
      writeString(out, name);
515
      writeString(out, legacyName);
516
      writeString(out, type == null ? null : type.getName());
517
      out.writeInt(extent);
518
      writeString(out, initial);
519
      writeString(out, xmlNodeType);
520
      writeString(out, codePage);
521
      int flags = (serializeHidden ? 1 : 0) | (caseSensitive ? 2 : 0) | (full ? 4 : 0);
522
      out.writeByte(flags);
523
      if (!full )
524
      {
525
         return;
526
      }
527
      writeString(out, format);
528
      writeString(out, label);
529
      writeString(out, columnLabel);
530
      writeString(out, help);
411 531
   }
412 532
   
413 533
   /**
......
427 547
          ClassNotFoundException
428 548
   {
429 549
      name = readString(in);
550
      legacyName = readString(in);
430 551
      String tn = readString(in);
431 552
      type = (tn == null) ? null : Class.forName(tn);
432 553
      extent = in.readInt();
433
      legacyName = readString(in);
554
      initial = readString(in);
555
      xmlNodeType = readString(in);
556
      codePage = readString(in);
557
      int flags = in.readByte();
558
      serializeHidden = (flags & 1) != 0;
559
      caseSensitive = (flags & 2) != 0;
560
      boolean full = (flags & 4) != 0;
561
      if (!full)
562
      {
563
         return;
564
      }
434 565
      format = readString(in);
435 566
      label = readString(in);
436 567
      columnLabel = readString(in);
568
      help = readString(in);
437 569
   }
438 570
   
439 571
   /**
src/com/goldencode/p2j/persist/TableMapper.java 2022-11-11 09:28:43 +0000
102 102
**     CA  20220601 getIndexFieldNames must return lowercased legacy names.
103 103
**     OM  20220914 Added MAX-WIDTH support for CHARACTER fields.
104 104
**     IAS 20221006 Added 'definedFormat' and 'definedLabel'.
105
**     IAS 20221018 Fixed processing of 'now' and 'today' INITIAL attribute value.
105 106
**     CA  20221031 Added JMX instrumentation for 'mapTemporaryTable'.
107
**     IAS 20222204 Added 'indexComponents()' and 'getLegacyIndexes' methods.
108
**     IAS 20221111 Minor cleanup of the LegacyFieldInfo c'tor.
106 109
*/
107 110

  
108 111
/*
......
163 166
import java.lang.reflect.*;
164 167
import java.util.*;
165 168
import java.util.concurrent.*;
169
import java.util.stream.Stream;
166 170

  
167 171
import com.goldencode.p2j.persist.annotation.*;
168 172
import com.goldencode.p2j.persist.annotation.Trigger;
......
788 792
   }
789 793
   
790 794
   /**
795
    * Get stream for the indexes associated with the given temporary table.
796
    *
797
    * @param    tt
798
    *           Temp table object.
799
    * @return   stream for the indexes associated with the given temporary table.
800
    */
801
   public static Stream<TableMapper.LegacyIndexInfo> getLegacyIndexes(TempTable tt)
802
   {
803
      TempTableMapper mapper = locateTemp(tt);
804
      
805
      synchronized (mapper)
806
      {
807
         return mapper.legacyIndexInfo(tt);
808
      }
809
   }
810
   /**
791 811
    * Get information about the index associated with the DMO referenced by the given buffer,
792 812
    * as a string.
793 813
    *
......
2663 2683
      }
2664 2684
      
2665 2685
      /**
2686
       * Get stream for the indexes associated with the given temporary table.
2687
       *
2688
       * @param    tt
2689
       *           Temp table object.
2690
       * @return   stream for the indexes associated with the given temporary table.
2691
       */
2692
      private Stream<LegacyIndexInfo> legacyIndexInfo(TempTable tt)
2693
      {
2694
         LegacyTableInfo tableInfo = p2j.get(tt);
2695
         return new ArrayList<>(tableInfo.idx).stream();
2696
      }
2697

  
2698
      /**
2666 2699
       * Get the legacy index name of converted index, which is defined by the specified backing
2667 2700
       * temp table.
2668 2701
       *
......
2882 2915
                  {
2883 2916
                     if ("today".equalsIgnoreCase(text))
2884 2917
                     {
2885
                        initialValue = date.today();
2918
                        initialValue = new character(text);
2886 2919
                     }
2887 2920
                     else
2888 2921
                     {
......
2893 2926
                  {
2894 2927
                     if ("now".equalsIgnoreCase(text))
2895 2928
                     {
2896
                        initialValue = datetime.now();
2929
                        initialValue = new character(text);
2897 2930
                     }
2898 2931
                     else if (text.toUpperCase().indexOf('T') > 0)
2899 2932
                     {
......
2910 2943
                  {
2911 2944
                     if ("now".equalsIgnoreCase(text))
2912 2945
                     {
2913
                        initialValue = datetimetz.now();
2946
                        initialValue = new character(text);
2914 2947
                     }
2915 2948
                     else if (text.toUpperCase().indexOf('T') > 0)
2916 2949
                     {
......
3118 3151
      }
3119 3152
      
3120 3153
      /**
3154
       * Get a stream for the index components.
3155
       * 
3156
       * @return iterator for the index components.
3157
       */
3158
      public Stream<LegacyIndexComponentInfo> indexComponents()
3159
      {
3160
         return Arrays.stream(components);
3161
      }
3162
      /**
3121 3163
       * Returns index information as a string. Format of this string is described in
3122 3164
       * {@link Buffer#indexInformation(int)}
3123 3165
       *
......
3216 3258
   static class LegacyIndexComponentInfo
3217 3259
   {
3218 3260
      /** The legacy name of the field participating in the index. */
3219
      private final String fieldLegacyName;
3261
      public final String fieldLegacyName;
3220 3262
      
3221 3263
      /** Determines if this component has descending sorting. */
3222
      private final boolean effectiveDescending;
3264
      public final boolean effectiveDescending;
3223 3265
      
3224 3266
      /**
3225 3267
       * Create a new index component information container, holding field name and sorting
......
3546 3588
         else
3547 3589
         {
3548 3590
            this.format = defaultFormat;
3591
            this.definedFormat = null;
3549 3592
         }
3550 3593
         
3551 3594
         this.dataType = dataType;
src/com/goldencode/p2j/persist/TableWrapper.java 2022-11-11 12:09:56 +0000
28 28
**                  (so that relations, schema, etc is done on the server-side).
29 29
**     CA  20220428 Allow null peerDef at setPeerDef.
30 30
**     CA  20220602 Added basic support for transport of object instances over appserver call.
31
**     IAS 20221029 Added support for the SCHEMA-MARSHAL attribute.
32
**     IAS 20221102 Re-worked (de)serialization.
33
**     IAS 20221104 Added structured indexes data.
34
**     IAS 20221111 Fixed 'schemaMarshalLevel' support.
31 35
*/
32 36

  
33 37
/*
......
86 90
package com.goldencode.p2j.persist;
87 91

  
88 92
import static com.goldencode.util.NativeTypeSerializer.*; 
93
import static com.goldencode.p2j.persist.AbstractTempTable.*;
94

  
89 95
import java.io.*;
90 96
import java.lang.reflect.Array;
91 97
import java.util.*;
98
import java.util.stream.*;
92 99

  
100
import com.goldencode.p2j.oo.lang.*;
93 101
import com.goldencode.p2j.util.*;
102
import com.goldencode.util.*;
94 103

  
95 104
/**
96 105
 * Any {@link TableResultSet} instance will be wrapped in a {@link TableWrapper} instance before
......
122 131

  
123 132
   /** Table name. */
124 133
   private String tableName;
134
   
135
   /** Flag indicating that table schema was received */  
136
   boolean receivedSchema = false;
137
   
138
   /** Table SCHEMA-MARSHAL attribute value encodes as int */ 
139
   private int schemaMarshalLevel;
125 140

  
126 141
   /**
127 142
    * Determines if this wrapper wraps data from a TABLE-HANDLE parameter. Necessary because of
......
159 174
    */
160 175
   private String indexes = null;
161 176

  
177
   /** List of indexes' descriptors */
178
   private List<IndexDefinition> indexDefs = null;
179
   
162 180
   /** Flag indicating if the source is a JSON table. */
163 181
   private boolean fromJson = false;
164 182
   
......
423 441
   }
424 442
   
425 443
   /**
444
    * Get List of indexes' descriptors.
445
    * @return the List of indexes' descriptors.
446
    */
447
   public List<IndexDefinition> getIndexDefs()
448
   {
449
      return indexDefs;
450
   }
451

  
452
   /**
426 453
    * Get the {@link #xmlns XML namespace}.
427 454
    * 
428 455
    * @return   See above.
......
573 600
           "A custom result set must not be specified when calling this method!");
574 601
      }
575 602

  
576
      return new ArrayList<PropertyDefinition>(properties);
603
      return properties != null ? new ArrayList<PropertyDefinition>(properties) : 
604
                                 Collections.emptyList();
577 605
   }
578 606

  
579 607
   /**
......
682 710
         return;
683 711
      }
684 712

  
685
      writeString(out, tableName);
686
      out.writeByte(tableType);
687
      out.writeByte(numIndexes);
688
      writeString(out,indexes);
689
      writeString(out,xmlns);
690
      writeString(out,xmlPrefix);
713
      boolean writeSchema = schemaMarshalLevel != SM_NONE;
714
      out.writeByte(schemaMarshalLevel);
715
      if (writeSchema)
716
      {
717
         writeString(out, tableName);
718
         out.writeByte(tableType);
719
         out.writeByte(numIndexes);
720
         writeString(out,indexes);
721
         writeList(out, indexDefs);
722
         writeString(out,xmlns);
723
         writeString(out,xmlPrefix);
724
      }
691 725

  
692 726
      // write properties
693
      Set<Integer> blobProps = null;
694
      Set<Integer> objectProps = null;
727
      Set<Integer> blobProps = new HashSet<>();
728
      Set<Integer> objectProps = new HashSet<>();
695 729
      if (resultSet != null)
696 730
      {
697 731
         int idx = 0;
698 732
         while (resultSet.hasMoreProperties())
699 733
         {
700 734
            PropertyDefinition property = resultSet.nextProperty();
701
            out.writeByte(1);
702
            property.writeExternal(out);
735
            if (writeSchema)
736
            {
737
               property.setMarshalLevel(schemaMarshalLevel);
738
               out.writeByte(1);
739
               property.writeExternal(out);
740
            }
703 741

  
704 742
            if (property.getType() == blob.class)
705 743
            {
706
               if (blobProps == null)
707
               {
708
                  blobProps = new HashSet<>();
709
               }
710 744
               blobProps.add(idx);
711 745
            }
712 746
            else if (object.class.isAssignableFrom(property.getType()))
713 747
            {
714
               if (objectProps == null)
715
               {
716
                  objectProps = new HashSet<>();
717
               }
718 748
               objectProps.add(idx);
719 749
            }
720 750
            idx = idx + 1;
721 751
         }
722 752
      }
723
      out.writeByte(0);
724
   
753
      if (writeSchema)
754
      {
755
         out.writeByte(0);
756
      }
757
      writeIntSet(out, blobProps);
758
      writeIntSet(out, objectProps);
759

  
725 760
      // write data 
726 761
      if (resultSet != null)
727 762
      {
728 763
         while (resultSet.hasMoreRows())
729 764
         {
730 765
            Object[] row = resultSet.nextRow();
731
            if (blobProps != null)
766
            if (!blobProps.isEmpty())
732 767
            {
733 768
               Object[] row2 = new Object[row.length];
734 769
               System.arraycopy(row, 0, row2, 0, row2.length);
......
743 778
               row = row2;
744 779
            }
745 780
            
746
            if (objectProps != null)
781
            if (!objectProps.isEmpty())
747 782
            {
748 783
               Object[] row2 = new Object[row.length];
749 784
               System.arraycopy(row, 0, row2, 0, row2.length);
......
751 786
               {
752 787
                  if (row2[idx] instanceof object)
753 788
                  {
754
                     row2[idx] = new LegacyObject((object) row2[idx]);
789
                     row2[idx] = new LegacyObject((object<?>) row2[idx]);
755 790
                  }
756 791
               }
757 792
               
......
781 816
    * @throws   IOException
782 817
    *           In case of I/O errors.
783 818
    * @throws   ClassNotFoundException 
819
    *          If the class of property could not be found/loaded.
784 820
    */
821
   @Override
785 822
   public final void readExternal(ObjectInput in)
786 823
   throws IOException,
787 824
          ClassNotFoundException
......
802 839
         return;
803 840
      }
804 841
      
805
      tableName = readString(in);
806
      tableType = in.readByte();
807

  
808
      numIndexes = in.readByte();
809
      indexes = readString(in);
810
      xmlns = readString(in);
811
      xmlPrefix = readString(in);
812
      
... This diff was truncated because it exceeds the maximum size that can be displayed.