1+ /*
2+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+ package build .tools .generateextraproperties ;
26+
27+ import java .io .IOException ;
28+ import java .nio .file .Files ;
29+ import java .nio .file .Paths ;
30+ import java .nio .file .StandardOpenOption ;
31+ import java .util .ArrayList ;
32+ import java .util .Arrays ;
33+ import java .util .HashMap ;
34+ import java .util .List ;
35+ import java .util .function .Predicate ;
36+ import java .util .stream .Collectors ;
37+ import java .util .stream .Stream ;
38+
39+ /**
40+ * Parses extra properties files of UCD, and replaces the placeholders in
41+ * the given template source file with the generated conditions, then emits
42+ * .java files. For example, if the properties file has:
43+ * <blockquote>
44+ * 0009..000D ; Type (; Value)
45+ * 0020 ; Type (; Value)
46+ * 2000..200A ; Type (; Value)
47+ * </blockquote>
48+ * and the template file contains
49+ * <blockquote>
50+ * %%%Type(=Value)%%%
51+ * </blockquote>
52+ * then the generated .java file would have the following in place:
53+ * <blockquote>
54+ * (cp >= 0x0009 && cp <= 0x000D) ||
55+ * cp == 0x0020 ||
56+ * (cp >= 0x2000 && cp <= 0x200A);
57+ * </blockquote>
58+ * Note that those in parentheses in the properties file and the
59+ * template file are optional.
60+ *
61+ * Arguments to this utility:
62+ * args[0]: Full path string to the template file
63+ * args[1]: Full path string to the properties file
64+ * args[2]: Full path string to the generated .java file
65+ * args[3...]: Names of the property to generate the conditions
66+ */
67+ public class GenerateExtraProperties {
68+ public static void main (String [] args ) {
69+ var templateFile = Paths .get (args [0 ]);
70+ var propertiesFile = Paths .get (args [1 ]);
71+ var gensrcFile = Paths .get (args [2 ]);
72+ var propertyNames = Arrays .copyOfRange (args , 3 , args .length );
73+ var replacementMap = new HashMap <String , String >();
74+
75+ try {
76+ for (var propertyName : propertyNames ) {
77+ var pn = "; " + propertyName .replaceFirst ("=" , "; " );
78+
79+ List <Range > ranges = Files .lines (propertiesFile )
80+ .filter (Predicate .not (l -> l .startsWith ("#" ) || l .isBlank ()))
81+ .filter (l -> l .contains (pn ))
82+ .map (l -> new Range (l .replaceFirst (" .*" , "" )))
83+ .sorted ()
84+ .collect (ArrayList <Range >::new ,
85+ (list , r ) -> {
86+ // collapsing consecutive pictographic ranges
87+ int lastIndex = list .size () - 1 ;
88+ if (lastIndex >= 0 ) {
89+ Range lastRange = list .get (lastIndex );
90+ if (lastRange .last + 1 == r .start ) {
91+ list .set (lastIndex , new Range (lastRange .start , r .last ));
92+ return ;
93+ }
94+ }
95+ list .add (r );
96+ },
97+ ArrayList <Range >::addAll );
98+
99+
100+ replacementMap .put ("%%%" + propertyName + "%%%" ,
101+ ranges .stream ()
102+ .map (GenerateExtraProperties ::rangeToString )
103+ .collect (Collectors .joining (" ||\n " , "" , ";" )));
104+ }
105+
106+ // Generate .java file
107+ Files .write (gensrcFile ,
108+ Files .lines (templateFile )
109+ .flatMap (l -> Stream .of (replacementMap .getOrDefault (l .trim (), l )))
110+ .collect (Collectors .toList ()),
111+ StandardOpenOption .CREATE , StandardOpenOption .TRUNCATE_EXISTING );
112+ } catch (IOException e ) {
113+ e .printStackTrace ();
114+ }
115+ }
116+
117+ static String rangeToString (Range r ) {
118+ if (r .start == r .last ) {
119+ return (" " .repeat (12 ) + "cp == 0x" + toHexString (r .start ));
120+ } else if (r .start == r .last - 1 ) {
121+ return " " .repeat (12 ) + "cp == 0x" + toHexString (r .start ) + " ||\n " +
122+ " " .repeat (12 ) + "cp == 0x" + toHexString (r .last );
123+ } else {
124+ return " " .repeat (11 ) + "(cp >= 0x" + toHexString (r .start ) +
125+ " && cp <= 0x" + toHexString (r .last ) + ")" ;
126+ }
127+ }
128+
129+ static int toInt (String hexStr ) {
130+ return Integer .parseUnsignedInt (hexStr , 16 );
131+ }
132+
133+ static String toHexString (int cp ) {
134+ String ret = Integer .toUnsignedString (cp , 16 ).toUpperCase ();
135+ if (ret .length () < 4 ) {
136+ ret = "0" .repeat (4 - ret .length ()) + ret ;
137+ }
138+ return ret ;
139+ }
140+
141+ static class Range implements Comparable <Range > {
142+ int start ;
143+ int last ;
144+
145+ Range (int start , int last ) {
146+ this .start = start ;
147+ this .last = last ;
148+ }
149+
150+ Range (String input ) {
151+ input = input .replaceFirst ("\\ s#.*" , "" );
152+ start = toInt (input .replaceFirst ("[\\ s\\ .].*" , "" ));
153+ last = input .contains (".." ) ?
154+ toInt (input .replaceFirst (".*\\ .\\ ." , "" )
155+ .replaceFirst (";.*" , "" ).trim ())
156+ : start ;
157+ }
158+
159+ @ Override
160+ public String toString () {
161+ return "Start: " + toHexString (start ) + ", Last: " + toHexString (last );
162+ }
163+
164+ @ Override
165+ public int compareTo (Range other ) {
166+ return Integer .compare (start , other .start );
167+ }
168+ }
169+ }
0 commit comments