Skip to content

Commit fb19f42

Browse files
committed
Move DTDEncoder to tools project.
1 parent 8d4f5d8 commit fb19f42

File tree

13 files changed

+799
-364
lines changed

13 files changed

+799
-364
lines changed

.idea/gradle.xml

Lines changed: 2 additions & 0 deletions
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-previewer', 'sierra-test', 'sierra-tools:dtd-encoder'
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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+
implementation "com.formdev:flatlaf:${flatLafVersion}"
23+
implementation "com.formdev:flatlaf-extras:${flatLafVersion}"
24+
}
25+
26+
application {
27+
mainClass = 'org.httprpc.sierra.tools.DTDEncoder'
28+
}
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
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+
var i = 0;
183+
184+
for (var value : values) {
185+
if (i > 0) {
186+
attributeTypeBuilder.append('|');
187+
}
188+
189+
attributeTypeBuilder.append(value.getKey());
190+
191+
i++;
192+
}
193+
194+
attributeTypeBuilder.append(')');
195+
196+
return attributeTypeBuilder.toString();
197+
}
198+
199+
private void startEntityDeclaration(Class<?> type, Class<?> baseType, Writer writer) throws IOException {
200+
writer.append("<!ENTITY % ");
201+
writer.append(type.getCanonicalName());
202+
writer.append(" \"");
203+
204+
if (baseType != null) {
205+
writer.append("%");
206+
207+
if (baseType == Object.class) {
208+
writer.append(UILoader.class.getCanonicalName());
209+
} else {
210+
writer.append(baseType.getCanonicalName());
211+
}
212+
213+
writer.append("; ");
214+
}
215+
}
216+
217+
private void appendAttributeDeclaration(String name, String type, Writer writer) throws IOException {
218+
writer.append(name);
219+
writer.append(" ");
220+
writer.append(type);
221+
writer.append(" ");
222+
}
223+
224+
private void endEntityDeclaration(Writer writer) throws IOException {
225+
writer.append("\">\n");
226+
}
227+
228+
private void declareElement(String tag, Class<?> type, Writer writer) throws IOException {
229+
writer.append("<!ELEMENT ");
230+
writer.append(tag);
231+
writer.append(" ");
232+
233+
if (JPanel.class.isAssignableFrom(type)
234+
|| JScrollPane.class.isAssignableFrom(type)
235+
|| JSplitPane.class.isAssignableFrom(type)
236+
|| JTabbedPane.class.isAssignableFrom(type)
237+
|| JToolBar.class.isAssignableFrom(type)
238+
|| JMenuBar.class.isAssignableFrom(type)
239+
|| JMenu.class.isAssignableFrom(type)
240+
|| MenuButton.class.isAssignableFrom(type)) {
241+
writer.append("(ANY)");
242+
} else {
243+
writer.append("EMPTY");
244+
}
245+
246+
writer.append(">\n");
247+
}
248+
249+
private void declareAttributeList(String tag, Class<?> type, Writer writer) throws IOException {
250+
writer.append("<!ATTLIST ");
251+
writer.append(tag);
252+
writer.append(" %");
253+
writer.append(type.getCanonicalName());
254+
writer.append(";>\n");
255+
}
256+
257+
public static void main(String[] args) throws IOException {
258+
var typeSet = new HashSet<Class<?>>();
259+
260+
var tags = new HashMap<Class<?>, String>();
261+
262+
for (var tag : getTags()) {
263+
var type = (Class<?>)getType(tag);
264+
265+
tags.put(type, tag);
266+
267+
while (type != Object.class) {
268+
typeSet.add(type);
269+
270+
type = type.getSuperclass();
271+
}
272+
}
273+
274+
var typeList = new ArrayList<>(typeSet);
275+
276+
typeList.sort(Comparator.comparing(DTDEncoder::getDepth).thenComparing(Class::getCanonicalName));
277+
278+
var dtdEncoder = new DTDEncoder(typeList, tags);
279+
280+
var file = new File(new File(System.getProperty("user.dir")), "sierra.dtd");
281+
282+
try (var outputStream = new FileOutputStream(file)) {
283+
dtdEncoder.write(null, outputStream);
284+
}
285+
}
286+
287+
private static int getDepth(Class<?> type) {
288+
var depth = 0;
289+
290+
while (type != Object.class) {
291+
depth++;
292+
293+
type = type.getSuperclass();
294+
}
295+
296+
return depth;
297+
}
298+
}

sierra.dtd

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
<!ENTITY % java.awt.Component "%org.httprpc.sierra.UILoader; background CDATA enabled (true|false) focusTraversalKeysEnabled (true|false) focusable (true|false) font CDATA foreground CDATA ignoreRepaint (true|false) name CDATA visible (true|false) ">
33
<!ENTITY % java.awt.Container "%java.awt.Component; focusCycleRoot (true|false) focusTraversalPolicyProvider (true|false) font CDATA ">
44
<!ENTITY % javax.swing.JComponent "%java.awt.Container; alignmentX CDATA alignmentY CDATA autoscrolls (true|false) background CDATA debugGraphicsOptions CDATA doubleBuffered (true|false) enabled (true|false) font CDATA foreground CDATA inheritsPopupMenu (true|false) opaque (true|false) requestFocusEnabled (true|false) toolTipText CDATA verifyInputWhenFocusTarget (true|false) visible (true|false) ">
5-
<!ENTITY % javax.swing.AbstractButton "%javax.swing.JComponent; actionCommand CDATA borderPainted (true|false) contentAreaFilled (true|false) disabledIcon CDATA disabledSelectedIcon CDATA displayedMnemonicIndex CDATA enabled (true|false) focusPainted (true|false) hideActionText (true|false) horizontalAlignment (left|center|right|leading|trailing) horizontalTextPosition CDATA icon CDATA iconTextGap CDATA label CDATA mnemonic CDATA multiClickThreshhold CDATA pressedIcon CDATA rolloverEnabled (true|false) rolloverIcon CDATA rolloverSelectedIcon CDATA selected (true|false) selectedIcon CDATA text CDATA verticalAlignment (top|center|bottom) verticalTextPosition CDATA ">
5+
<!ENTITY % javax.swing.AbstractButton "%javax.swing.JComponent; actionCommand CDATA borderPainted (true|false) contentAreaFilled (true|false) disabledIcon CDATA disabledSelectedIcon CDATA displayedMnemonicIndex CDATA enabled (true|false) focusPainted (true|false) hideActionText (true|false) horizontalAlignment (left|right|leading|trailing|center) horizontalTextPosition CDATA icon CDATA iconTextGap CDATA label CDATA mnemonic CDATA multiClickThreshhold CDATA pressedIcon CDATA rolloverEnabled (true|false) rolloverIcon CDATA rolloverSelectedIcon CDATA selected (true|false) selectedIcon CDATA text CDATA verticalAlignment (top|bottom|center) verticalTextPosition CDATA ">
66
<!ENTITY % javax.swing.JColorChooser "%javax.swing.JComponent; color CDATA dragEnabled (true|false) ">
77
<!ELEMENT color-chooser EMPTY>
88
<!ATTLIST color-chooser %javax.swing.JColorChooser;>
99
<!ENTITY % javax.swing.JComboBox "%javax.swing.JComponent; actionCommand CDATA editable (true|false) enabled (true|false) lightWeightPopupEnabled (true|false) maximumRowCount CDATA popupVisible (true|false) selectedIndex CDATA ">
1010
<!ELEMENT combo-box EMPTY>
1111
<!ATTLIST combo-box %javax.swing.JComboBox;>
12-
<!ENTITY % javax.swing.JLabel "%javax.swing.JComponent; disabledIcon CDATA displayedMnemonic CDATA displayedMnemonicIndex CDATA horizontalAlignment (left|center|right|leading|trailing) horizontalTextPosition CDATA icon CDATA iconTextGap CDATA text CDATA verticalAlignment (top|center|bottom) verticalTextPosition CDATA ">
12+
<!ENTITY % javax.swing.JLabel "%javax.swing.JComponent; disabledIcon CDATA displayedMnemonic CDATA displayedMnemonicIndex CDATA horizontalAlignment (left|right|leading|trailing|center) horizontalTextPosition CDATA icon CDATA iconTextGap CDATA text CDATA verticalAlignment (top|bottom|center) verticalTextPosition CDATA ">
1313
<!ELEMENT label EMPTY>
1414
<!ATTLIST label %javax.swing.JLabel;>
1515
<!ENTITY % javax.swing.JList "%javax.swing.JComponent; dragEnabled (true|false) dropMode (use-selection|on|insert|insert-rows|insert-cols|on-or-insert|on-or-insert-rows|on-or-insert-cols) fixedCellHeight CDATA fixedCellWidth CDATA layoutOrientation CDATA selectedIndex CDATA selectionBackground CDATA selectionForeground CDATA selectionMode CDATA valueIsAdjusting (true|false) visibleRowCount CDATA ">
@@ -53,13 +53,13 @@
5353
<!ENTITY % org.httprpc.sierra.ActivityIndicator "%javax.swing.JComponent; indicatorSize CDATA ">
5454
<!ELEMENT activity-indicator EMPTY>
5555
<!ATTLIST activity-indicator %org.httprpc.sierra.ActivityIndicator;>
56-
<!ENTITY % org.httprpc.sierra.ImagePane "%javax.swing.JComponent; horizontalAlignment (leading|trailing|center) image CDATA scaleMode (none|fill-width|fill-height) verticalAlignment (top|bottom|center) ">
56+
<!ENTITY % org.httprpc.sierra.ImagePane "%javax.swing.JComponent; horizontalAlignment (left|right|leading|trailing|center) image CDATA scaleMode (none|fill-width|fill-height) verticalAlignment (top|bottom|center) ">
5757
<!ELEMENT image-pane EMPTY>
5858
<!ATTLIST image-pane %org.httprpc.sierra.ImagePane;>
5959
<!ENTITY % org.httprpc.sierra.Spacer "%javax.swing.JComponent; ">
6060
<!ELEMENT spacer EMPTY>
6161
<!ATTLIST spacer %org.httprpc.sierra.Spacer;>
62-
<!ENTITY % org.httprpc.sierra.TextPane "%javax.swing.JComponent; horizontalAlignment (leading|trailing|center) text CDATA verticalAlignment (top|bottom|center) wrapText (true|false) ">
62+
<!ENTITY % org.httprpc.sierra.TextPane "%javax.swing.JComponent; horizontalAlignment (left|right|leading|trailing|center) text CDATA verticalAlignment (top|bottom|center) wrapText (true|false) ">
6363
<!ELEMENT text-pane EMPTY>
6464
<!ATTLIST text-pane %org.httprpc.sierra.TextPane;>
6565
<!ENTITY % javax.swing.JButton "%javax.swing.AbstractButton; defaultCapable (true|false) ">
@@ -74,7 +74,7 @@
7474
<!ENTITY % javax.swing.JTextArea "%javax.swing.text.JTextComponent; columns CDATA font CDATA lineWrap (true|false) rows CDATA tabSize CDATA wrapStyleWord (true|false) ">
7575
<!ELEMENT text-area EMPTY>
7676
<!ATTLIST text-area %javax.swing.JTextArea;>
77-
<!ENTITY % javax.swing.JTextField "%javax.swing.text.JTextComponent; columns CDATA font CDATA horizontalAlignment (left|center|right|leading|trailing) scrollOffset CDATA placeholderText CDATA showClearButton (true|false) leadingIcon CDATA trailingIcon CDATA ">
77+
<!ENTITY % javax.swing.JTextField "%javax.swing.text.JTextComponent; columns CDATA font CDATA horizontalAlignment (left|right|leading|trailing|center) scrollOffset CDATA placeholderText CDATA showClearButton (true|false) leadingIcon CDATA trailingIcon CDATA ">
7878
<!ELEMENT text-field EMPTY>
7979
<!ATTLIST text-field %javax.swing.JTextField;>
8080
<!ENTITY % javax.swing.JToggleButton "%javax.swing.AbstractButton; ">
@@ -106,13 +106,13 @@
106106
<!ELEMENT radio-button-menu-item EMPTY>
107107
<!ATTLIST radio-button-menu-item %javax.swing.JRadioButtonMenuItem;>
108108
<!ENTITY % org.httprpc.sierra.BoxPanel "%org.httprpc.sierra.LayoutPanel; spacing CDATA ">
109-
<!ENTITY % org.httprpc.sierra.MenuButton "%javax.swing.JButton; popupHorizontalAlignment (leading|trailing|center) popupVerticalAlignment (top|bottom|center) ">
109+
<!ENTITY % org.httprpc.sierra.MenuButton "%javax.swing.JButton; popupHorizontalAlignment (left|right|leading|trailing|center) popupVerticalAlignment (top|bottom|center) ">
110110
<!ELEMENT menu-button (ANY)>
111111
<!ATTLIST menu-button %org.httprpc.sierra.MenuButton;>
112112
<!ENTITY % org.httprpc.sierra.NumberField "%javax.swing.JTextField; value CDATA ">
113113
<!ELEMENT number-field EMPTY>
114114
<!ATTLIST number-field %org.httprpc.sierra.NumberField;>
115-
<!ENTITY % org.httprpc.sierra.Picker "%javax.swing.JTextField; popupHorizontalAlignment (leading|trailing|center) popupVerticalAlignment (top|bottom|center) ">
115+
<!ENTITY % org.httprpc.sierra.Picker "%javax.swing.JTextField; popupHorizontalAlignment (left|right|leading|trailing|center) popupVerticalAlignment (top|bottom|center) ">
116116
<!ENTITY % org.httprpc.sierra.StackPanel "%org.httprpc.sierra.LayoutPanel; ">
117117
<!ELEMENT stack-panel (ANY)>
118118
<!ATTLIST stack-panel %org.httprpc.sierra.StackPanel;>

0 commit comments

Comments
 (0)