Project

General

Profile

marshal3.diff

Igor Skornyakov, 11/08/2022 05:06 AM

Download (72.2 KB)

View differences:

src/com/goldencode/p2j/persist/DataSet.java 2022-11-08 09:46:28 +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
                  ErrorManager.recordOrThrowError(12323);
870
               }
854 871
               // if [dsParam] is remote, the dataset was rehydrated when [dsParam] was created
855 872
               // do not copy now for 2nd time. Since it is an [input] param we can use the 
856 873
               // dataset handle directly.
......
3899 3916
      List<BufferImpl> localBuffers = new ArrayList<>(bufs.length);
3900 3917
      for (Buffer buf : bufs)
3901 3918
      {
3919
         if (buf == null)
3920
         {
3921
            continue;
3922
         }
3902 3923
         BufferImpl bufRef = ((BufferImpl) buf).ref();
3903 3924
         if (initClass == null)
3904 3925
         {
src/com/goldencode/p2j/persist/DataSetParameter.java 2022-11-08 09:48:10 +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.
42 43
*/
43 44

  
44 45
/*
......
541 542
         for (int k = 0; k < tableDefs.size(); k++)
542 543
         {
543 544
            DsTableDefinition tableDef = tableDefs.get(k);
544
            
545
            if (!tableDef.isReceivedSchema())
546
            {
547
               continue;
548
            }
545 549
            if (!tableDef.isBeforeTable())
546 550
            {
547 551
               Iterator<PropertyDefinition> props = tableDef.propertyIterator();
548 552
               String idx = tableDef.getIndexes();
549 553
               String xmlns = tableDef.getXmlns();
550 554
               String prefix = tableDef.getXmlPrefix();
551
               buffs[k] = TempTableBuilder.createRemoteTable(tableDef.getName(), props, idx, xmlns, prefix);
555
               List<IndexDefinition> indexDefs = tableDef.getIndexDefs();
556
               TempTableBuilder ttb = new TempTableBuilder(); 
557
               if (indexDefs != null)
558
               {
559
                  buffs[k] = ttb.createRemoteTable(tableDef.getName(), 
560
                           props, () -> indexDefs.stream().forEach(ix -> ix.addTo(ttb)), 
561
                           xmlns, prefix);
562
               }
563
               else
564
               {
565
                  buffs[k] = ttb.createRemoteTable(tableDef.getName(), 
566
                           props, idx, xmlns, prefix);
567
               }
552 568
               
553 569
               if (tableDef.isAfterTable() && tableDef.getPeerDef() != null)
554 570
               {
src/com/goldencode/p2j/persist/DatasetWrapper.java 2022-11-08 09:49:02 +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
**     IAS 20221108 Fixed support for SCHEMA-MARSHAL == NONE.
20 21
*/
21 22

  
22 23
/*
......
572 573
         oos.close();
573 574
         tw = new TableWrapper();
574 575
         tw.readExternal(new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())));
575
         
576
         tw.receivedSchema = tdef.receivedSchema;
576 577
         if (bres != null)
577 578
         {
578 579
            TableWrapper btw = new TableWrapper(bres);
src/com/goldencode/p2j/persist/DsTableDefinition.java 2022-11-08 09:51:59 +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.
23 24
*/
24 25

  
25 26
/*
......
79 80

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

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

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

  
129 138
   /**
130 139
    * A string with all indexes of this table definition encoded as a {@code String}.
131 140
    * 
......
188 197
         case SM_FULL:
189 198
         case SM_DEFAULT:
190 199
            // full table schema is serialized with table parameter
191
            this.indexes = TableMapper.getLegacyIndexInfo(parentTable);
192
            this.numIndexes = this.indexes.split("\\.").length;
193 200
            this.xmlns = parentTable.namespaceURI().toStringMessage();
194 201
            this.xmlPrefix = parentTable.namespacePrefix().toStringMessage();
195 202
            this.xmlNodeName = parentTable.getXmlNodeName().toStringMessage();
196 203
            // no break, fall through
197 204
            
198 205
         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 (?))
206
            this.indexes = TableMapper.getLegacyIndexInfo(parentTable);
207
            this.numIndexes = this.indexes.split("\\.").length;
208
            this.indexDefs = TableMapper.getLegacyIndexes(parentTable).map(lif -> new IndexDefinition(lif)).
209
                     collect(Collectors.toList());
205 210
            this.errorString = defBuff.errorString().toStringMessage();
206 211
            // no break, fall through
207 212
         
......
277 282
      this.name = name;
278 283
   }
279 284
   
285
   /** 
286
    * Check that table schema was received.
287
    * 
288
    * @return <code>true</code> if table schema was received.
289
    */
290
   public boolean isReceivedSchema() 
291
   {
292
      return receivedSchema;
293
   }
294

  
280 295
   /**
281 296
    * Check whether this is a definition of an AFTER-TABLE.
282 297
    * 
......
386 401
   }
387 402
   
388 403
   /**
404
    * Get List of indexes' descriptors.
405
    * @return the List of indexes' descriptors.
406
    */
407
   public List<IndexDefinition> getIndexDefs()
408
   {
409
      return indexDefs;
410
   }
411

  
412
   /**
389 413
    * Sets the XML namespace for this table definition.
390 414
    * 
391 415
    * @param   xmlns
......
502 526
               "A custom result set must not be specified when calling this method!");
503 527
      }
504 528
      
505
      return new ArrayList<>(properties);
529
      return new ArrayList<>(properties != null ? properties : Collections.emptyList());
506 530
   }
507 531
   
508 532
   /**
......
562 586
   public final void writeExternal(ObjectOutput out)
563 587
   throws IOException
564 588
   {
589
      boolean writeSchema = schemaMarshalLevel != SM_NONE;
590
      out.writeByte(schemaMarshalLevel);
565 591
      writeString(out, name);
566 592
      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;
593
      if (writeSchema)
594
      {
595
         out.writeByte(numIndexes);
596
         writeString(out,indexes);
597
         writeList(out, indexDefs);
598
         writeString(out,xmlns);
599
         writeString(out,xmlPrefix);
600
      }
601

  
602
      // write properties
603
      Set<Integer> blobProps = new HashSet<>();
604
      Set<Integer> objectProps = new HashSet<>();
576 605
      if (resultSet != null)
577 606
      {
578 607
         int idx = 0;
579 608
         while (resultSet.hasMoreProperties())
580 609
         {
581 610
            PropertyDefinition property = resultSet.nextProperty();
582
            property.setMarshalLevel(schemaMarshalLevel);
583
            out.writeByte(1);
584
            property.writeExternal(out);
585
            
611
            if (writeSchema)
612
            {
613
               property.setMarshalLevel(schemaMarshalLevel);
614
               out.writeByte(1);
615
               property.writeExternal(out);
616
            }
617

  
586 618
            if (property.getType() == blob.class)
587 619
            {
588
               if (blobProps == null)
589
               {
590
                  blobProps = new HashSet<>();
591
               }
592 620
               blobProps.add(idx);
593 621
            }
622
            else if (object.class.isAssignableFrom(property.getType()))
623
            {
624
               objectProps.add(idx);
625
            }
594 626
            idx = idx + 1;
595 627
         }
596 628
      }
597
      out.writeByte(0);
629
      if (writeSchema)
630
      {
631
         out.writeByte(0);
632
      }
633
      writeIntSet(out, blobProps);
634
      writeIntSet(out, objectProps);
598 635
      
599 636
      // write data 
600 637
      if (resultSet != null)
......
647 684
   throws IOException,
648 685
          ClassNotFoundException
649 686
   {
687
      receivedSchema = in.readByte() != SM_NONE;
650 688
      name = readString(in);
651 689
      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) 
690
      if (receivedSchema)
665 691
      {
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)
692
         numIndexes = in.readByte();
693
         indexes = readString(in);
694
         indexDefs = readList(in, () -> new IndexDefinition());
695
         xmlns = readString(in);
696
         xmlPrefix = readString(in);
697
         properties = new ArrayList<>();
698
         while (in.readByte() != 0)
674 699
         {
675
            if (blobProps == null)
676
            {
677
               blobProps = new HashSet<>();
678
            }
679
            blobProps.add(idx);
700
            PropertyDefinition pd = new PropertyDefinition();
701
            pd.readExternal(in);
702
            properties.add(pd);
703
            
680 704
         }
681
         idx = idx + 1;
682 705
      }
683 706
      
707
      Set<Integer> blobProps = readIntSet(in);
708
      Set<Integer> objectProps = readIntSet(in);
709
      
684 710
      // read data
685 711
      rows = new ArrayList<>();
686 712
      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-02 10:39:37 +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
      out.writeByte(serializeHidden ? 1 : 0);
520
      out.writeByte(caseSensitive ? 1 : 0);
521
      writeString(out, xmlNodeType);
522
      writeString(out, codePage);
523
      out.writeByte(full ? 1 : 0);
524
      if (!full )
525
      {
526
         return;
527
      }
528
      writeString(out, format);
529
      writeString(out, label);
530
      writeString(out, columnLabel);
531
      writeString(out, help);
411 532
   }
412 533
   
413 534
   /**
......
427 548
          ClassNotFoundException
428 549
   {
429 550
      name = readString(in);
551
      legacyName = readString(in);
430 552
      String tn = readString(in);
431 553
      type = (tn == null) ? null : Class.forName(tn);
432 554
      extent = in.readInt();
433
      legacyName = readString(in);
555
      initial = readString(in);
556
      serializeHidden = in.readByte() == 1;
557
      caseSensitive = in.readByte() == 1;
558
      xmlNodeType = readString(in);
559
      codePage = readString(in);
560
      boolean full = in.readByte() == 1;
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-04 14:15:48 +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.
106 108
*/
107 109

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

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

  
2697
      /**
2666 2698
       * Get the legacy index name of converted index, which is defined by the specified backing
2667 2699
       * temp table.
2668 2700
       *
......
2882 2914
                  {
2883 2915
                     if ("today".equalsIgnoreCase(text))
2884 2916
                     {
2885
                        initialValue = date.today();
2917
                        initialValue = new character(text);
2886 2918
                     }
2887 2919
                     else
2888 2920
                     {
......
2893 2925
                  {
2894 2926
                     if ("now".equalsIgnoreCase(text))
2895 2927
                     {
2896
                        initialValue = datetime.now();
2928
                        initialValue = new character(text);
2897 2929
                     }
2898 2930
                     else if (text.toUpperCase().indexOf('T') > 0)
2899 2931
                     {
......
2910 2942
                  {
2911 2943
                     if ("now".equalsIgnoreCase(text))
2912 2944
                     {
2913
                        initialValue = datetimetz.now();
2945
                        initialValue = new character(text);
2914 2946
                     }
2915 2947
                     else if (text.toUpperCase().indexOf('T') > 0)
2916 2948
                     {
......
3118 3150
      }
3119 3151
      
3120 3152
      /**
3153
       * Get a stream for the index components.
3154
       * 
3155
       * @return iterator for the index components.
3156
       */
3157
      public Stream<LegacyIndexComponentInfo> indexComponents()
3158
      {
3159
         return Arrays.stream(components);
3160
      }
3161
      /**
3121 3162
       * Returns index information as a string. Format of this string is described in
3122 3163
       * {@link Buffer#indexInformation(int)}
3123 3164
       *
......
3216 3257
   static class LegacyIndexComponentInfo
3217 3258
   {
3218 3259
      /** The legacy name of the field participating in the index. */
3219
      private final String fieldLegacyName;
3260
      public final String fieldLegacyName;
3220 3261
      
3221 3262
      /** Determines if this component has descending sorting. */
3222
      private final boolean effectiveDescending;
3263
      public final boolean effectiveDescending;
3223 3264
      
3224 3265
      /**
3225 3266
       * Create a new index component information container, holding field name and sorting
src/com/goldencode/p2j/persist/TableWrapper.java 2022-11-07 14:08:36 +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.
31 34
*/
32 35

  
33 36
/*
......
86 89
package com.goldencode.p2j.persist;
87 90

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

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

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

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

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

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

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

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

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

  
579 606
   /**
......
682 709
         return;
683 710
      }
684 711

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

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

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

  
725 759
      // write data 
726 760
      if (resultSet != null)
727 761
      {
728 762
         while (resultSet.hasMoreRows())
729 763
         {
730 764
            Object[] row = resultSet.nextRow();
731
            if (blobProps != null)
765
            if (!blobProps.isEmpty())
732 766
            {
733 767
               Object[] row2 = new Object[row.length];
734 768
               System.arraycopy(row, 0, row2, 0, row2.length);
......
743 777
               row = row2;
744 778
            }
745 779
            
746
            if (objectProps != null)
780
            if (!objectProps.isEmpty())
747 781
            {
748 782
               Object[] row2 = new Object[row.length];
749 783
               System.arraycopy(row, 0, row2, 0, row2.length);
......
751 785
               {
752 786
                  if (row2[idx] instanceof object)
753 787
                  {
754
                     row2[idx] = new LegacyObject((object) row2[idx]);
788
                     row2[idx] = new LegacyObject((object<?>) row2[idx]);
755 789
                  }
756 790
               }
757 791
               
......
781 815
    * @throws   IOException
782 816
    *           In case of I/O errors.
783 817
    * @throws   ClassNotFoundException 
818
    *          If the class of property could not be found/loaded.
784 819
    */
820
   @Override
785 821
   public final void readExternal(ObjectInput in)
786 822
   throws IOException,
787 823
          ClassNotFoundException
......
802 838
         return;
803 839
      }
804 840
      
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
      
813
      Set<Integer> blobProps = null;
814
      Set<Integer> objectProps = null;
815
      int idx = 0;
816
      properties = new ArrayList<>();
817
      do
841
      receivedSchema = in.readByte() != SM_NONE;
842
      if (receivedSchema)
818 843
      {
819
         if (in.readByte() == 0)
820
         {
821
            break;
822
         }
823
         PropertyDefinition pd = new PropertyDefinition();
824
         pd.readExternal(in);
825
         properties.add(pd);
826
         
827
         if (pd.getType() == blob.class)
828
         {
829
            if (blobProps == null)
830
            {
831
               blobProps = new HashSet<>();
832
            }
833
            blobProps.add(idx);
834
         }
835
         if (object.class.isAssignableFrom(pd.getType()))
836
         {
837
            if (objectProps == null)
838
            {
839
               objectProps = new HashSet<>();
840
            }
841
            objectProps.add(idx);
842
         }
843
         idx = idx + 1;
844
         tableName = readString(in);
845
         tableType = in.readByte();
846
         numIndexes = in.readByte();
847
         indexes = readString(in);
848
         indexDefs = readList(in, () -> new IndexDefinition());
849
         xmlns = readString(in);
850
         xmlPrefix = readString(in);
851
         properties = new ArrayList<>();
852
         while (in.readByte() != 0)
853
         {
854
            PropertyDefinition pd = new PropertyDefinition();
855
            pd.readExternal(in);
856
            properties.add(pd);
857
            
858
         }
844 859
      }
845
      while (true);
860
      
861
      Set<Integer> blobProps = readIntSet(in);
862
      Set<Integer> objectProps = readIntSet(in);
846 863
      
847 864
      // read data
848 865
      rows = new ArrayList<>();
......
857 874
         
858 875
         Object[] row = (Object[]) next;
859 876
         rows.add(row);
860
         if (blobProps != null)
861
         {
862
            for (Integer i : blobProps)
863
            {
864
               row[i] = new blob(((MemoryBuffer) row[i]).getValue());
865
            }
866
         }
867
         if (objectProps != null)
868
         {
869
            for (Integer i : objectProps)
870
            {
871
               LegacyObject ref = (LegacyObject) row[i];
872
               ObjectVar v = new ObjectVar(ref.getType());
873
               v.assign(ref.restore());
874
               row[i] = v;
875
            }
876
         }
877
         blobProps.stream().forEach(i -> row[i] = new blob(((MemoryBuffer) row[i]).getValue()));
878
         objectProps.stream().forEach(i -> {
879
            LegacyObject ref = (LegacyObject) row[i];
880
            ObjectVar<? extends _BaseObject_> v = new ObjectVar<>(ref.getType());
881
            v.assign(ref.restore());
882
            row[i] = v;
883
         });
877 884

  
878 885
         next = in.readObject();
879 886
         rowsMeta.add((Object[]) next);
......
890 897
      }
891 898
   }
892 899

  
900
   /** 
901
    * Check that table schema was received.
902
    * 
903
    * @return <code>true</code> if table schema was received.
904
    */
905
   public boolean isReceivedSchema() 
906
   {
907
      return receivedSchema;
908
   }
909

  
893 910
   /**
894 911
    * Determines if this wrapper wraps data from a TABLE-HANDLE parameter.
895 912
    *
......
921 938
      this.tableHandle = tableHandle;
922 939
   }
923 940

  
941
   /** Get encoded table SCHEMA-MARSHAL attribute value.
942
    * 
943
    * @return encoded table SCHEMA-MARSHAL attribute value.
944
    */
945
   public int getSchemaMarshalLevel()
946
   {
947
      return schemaMarshalLevel;
948
   }
949

  
950
   /** Set encoded table SCHEMA-MARSHAL attribute value.
951
    * 
952
    * @param schemaMarshalLevel 
953
    *        encoded table SCHEMA-MARSHAL attribute value.
954
    */
955
   public void setSchemaMarshalLevel(int schemaMarshalLevel)
956
   {
957
      this.schemaMarshalLevel = schemaMarshalLevel;
958
   }
959

  
924 960
   /**
925 961
    * Initialize this wrapper with the info from the given temp-table.
926 962
    * 
......
933 969
      Buffer defBuff = (Buffer) table.defaultBufferHandle().getResource();
934 970
      this.indexes = TableMapper.getLegacyIndexInfo(table);
935 971
      this.numIndexes = indexes.split("\\.").length; // TODO: "." or "\\." ?
972
      this.indexDefs = TableMapper.getLegacyIndexes(table).map(lif -> new IndexDefinition(lif)).
973
                                                           collect(Collectors.toList());
936 974
      this.xmlns = defBuff.namespaceURI().toStringMessage();
937 975
      this.xmlPrefix = defBuff.namespacePrefix().toStringMessage();
938 976
   }
src/com/goldencode/p2j/persist/TempTableBuilder.java 2022-11-08 09:26:37 +0000
122 122
**     OM  20220914 Added MAX-WIDTH support for CHARACTER fields.
123 123
**     IAS 20221003 Fixed default value of the PRIMARY attribute
124 124
**     IAS 20221014 Added COMHANDLE to the 'datatypesMatchLen' map
125
**     IAS 20221029 Added support for missed properties.
126
**     IAS 20221104 Added indexes parsing for input remote table.
127
**     IAS 20221108 Replaced static 'createRemoteTable' with a regular one.
125 128
*/
126 129

  
127 130
/*
......
313 316
    *           The XML namespace.
314 317
    * @param    xmlPrefix
315 318
    *           The XML prefix.
319
    * @return   default buffer for the table
316 320
    */
317
   public static BufferImpl createRemoteTable(String tableName,
321
   public BufferImpl createRemoteTable(String tableName,
318 322
                                              Iterator<PropertyDefinition> props,
319 323
                                              String tableIndexes, 
320 324
                                              String xmlns,
321 325
                                              String xmlPrefix)
322 326
   {
323
      TempTableBuilder ttb = new TempTableBuilder();
324
      props.forEachRemaining(ttb::addNewField);
325
      
326
      if (tableIndexes != null)
327
      {
328
         String[] indexes = tableIndexes.split("\\.");
329
         for (int i = 0; i < indexes.length; i++)
330
         {
331
            String indexDef = indexes[i];
332
            if (indexDef.isEmpty())
333
            {
334
               continue;
335
            }
336
            String[] compAndName = indexDef.split(":");
337
            String typeAndComps = compAndName[0];
338
            String idxName = compAndName[1];
339
            String[] comps = typeAndComps.split(",");
340
            boolean unique = (i != 0) || "1".equals(comps[0]);
341
            boolean primary = (i == 0) && ("1".equals(comps[0]) || "0".equals(comps[0]));
342
            
343
            ttb.addNewIndex(new character(idxName),
344
                            new logical(unique),
345
                            new logical(primary));
346
            for (int j = (primary ? 1 : 0); j < comps.length; j++)
347
            {
348
               ttb.addFieldToIndex(idxName, comps[j]);
349
            }
350
         }
351
      }
352
      
353
      ttb.tempTablePrepare(tableName);
354
      BufferImpl buff = (BufferImpl) ttb.defaultBufferHandle().getResource();
355
      if (xmlns != null)
356
      {
357
         buff.namespaceURI(xmlns);
358
      }
359
      if (xmlPrefix != null)
360
      {
361
         buff.namespacePrefix(xmlPrefix);
362
      }
363
      
364
      return buff;
327
      return createTable(tableName, props, 
328
               () -> parseIndexString(tableIndexes), xmlns, xmlPrefix);
329
   }
330
   
331
   /**
332
    * Create a temp-table with the specified definition, as received from a remote side.
333
    * 
334
    * @param    tableName
335
    *           The table name.
336
    * @param    props
337
    *           The property definitions.
338
    * @param    indexProvider
339
    *           indexes' provider.
340
    * @param    xmlns
341
    *           The XML namespace.
342
    * @param    xmlPrefix
343
    *           The XML prefix.
344
    * @return   default buffer for the table
345
    */
346
   public BufferImpl createRemoteTable(String tableName,
347
                                              Iterator<PropertyDefinition> props,
348
                                              Runnable indexProvider, 
349
                                              String xmlns,
350
                                              String xmlPrefix)
351
   {
352
      return createTable(tableName, props, indexProvider, xmlns, xmlPrefix);
365 353
   }
366 354
   
367 355
   /**
......
1340 1328
                              character    label,
1341 1329
                              character    columnLabel)
1342 1330
   {
1331
      return addNewField(name, type, extent, format, initial, label, columnLabel,
1332
               null, null, null, false, false);
1333
   }
1334
   /**
1335
    * Adds a field with the specified properties to the temp-table.
1336
    * This method is the P2J equivalent of <code>ADD-NEW-FIELD</code> method
1337
    * of Progress 4GL.
1338
    * <p>
1339
    * When a parameter is set to null, it means it was not specified by the business logic.
1340
    *
1341
    * @param   name
1342
    *          The name of the field to be created in the temp-table.
1343
    * @param   type
1344
    *          The data type of the specified field.
1345
    * @param   extent
1346
    *          An integer expression specifying the extent of an array.
1347
    * @param   format
1348
    *          The data format for the defined data type. If empty or unknown, format is
1349
    *          replaced with default format. Null value means that format is not used in
1350
    *          ADD-NEW-FIELD.
1351
    * @param   initial
1352
    *          An expression that evaluates to the initial value of the defined field.
1353
    *          TODO: this method will probably be overloaded because of this.
1354
    * @param   label
1355
    *          The label of the defined field. If <code>null</code> or unknown the name
1356
    *          parameter will be used.
1357
    * @param   columnLabel
1358
    *          The label of the column associated with the defined field
1359
    * @param   help 
1360
    * @param   xmlNodeType 
1361
    * @param   codePage 
1362
    * @param   serializeHidden 
1363
    * @param   caseSensitive 
1364
    *
1365
    * @return  <code>true</code> on success.
1366
    */
1367
   public logical addNewField(character    name,
1368
                              character    type,
1369
                              integer      extent,
1370
                              character    format,
1371
                              BaseDataType initial,
1372
                              character    label,
1373
                              character    columnLabel,
1374
                              character    help,
1375
                              character    xmlNodeType,
1376
                              character    codePage,
1377
                              boolean      serializeHidden,
1378
                              boolean      caseSensitive)
1379
   {
1343 1380
      addFunctionCalled = true;
1344 1381
      
1345 1382
      if (_prepared())
......
1397 1434
      
1398 1435
      String labelStr = label != null ? label.getValue() : null;
1399 1436
      String columnLabelStr = columnLabel != null ? columnLabel.getValue() : null;
1437
      String helpStr = help != null ? help.getValue() : null;
1438
      String codePageStr = codePage != null ? codePage.getValue() : null;
1439
      String xmlNodeTypeStr = xmlNodeType != null ? xmlNodeType.getValue() : null;
1400 1440
      
1401 1441
      // Note: case-sensitivity and CLOB code page cannot be specified using P4GL ADD-NEW-FIELD method
1402 1442
      long ext = extent == null || extent.getValue() == 1 ? 0 : extent.getValue();
1403 1443
      P2JField field = new P2JField(fieldName, parmType, ext, formatStr,
1404
                                    initial, labelStr, columnLabelStr, false, null, null, false, null, null,
1405
                                    null, null, false, 0, 0);
... This diff was truncated because it exceeds the maximum size that can be displayed.