Skip to content

Commit 6704938

Browse files
authored
Merge branch 'HTTP-RPC:master' into master
2 parents 61b2752 + abae6fe commit 6704938

15 files changed

Lines changed: 788 additions & 368 deletions

File tree

.idea/compiler.xml

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/gradle.xml

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

settings.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
rootProject.name = 'Sierra'
22

3-
include 'sierra', 'sierra-previewer', 'sierra-test'
3+
include 'sierra', 'sierra-test', 'sierra-tools:dtd-encoder', 'sierra-tools:previewer'
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
plugins {
16+
id 'application'
17+
}
18+
19+
dependencies {
20+
implementation project(':sierra')
21+
}
22+
23+
application {
24+
mainClass = 'org.httprpc.sierra.tools.DTDEncoder'
25+
}
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
package org.httprpc.sierra.tools;
16+
17+
import org.httprpc.kilo.beans.BeanAdapter;
18+
import org.httprpc.kilo.io.Encoder;
19+
import org.httprpc.sierra.ConstantAdapter;
20+
import org.httprpc.sierra.HorizontalAlignment;
21+
import org.httprpc.sierra.MenuButton;
22+
import org.httprpc.sierra.UILoader;
23+
import org.httprpc.sierra.VerticalAlignment;
24+
25+
import javax.swing.Icon;
26+
import javax.swing.JMenu;
27+
import javax.swing.JMenuBar;
28+
import javax.swing.JPanel;
29+
import javax.swing.JScrollPane;
30+
import javax.swing.JSplitPane;
31+
import javax.swing.JTabbedPane;
32+
import javax.swing.JTextField;
33+
import javax.swing.JToolBar;
34+
import java.awt.Color;
35+
import java.awt.Font;
36+
import java.awt.Image;
37+
import java.io.File;
38+
import java.io.FileOutputStream;
39+
import java.io.IOException;
40+
import java.io.Writer;
41+
import java.util.ArrayList;
42+
import java.util.Comparator;
43+
import java.util.HashMap;
44+
import java.util.HashSet;
45+
import java.util.List;
46+
import java.util.Map;
47+
48+
import static org.httprpc.sierra.UILoader.*;
49+
50+
public class DTDEncoder extends Encoder<Void> {
51+
private List<Class<?>> typeList;
52+
private Map<Class<?>, String> tags;
53+
54+
private static final String CDATA = "CDATA";
55+
56+
private DTDEncoder(List<Class<?>> typeList, Map<Class<?>, String> tags) {
57+
this.typeList = typeList;
58+
this.tags = tags;
59+
}
60+
61+
@Override
62+
public void write(Void value, Writer writer) throws IOException {
63+
startEntityDeclaration(UILoader.class, null, writer);
64+
65+
appendAttributeDeclaration(UILoader.Attribute.NAME.getName(), CDATA, writer);
66+
appendAttributeDeclaration(UILoader.Attribute.GROUP.getName(), CDATA, writer);
67+
appendAttributeDeclaration(UILoader.Attribute.BORDER.getName(), CDATA, writer);
68+
appendAttributeDeclaration(UILoader.Attribute.PADDING.getName(), CDATA, writer);
69+
appendAttributeDeclaration(UILoader.Attribute.WEIGHT.getName(), CDATA, writer);
70+
appendAttributeDeclaration(UILoader.Attribute.SIZE.getName(), CDATA, writer);
71+
appendAttributeDeclaration(UILoader.Attribute.TAB_TITLE.getName(), CDATA, writer);
72+
appendAttributeDeclaration(UILoader.Attribute.TAB_ICON.getName(), CDATA, writer);
73+
appendAttributeDeclaration(UILoader.Attribute.STYLE.getName(), CDATA, writer);
74+
appendAttributeDeclaration(UILoader.Attribute.STYLE_CLASS.getName(), CDATA, writer);
75+
76+
endEntityDeclaration(writer);
77+
78+
for (var type : typeList) {
79+
startEntityDeclaration(type, type.getSuperclass(), writer);
80+
81+
for (var entry : BeanAdapter.getProperties(type).entrySet()) {
82+
var property = entry.getValue();
83+
var mutator = property.getMutator();
84+
85+
if (mutator == null || mutator.getDeclaringClass() != type) {
86+
continue;
87+
}
88+
89+
var attributeName = entry.getKey();
90+
91+
var propertyType = mutator.getParameterTypes()[0];
92+
93+
String attributeType;
94+
if (propertyType == Integer.TYPE || propertyType == Integer.class) {
95+
if (attributeName.equals(UILoader.Attribute.HORIZONTAL_ALIGNMENT.getName())) {
96+
attributeType = getAttributeType(HorizontalAlignment.values());
97+
} else if (attributeName.equals(UILoader.Attribute.VERTICAL_ALIGNMENT.getName())) {
98+
attributeType = getAttributeType(VerticalAlignment.values());
99+
} else if (attributeName.equals(UILoader.Attribute.ORIENTATION.getName())) {
100+
attributeType = getAttributeType(UILoader.Orientation.values());
101+
} else if (attributeName.equals(UILoader.Attribute.FOCUS_LOST_BEHAVIOR.getName())) {
102+
attributeType = getAttributeType(UILoader.FocusLostBehavior.values());
103+
} else if (attributeName.equals(UILoader.Attribute.TAB_PLACEMENT.getName())) {
104+
attributeType = getAttributeType(UILoader.TabPlacement.values());
105+
} else if (attributeName.equals(UILoader.Attribute.TAB_LAYOUT_POLICY.getName())) {
106+
attributeType = getAttributeType(UILoader.TabLayoutPolicy.values());
107+
} else {
108+
attributeType = CDATA;
109+
}
110+
} else if (propertyType == Boolean.TYPE || propertyType == Boolean.class) {
111+
attributeType = String.format("(%b|%b)", true, false);
112+
} else if (Enum.class.isAssignableFrom(propertyType)) {
113+
var attributeTypeBuilder = new StringBuilder();
114+
115+
attributeTypeBuilder.append('(');
116+
117+
var fields = propertyType.getDeclaredFields();
118+
119+
var i = 0;
120+
121+
for (var j = 0; j < fields.length; j++) {
122+
var field = fields[j];
123+
124+
if (!field.isEnumConstant()) {
125+
continue;
126+
}
127+
128+
if (i > 0) {
129+
attributeTypeBuilder.append('|');
130+
}
131+
132+
attributeTypeBuilder.append(field.getName().toLowerCase().replace('_', '-'));
133+
134+
i++;
135+
}
136+
137+
attributeTypeBuilder.append(')');
138+
139+
attributeType = attributeTypeBuilder.toString();
140+
} else if (propertyType.isPrimitive()
141+
|| Number.class.isAssignableFrom(propertyType)
142+
|| propertyType == String.class
143+
|| propertyType == Color.class
144+
|| propertyType == Font.class
145+
|| propertyType == Icon.class
146+
|| propertyType == Image.class) {
147+
attributeType = CDATA;
148+
} else {
149+
attributeType = null;
150+
}
151+
152+
if (attributeType != null) {
153+
appendAttributeDeclaration(attributeName, attributeType, writer);
154+
}
155+
}
156+
157+
if (type == JTextField.class) {
158+
appendAttributeDeclaration(UILoader.Attribute.PLACEHOLDER_TEXT.getName(), CDATA, writer);
159+
appendAttributeDeclaration(UILoader.Attribute.SHOW_CLEAR_BUTTON.getName(), String.format("(%b|%b)", true, false), writer);
160+
appendAttributeDeclaration(UILoader.Attribute.LEADING_ICON.getName(), CDATA, writer);
161+
appendAttributeDeclaration(UILoader.Attribute.TRAILING_ICON.getName(), CDATA, writer);
162+
}
163+
164+
endEntityDeclaration(writer);
165+
166+
var tag = tags.get(type);
167+
168+
if (tag != null) {
169+
declareElement(tag, type, writer);
170+
declareAttributeList(tag, type, writer);
171+
}
172+
}
173+
174+
writer.flush();
175+
}
176+
177+
private String getAttributeType(ConstantAdapter[] values) {
178+
var attributeTypeBuilder = new StringBuilder();
179+
180+
attributeTypeBuilder.append('(');
181+
182+
for (var i = 0; i < values.length; i++) {
183+
if (i > 0) {
184+
attributeTypeBuilder.append('|');
185+
}
186+
187+
attributeTypeBuilder.append(values[i].getKey());
188+
}
189+
190+
attributeTypeBuilder.append(')');
191+
192+
return attributeTypeBuilder.toString();
193+
}
194+
195+
private void startEntityDeclaration(Class<?> type, Class<?> baseType, Writer writer) throws IOException {
196+
writer.append("<!ENTITY % ");
197+
writer.append(type.getCanonicalName());
198+
writer.append(" \"");
199+
200+
if (baseType != null) {
201+
writer.append("%");
202+
203+
if (baseType == Object.class) {
204+
writer.append(UILoader.class.getCanonicalName());
205+
} else {
206+
writer.append(baseType.getCanonicalName());
207+
}
208+
209+
writer.append("; ");
210+
}
211+
}
212+
213+
private void appendAttributeDeclaration(String name, String type, Writer writer) throws IOException {
214+
writer.append(name);
215+
writer.append(" ");
216+
writer.append(type);
217+
writer.append(" ");
218+
}
219+
220+
private void endEntityDeclaration(Writer writer) throws IOException {
221+
writer.append("\">\n");
222+
}
223+
224+
private void declareElement(String tag, Class<?> type, Writer writer) throws IOException {
225+
writer.append("<!ELEMENT ");
226+
writer.append(tag);
227+
writer.append(" ");
228+
229+
if (JPanel.class.isAssignableFrom(type)
230+
|| JScrollPane.class.isAssignableFrom(type)
231+
|| JSplitPane.class.isAssignableFrom(type)
232+
|| JTabbedPane.class.isAssignableFrom(type)
233+
|| JToolBar.class.isAssignableFrom(type)
234+
|| JMenuBar.class.isAssignableFrom(type)
235+
|| JMenu.class.isAssignableFrom(type)
236+
|| MenuButton.class.isAssignableFrom(type)) {
237+
writer.append("(ANY)");
238+
} else {
239+
writer.append("EMPTY");
240+
}
241+
242+
writer.append(">\n");
243+
}
244+
245+
private void declareAttributeList(String tag, Class<?> type, Writer writer) throws IOException {
246+
writer.append("<!ATTLIST ");
247+
writer.append(tag);
248+
writer.append(" %");
249+
writer.append(type.getCanonicalName());
250+
writer.append(";>\n");
251+
}
252+
253+
public static void main(String[] args) throws Exception {
254+
var typeSet = new HashSet<Class<?>>();
255+
256+
var tags = new HashMap<Class<?>, String>();
257+
258+
for (var tag : getTags()) {
259+
var type = (Class<?>)getType(tag);
260+
261+
tags.put(type, tag);
262+
263+
while (type != Object.class) {
264+
typeSet.add(type);
265+
266+
type = type.getSuperclass();
267+
}
268+
}
269+
270+
var typeList = new ArrayList<>(typeSet);
271+
272+
typeList.sort(Comparator.comparing(DTDEncoder::getDepth).thenComparing(Class::getCanonicalName));
273+
274+
var dtdEncoder = new DTDEncoder(typeList, tags);
275+
276+
var file = new File(new File(System.getProperty("user.dir")), "sierra.dtd");
277+
278+
try (var outputStream = new FileOutputStream(file)) {
279+
dtdEncoder.write(null, outputStream);
280+
}
281+
}
282+
283+
private static int getDepth(Class<?> type) {
284+
var depth = 0;
285+
286+
while (type != Object.class) {
287+
depth++;
288+
289+
type = type.getSuperclass();
290+
}
291+
292+
return depth;
293+
}
294+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
plugins {
16+
id 'application'
17+
}
18+
19+
dependencies {
20+
implementation project(':sierra')
21+
implementation "com.formdev:flatlaf:${flatLafVersion}"
22+
implementation "com.formdev:flatlaf-extras:${flatLafVersion}"
23+
implementation 'com.fifesoft:rsyntaxtextarea:3.6.0'
24+
implementation 'com.fifesoft:autocomplete:3.3.2'
25+
26+
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1'
27+
testImplementation 'org.mockito:mockito-core:5.9.0'
28+
29+
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
30+
}
31+
32+
tasks.named('test', Test) {
33+
useJUnitPlatform()
34+
}
35+
36+
application {
37+
mainClass = 'org.httprpc.sierra.previewer.SierraPreviewerApp'
38+
}

0 commit comments

Comments
 (0)