1
+ package com .relogiclabs .jschema .internal .library ;
2
+
3
+ import com .relogiclabs .jschema .exception .InvalidSelfStateException ;
4
+ import com .relogiclabs .jschema .extension .ScriptMethod ;
5
+ import com .relogiclabs .jschema .internal .engine .ScriptTreeHelper ;
6
+ import com .relogiclabs .jschema .internal .script .GArray ;
7
+ import com .relogiclabs .jschema .internal .script .GDouble ;
8
+ import com .relogiclabs .jschema .internal .script .GInteger ;
9
+ import com .relogiclabs .jschema .type .EArray ;
10
+ import com .relogiclabs .jschema .type .EInteger ;
11
+ import com .relogiclabs .jschema .type .ENumber ;
12
+ import com .relogiclabs .jschema .type .EValue ;
13
+
14
+ import java .util .Collections ;
15
+
16
+ import static com .relogiclabs .jschema .internal .engine .ScriptTreeHelper .areEqual ;
17
+ import static com .relogiclabs .jschema .internal .engine .ScriptTreeHelper .dereference ;
18
+ import static com .relogiclabs .jschema .internal .engine .ScriptTreeHelper .stringify ;
19
+ import static com .relogiclabs .jschema .message .ErrorCode .ARREMT01 ;
20
+ import static com .relogiclabs .jschema .message .ErrorCode .ARRRON01 ;
21
+ import static com .relogiclabs .jschema .message .ErrorCode .NUMARR01 ;
22
+ import static com .relogiclabs .jschema .type .EType .ARRAY ;
23
+ import static com .relogiclabs .jschema .type .EUndefined .UNDEFINED ;
24
+ import static java .util .Comparator .comparing ;
25
+ import static java .util .Comparator .comparingDouble ;
26
+
27
+ public class ArrayMethods1 extends AbstractMethods {
28
+ @ ScriptMethod (ARRAY )
29
+ public EInteger length () {
30
+ return GInteger .from (getSelf (EArray .class ).size ());
31
+ }
32
+
33
+ @ ScriptMethod (ARRAY )
34
+ public EInteger push (EValue element , EValue ... elements ) {
35
+ var array = getSelf (EArray .class );
36
+ requireWritableArray (array );
37
+ array .set (array .size (), element );
38
+ for (var v : elements ) array .set (array .size (), v );
39
+ return GInteger .from (array .size ());
40
+ }
41
+
42
+ @ ScriptMethod (ARRAY )
43
+ public EValue pop () {
44
+ var array = getSelf (EArray .class );
45
+ requireWritableArray (array );
46
+ requireNonEmptyArray (array );
47
+ return dereference (array .elements ().remove (array .size () - 1 ));
48
+ }
49
+
50
+ @ ScriptMethod (ARRAY )
51
+ public EValue find (EValue element ) {
52
+ var array = getSelf (EArray .class );
53
+ for (var i = 0 ; i < array .size (); i ++)
54
+ if (areEqual (array .get (i ), element , getRuntime ())) return GInteger .from (i );
55
+ return UNDEFINED ;
56
+ }
57
+
58
+ @ ScriptMethod (ARRAY )
59
+ public EValue find (EValue element , EInteger start ) {
60
+ var array = getSelf (EArray .class );
61
+ for (var i = (int ) start .getValue (); i < array .size (); i ++)
62
+ if (areEqual (array .get (i ), element , getRuntime ())) return GInteger .from (i );
63
+ return UNDEFINED ;
64
+ }
65
+
66
+ @ ScriptMethod (ARRAY )
67
+ public EArray fill (EValue value , EInteger length ) {
68
+ return GArray .filledFrom (value , (int ) length .getValue ());
69
+ }
70
+
71
+ @ ScriptMethod (ARRAY )
72
+ public EArray sort () {
73
+ var array = getSelf (EArray .class );
74
+ requireWritableArray (array );
75
+ if (isAllNumbers (array )) array .elements ().sort (comparingDouble (e -> toDouble (dereference (e ))));
76
+ else array .elements ().sort (comparing (e -> stringify (dereference (e ))));
77
+ return array ;
78
+ }
79
+
80
+ private static boolean isAllNumbers (EArray array ) {
81
+ for (var e : array .elements ())
82
+ if (!(dereference (e ) instanceof ENumber )) return false ;
83
+ return true ;
84
+ }
85
+
86
+ @ ScriptMethod (ARRAY )
87
+ public EArray reverse () {
88
+ var array = getSelf (EArray .class );
89
+ requireWritableArray (array );
90
+ Collections .reverse (array .elements ());
91
+ return array ;
92
+ }
93
+
94
+ @ ScriptMethod (ARRAY )
95
+ public EValue max () {
96
+ var array = getSelf (EArray .class );
97
+ requireNonEmptyArray (array );
98
+ return array .elements ().stream ().map (ScriptTreeHelper ::dereference )
99
+ .max (comparingDouble (this ::toDouble ))
100
+ .orElseThrow (() -> new IllegalStateException ("Array max not found" ));
101
+ }
102
+
103
+ @ ScriptMethod (ARRAY )
104
+ public EValue min () {
105
+ var array = getSelf (EArray .class );
106
+ requireNonEmptyArray (array );
107
+ return array .elements ().stream ().map (ScriptTreeHelper ::dereference )
108
+ .min (comparingDouble (this ::toDouble ))
109
+ .orElseThrow (() -> new IllegalStateException ("Array min not found" ));
110
+ }
111
+
112
+ @ ScriptMethod (ARRAY )
113
+ public EValue sum () {
114
+ var sum = getSelf (EArray .class ).elements ().stream ()
115
+ .map (ScriptTreeHelper ::dereference )
116
+ .mapToDouble (this ::toDouble ).sum ();
117
+ if (sum % 1 == 0 ) return GInteger .from ((long ) sum );
118
+ else return GDouble .from (sum );
119
+ }
120
+
121
+ @ ScriptMethod (ARRAY )
122
+ public EArray copy () {
123
+ return new GArray (getSelf (EArray .class ).elements ());
124
+ }
125
+
126
+ private void requireNonEmptyArray (EArray array ) {
127
+ if (array .size () != 0 ) return ;
128
+ var exception = new InvalidSelfStateException (ARREMT01 , "Array cannot be empty" );
129
+ exception .setSelf (getSelf ());
130
+ exception .setMethod (getMethod ());
131
+ throw exception ;
132
+ }
133
+
134
+ private void requireWritableArray (EArray array ) {
135
+ if (!array .isReadonly ()) return ;
136
+ var exception = new InvalidSelfStateException (ARRRON01 , "Array cannot be readonly" );
137
+ exception .setSelf (getSelf ());
138
+ exception .setMethod (getMethod ());
139
+ throw exception ;
140
+ }
141
+
142
+ private double toDouble (EValue value ) {
143
+ if (value instanceof ENumber n ) return n .toDouble ();
144
+ var exception = new InvalidSelfStateException (NUMARR01 ,
145
+ "All array elements must be numerical" );
146
+ exception .setSelf (getSelf ());
147
+ exception .setMethod (getMethod ());
148
+ throw exception ;
149
+ }
150
+ }
0 commit comments