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