This is an automated email from the ASF dual-hosted git repository. ntimofeev pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 652ede9647d0db7508995b11304312d5b2cc4884 Author: Ivan Nikitka <[email protected]> AuthorDate: Fri Sep 23 16:35:04 2022 +0200 template editor feature --- .../apache/cayenne/gen/ClassGenerationAction.java | 19 +- modeler/cayenne-modeler/pom.xml | 6 + .../modeler/dialog/pref/TemplatePreferences.java | 9 +- .../dialog/pref/TemplatePreferencesView.java | 7 + .../dialog/templateeditor/FileTemplateSaver.java | 60 ++ .../templateeditor/FindAndReplaceController.java | 121 +++ .../dialog/templateeditor/FindAndReplaceView.java | 88 ++ .../dialog/templateeditor/FindController.java | 110 ++ .../modeler/dialog/templateeditor/FindView.java | 101 ++ .../PreviewClassGenerationFactory.java | 55 + .../templateeditor/PreviewGenerationAction.java | 64 ++ .../templateeditor/TemplateEditorController.java | 201 ++++ .../dialog/templateeditor/TemplateEditorView.java | 187 ++++ .../dialog/templateeditor/TemplateLoader.java | 58 ++ .../dialog/templateeditor/VelocityTokenMaker.java | 1065 ++++++++++++++++++++ .../modeler/images/icon-find_and_replace.png | Bin 0 -> 620 bytes pom.xml | 5 + 17 files changed, 2147 insertions(+), 9 deletions(-) diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java index 8a5ca11b6..17315e01a 100644 --- a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java @@ -270,13 +270,7 @@ public class ClassGenerationAction { if (template == null) { Properties props = new Properties(); - - props.put("resource.loaders", "cayenne"); - props.put("resource.loader.cayenne.class", ClassGeneratorResourceLoader.class.getName()); - props.put("resource.loader.cayenne.cache", "false"); - if (cgenConfiguration.getRootPath() != null) { - props.put("resource.loader.cayenne.root", cgenConfiguration.getRootPath().toString()); - } + initVelocityProperties(props); VelocityEngine velocityEngine = new VelocityEngine(); velocityEngine.init(props); @@ -288,12 +282,21 @@ public class ClassGenerationAction { return template; } + protected void initVelocityProperties(Properties props) { + props.put("resource.loaders", "cayenne"); + props.put("resource.loader.cayenne.class", ClassGeneratorResourceLoader.class.getName()); + props.put("resource.loader.cayenne.cache", "false"); + if (cgenConfiguration.getRootPath() != null) { + props.put("resource.loader.cayenne.root", cgenConfiguration.getRootPath().toString()); + } + } + /** * Validates the state of this class generator. * Throws CayenneRuntimeException if it is in an inconsistent state. * Called internally from "execute". */ - private void validateAttributes() { + protected void validateAttributes() { Path dir = cgenConfiguration.buildPath(); if (dir == null) { throw new CayenneRuntimeException("'rootPath' attribute is missing."); diff --git a/modeler/cayenne-modeler/pom.xml b/modeler/cayenne-modeler/pom.xml index 4cff481c9..0a2bf1707 100644 --- a/modeler/cayenne-modeler/pom.xml +++ b/modeler/cayenne-modeler/pom.xml @@ -101,5 +101,11 @@ <artifactId>junit</artifactId> <scope>test</scope> </dependency> + + <dependency> + <groupId>com.fifesoft</groupId> + <artifactId>rsyntaxtextarea</artifactId> + </dependency> + </dependencies> </project> diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TemplatePreferences.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TemplatePreferences.java index d531be754..520a5cf59 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TemplatePreferences.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TemplatePreferences.java @@ -20,6 +20,7 @@ package org.apache.cayenne.modeler.dialog.pref; import org.apache.cayenne.modeler.CodeTemplateManager; +import org.apache.cayenne.modeler.dialog.templateeditor.TemplateEditorController; import org.apache.cayenne.modeler.pref.FSPath; import org.apache.cayenne.modeler.util.CayenneController; import org.apache.cayenne.pref.CayennePreferenceEditor; @@ -89,6 +90,7 @@ public class TemplatePreferences extends CayenneController { builder.bindToAction(view.getAddButton(), "addTemplateAction()"); builder.bindToAction(view.getCreateFromDefaultButton(), "createFromDefaultAction()"); builder.bindToAction(view.getRemoveButton(), "removeTemplateAction()"); + builder.bindToAction(view.getTemplateEditorButton(), "templateEditorAction()"); TableBindingBuilder tableBuilder = new TableBindingBuilder(builder); @@ -123,6 +125,11 @@ public class TemplatePreferences extends CayenneController { addToTemplateEntries(path); } + @SuppressWarnings("unused") + public void templateEditorAction() { + new TemplateEditorController(this).startupAction(); + } + @SuppressWarnings("unused") public void createFromDefaultAction() { List<FSPath> paths = new CreateTemplateFromDefaultController(this).startupAction(); @@ -150,7 +157,7 @@ public class TemplatePreferences extends CayenneController { addToTemplateEntries(path); } - private void addToTemplateEntries(FSPath path) { + public void addToTemplateEntries(FSPath path) { if (path != null) { int len = templateEntries.size(); templateEntries.add(path); diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TemplatePreferencesView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TemplatePreferencesView.java index 5e35f3fb7..71466287c 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TemplatePreferencesView.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TemplatePreferencesView.java @@ -36,6 +36,7 @@ public class TemplatePreferencesView extends JPanel { protected JButton addButton; protected JButton createFromDefaultButton; protected JButton removeButton; + protected JButton templateEditorButton; protected JTable table; public TemplatePreferencesView() { @@ -43,6 +44,7 @@ public class TemplatePreferencesView extends JPanel { // create widgets addButton = new JButton("Add Template"); createFromDefaultButton = new JButton("Create from default"); + templateEditorButton = new JButton("Edit template"); removeButton = new JButton("Remove Template"); table = new CayenneTable(); @@ -57,6 +59,7 @@ public class TemplatePreferencesView extends JPanel { builder.append(addButton); builder.append(createFromDefaultButton); + builder.append(templateEditorButton); builder.append(removeButton); setLayout(new BorderLayout()); @@ -81,4 +84,8 @@ public class TemplatePreferencesView extends JPanel { public JButton getRemoveButton() { return removeButton; } + + public JButton getTemplateEditorButton() { + return templateEditorButton; + } } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FileTemplateSaver.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FileTemplateSaver.java new file mode 100644 index 000000000..c735af63d --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FileTemplateSaver.java @@ -0,0 +1,60 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.SwingConstants; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +/** + * since 4.3 + */ +public class FileTemplateSaver { + + private static final Logger logger = LoggerFactory.getLogger(FileTemplateSaver.class); + + public void save(String templateText, File dest, JDialog view) { + try { + Files.write(dest.toPath(), templateText.getBytes()); + } catch (IOException e) { + JOptionPane.showMessageDialog( + view, + "File writing error \n" + dest, + "Error", + JOptionPane.WARNING_MESSAGE); + logger.warn("File writing error {}", dest); + } + JOptionPane.showMessageDialog( + view, + new JLabel("The changes in the \n" + + dest + + "\n have been saved", SwingConstants.CENTER), + "Message", + JOptionPane.PLAIN_MESSAGE); + logger.info("Change the template {}", dest); + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindAndReplaceController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindAndReplaceController.java new file mode 100644 index 000000000..3b88e0306 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindAndReplaceController.java @@ -0,0 +1,121 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + +import org.fife.ui.rtextarea.SearchContext; +import org.fife.ui.rtextarea.SearchEngine; + +import javax.swing.JButton; +import javax.swing.JOptionPane; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * since 4.3 + */ +public class FindAndReplaceController extends FindController implements ActionListener { + + private FindAndReplaceView view; + private JButton nextButton; + private JButton replaceButton; + private JButton replaceAllButton; + + public FindAndReplaceController(TemplateEditorController parent) { + super(parent); + initComponents(); + initListeners(); + } + + @Override + protected void initComponents() { + this.view = new FindAndReplaceView(); + this.nextButton = view.getNextButton(); + this.replaceButton = view.getReplaceButton(); + this.replaceAllButton = view.getReplaceAllButton(); + } + + @Override + protected void initListeners() { + nextButton.setActionCommand("findNext"); + nextButton.addActionListener(this); + replaceButton.setActionCommand("replace"); + replaceButton.addActionListener(this); + replaceAllButton.setActionCommand("replaceAll"); + replaceAllButton.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + String command = e.getActionCommand(); + SearchContext context = getSearchContext(true,view); + if (context == null) return; + switch (command) { + case "findNext": { + boolean found = SearchEngine.find(parentView.getEditingTemplatePane(), context).wasFound(); + if (!found) { + JOptionPane.showMessageDialog(view, TEXT_NOT_FOUND_MSG); + } + break; + } + case "replace": { + boolean found = SearchEngine.replace(parentView.getEditingTemplatePane(), context).wasFound(); + if (!found) { + JOptionPane.showMessageDialog(view, TEXT_NOT_FOUND_MSG); + } + break; + } + case "replaceAll": { + boolean found = SearchEngine.replaceAll(parentView.getEditingTemplatePane(), context).wasFound(); + if (!found) { + JOptionPane.showMessageDialog(view, TEXT_NOT_FOUND_MSG); + } + break; + } + default: + break; + } + } + + @Override + protected SearchContext getSearchContext(boolean forward, FindView view) { + SearchContext context = super.getSearchContext(forward,view); + context.setReplaceWith(this.view.getReplaceWithField().getText()); + return context; + } + + @Override + public Component getView() { + return view; + } + + /** + * Pops up a dialog and blocks current thread until the dialog is closed. + */ + @Override + public void startupAction() { + view.setModal(true); + view.pack(); + view.setResizable(false); + makeCloseableOnEscape(); + centerView(); + view.setVisible(true); + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindAndReplaceView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindAndReplaceView.java new file mode 100644 index 000000000..19a9b7eb0 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindAndReplaceView.java @@ -0,0 +1,88 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + +import com.jgoodies.forms.builder.PanelBuilder; +import com.jgoodies.forms.layout.CellConstraints; +import com.jgoodies.forms.layout.FormLayout; + +import javax.swing.JButton; +import javax.swing.JTextField; +import java.awt.BorderLayout; + +/** + * since 4.3 + */ +public class FindAndReplaceView extends FindView { + + private JTextField replaceWithField; + private JButton replaceButton; + private JButton replaceAllButton; + + public FindAndReplaceView() { + initComponents(); + buildView(); + } + + @Override + protected void initComponents() { + super.initComponents(); + this.replaceWithField = new JTextField(); + this.replaceButton = new JButton("Replace"); + this.replaceAllButton = new JButton("Replace all"); + } + + @Override + protected void buildView() { + this.setTitle("Find and replace dialog"); + CellConstraints cc = new CellConstraints(); + PanelBuilder builder = new PanelBuilder(new FormLayout(COLUMN_SPECS, ROW_SPECS)); + builder.setDefaultDialogBorder(); + + builder.addLabel("Find what:", cc.xy(1, 1)); + builder.add(searchField, cc.xyw(3, 1, 3)); + builder.addLabel("Replace with:", cc.xy(1, 3)); + builder.add(replaceWithField, cc.xyw(3, 3, 3)); + builder.add(regexCB, cc.xy(1, 5)); + builder.add(matchCaseCB, cc.xy(3, 5)); + builder.add(wholeWordCB, cc.xy(5, 5)); + + builder.add(nextButton, cc.xy(7, 1)); + builder.add(replaceButton, cc.xy(7, 3)); + builder.add(replaceAllButton, cc.xy(7, 5)); + + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(builder.getPanel(), BorderLayout.CENTER); + } + + public JTextField getReplaceWithField() { + return replaceWithField; + } + + public JButton getReplaceButton() { + return replaceButton; + } + + public JButton getReplaceAllButton() { + return replaceAllButton; + } + + +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindController.java new file mode 100644 index 000000000..8515f012e --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindController.java @@ -0,0 +1,110 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + +import org.apache.cayenne.modeler.util.CayenneController; +import org.apache.cayenne.util.Util; +import org.fife.ui.rtextarea.SearchContext; +import org.fife.ui.rtextarea.SearchEngine; + +import javax.swing.JButton; +import javax.swing.JOptionPane; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * since 4.3 + */ +public class FindController extends CayenneController implements ActionListener { + + private FindView view; + protected TemplateEditorView parentView; + private JButton nextButton; + private JButton prevButton; + protected static final String TEXT_NOT_FOUND_MSG = "Text not found"; + + public FindController(TemplateEditorController parent) { + super(parent); + this.parentView = (TemplateEditorView) parent.getView(); + initComponents(); + initListeners(); + } + + protected void initComponents() { + this.view = new FindView(); + this.nextButton = this.view.getNextButton(); + this.prevButton = this.view.getPrevButton(); + } + + @Override + public Component getView() { + return view; + } + + protected void initListeners() { + nextButton.setActionCommand("FindNext"); + nextButton.addActionListener(this); + prevButton.setActionCommand("FindPrev"); + prevButton.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + + // "FindNext" => search forward, "FindPrev" => search backward + String command = e.getActionCommand(); + boolean forward = "FindNext".equals(command); + + SearchContext context = getSearchContext(forward, view); + if (context == null) return; + + boolean found = SearchEngine.find(parentView.getEditingTemplatePane(), context).wasFound(); + if (!found) { + JOptionPane.showMessageDialog(view, TEXT_NOT_FOUND_MSG); + } + } + + protected SearchContext getSearchContext(boolean forward, FindView view) { + SearchContext context = new SearchContext(); + String text = view.getSearchField().getText(); + if (Util.isEmptyString(text)) { + return null; + } + context.setSearchFor(text); + context.setMatchCase(view.getMatchCaseCB().isSelected()); + context.setRegularExpression(view.getRegexCB().isSelected()); + context.setWholeWord(view.getWholeWordCB().isSelected()); + context.setSearchForward(forward); + return context; + } + + /** + * Pops up a dialog and blocks current thread until the dialog is closed. + */ + public void startupAction() { + view.setModal(true); + view.pack(); + view.setResizable(false); + makeCloseableOnEscape(); + centerView(); + view.setVisible(true); + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindView.java new file mode 100644 index 000000000..118d1e5a4 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/FindView.java @@ -0,0 +1,101 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + +import com.jgoodies.forms.builder.PanelBuilder; +import com.jgoodies.forms.layout.CellConstraints; +import com.jgoodies.forms.layout.FormLayout; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JTextField; +import java.awt.BorderLayout; + +/** + * since 4.3 + */ +public class FindView extends JDialog { + + protected JTextField searchField; + protected JCheckBox regexCB; + protected JCheckBox matchCaseCB; + protected JCheckBox wholeWordCB; + protected JButton nextButton; + private JButton prevButton; + protected static final String COLUMN_SPECS = "left:pref, 3dlu, left:pref,3dlu, 110dlu, 3dlu, fill:p:grow"; + protected static final String ROW_SPECS = "4 * (p, 3dlu)"; + + public FindView() { + initComponents(); + buildView(); + } + + protected void initComponents() { + this.searchField = new JTextField(); + this.regexCB = new JCheckBox("Regex"); + this.matchCaseCB = new JCheckBox("Match Case"); + this.wholeWordCB = new JCheckBox("Whole word"); + this.nextButton = new JButton("Find Next"); + this.prevButton = new JButton("Find Previous"); + } + + protected void buildView() { + this.setTitle("Find dialog"); + CellConstraints cc = new CellConstraints(); + PanelBuilder builder = new PanelBuilder(new FormLayout(COLUMN_SPECS, ROW_SPECS)); + builder.setDefaultDialogBorder(); + + builder.addLabel("Find what:", cc.xy(1, 1)); + builder.add(searchField, cc.xyw(3, 1, 3)); + builder.add(regexCB, cc.xy(1, 3)); + builder.add(matchCaseCB, cc.xy(3, 3)); + builder.add(wholeWordCB, cc.xy(5, 3)); + builder.add(nextButton, cc.xy(7, 1)); + builder.add(prevButton, cc.xy(7, 3)); + + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(builder.getPanel(), BorderLayout.CENTER); + } + + public JTextField getSearchField() { + return searchField; + } + + public JCheckBox getRegexCB() { + return regexCB; + } + + public JCheckBox getMatchCaseCB() { + return matchCaseCB; + } + + public JButton getNextButton() { + return nextButton; + } + + public JButton getPrevButton() { + return prevButton; + } + + public JCheckBox getWholeWordCB() { + return wholeWordCB; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/PreviewClassGenerationFactory.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/PreviewClassGenerationFactory.java new file mode 100644 index 000000000..f8bba275b --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/PreviewClassGenerationFactory.java @@ -0,0 +1,55 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.gen.CgenConfiguration; +import org.apache.cayenne.gen.ClassGenerationAction; +import org.apache.cayenne.gen.ClassGenerationActionFactory; +import org.apache.cayenne.gen.MetadataUtils; +import org.apache.cayenne.gen.ToolsUtilsFactory; + +import java.io.StringWriter; + + +/** + * @since 4.3 + */ +public class PreviewClassGenerationFactory implements ClassGenerationActionFactory { + + @Inject + private ToolsUtilsFactory utilsFactory; + + @Inject + private MetadataUtils metadataUtils; + + @Inject + private StringWriter writer; + + @Override + public ClassGenerationAction createAction(CgenConfiguration cgenConfiguration) { + PreviewGenerationAction action = new PreviewGenerationAction(cgenConfiguration); + action.setUtilsFactory(utilsFactory); + action.setMetadataUtils(metadataUtils); + action.setWriter(writer); + return action; + } + +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/PreviewGenerationAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/PreviewGenerationAction.java new file mode 100644 index 000000000..7be3de7aa --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/PreviewGenerationAction.java @@ -0,0 +1,64 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + + +import org.apache.cayenne.gen.CgenConfiguration; +import org.apache.cayenne.gen.ClassGenerationAction; +import org.apache.cayenne.gen.TemplateType; +import org.apache.velocity.runtime.RuntimeConstants; +import org.apache.velocity.runtime.resource.loader.StringResourceLoader; + +import java.io.Writer; +import java.util.Properties; + +/** + * @since 4.3 + */ +public class PreviewGenerationAction extends ClassGenerationAction { + + private Writer writer; + + public PreviewGenerationAction(CgenConfiguration cgenConfig) { + super(cgenConfig); + } + + @Override + protected void validateAttributes() { + //Mock + } + + public void setWriter(Writer writer) { + this.writer = writer; + } + + @Override + protected Writer openWriter(TemplateType templateType) { + return writer; + } + + @Override + protected void initVelocityProperties(Properties props) { + props.setProperty(RuntimeConstants.RESOURCE_LOADERS, "string"); + props.setProperty("resource.loader.string.class", StringResourceLoader.class.getName()); + props.setProperty("resource.loader.string.repository.name",TemplateEditorController.TEMPLATE_EDITOR_REPO); + } + +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/TemplateEditorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/TemplateEditorController.java new file mode 100644 index 000000000..8c20aac4b --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/TemplateEditorController.java @@ -0,0 +1,201 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + +import org.apache.cayenne.configuration.xml.DataChannelMetaData; +import org.apache.cayenne.di.Injector; +import org.apache.cayenne.gen.CgenConfiguration; +import org.apache.cayenne.gen.ClassGenerationAction; +import org.apache.cayenne.gen.ClassGenerationActionFactory; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.modeler.dialog.pref.TemplatePreferences; +import org.apache.cayenne.modeler.dialog.pref.TemplatePreferencesView; +import org.apache.cayenne.modeler.util.CayenneController; +import org.apache.cayenne.swing.BindingBuilder; +import org.apache.cayenne.tools.ToolsInjectorBuilder; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.runtime.resource.loader.StringResourceLoader; +import org.apache.velocity.runtime.resource.util.StringResourceRepository; +import org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl; + +import javax.swing.text.BadLocationException; +import java.awt.Component; +import java.io.File; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * since 4.3 + */ +public class TemplateEditorController extends CayenneController { + + protected TemplatePreferencesView preferencesView; + protected TemplateEditorView view; + protected boolean canceled; + private final Map<String, String> customTemplates; + private static final String EDITED_TEMPLATE = "editedTemplate"; + public static final String TEMPLATE_EDITOR_REPO = "templateEditorRepo"; + private final DataMap currentDataMap; + + public TemplateEditorController(TemplatePreferences preferences) { + super(preferences); + this.preferencesView = (TemplatePreferencesView) preferences.getView(); + this.customTemplates = application.getCodeTemplateManager().getCustomTemplates(); + this.currentDataMap = application.getFrameController().getProjectController().getCurrentDataMap(); + this.view = new TemplateEditorView( getEntityNames()); + initBindings(); + } + + public void startupAction() { + this.view.setModal(true); + this.view.getEditingTemplatePane().setText(loadSelectedTemplateText()); + this.view.editingTemplatePane.setCaretPosition(0); + this.view.pack(); + makeCloseableOnEscape(); + centerView(); + this.view.setVisible(true); + } + + private String loadSelectedTemplateText() { + TemplateLoader templateLoader = new TemplateLoader(); + return templateLoader.load(view, getSelectedTemplate()); + } + + public Component getView() { + return view; + } + + protected void initBindings() { + BindingBuilder builder = new BindingBuilder(getApplication().getBindingFactory(), this); + builder.bindToAction(view.getSaveButton(), "saveAction()"); + builder.bindToAction(view.getPreviewButton(), "generateAction()"); + builder.bindToAction(view.getFindButton(), "findAction()"); + builder.bindToAction(view.getFindAndReplaceButton(), "findAndReplaceAction()"); + } + + @SuppressWarnings("unused") + public void saveAction() { + if (getSelectedTemplate() != null) { + File dest = new File(getSelectedTemplate()); + FileTemplateSaver templateSaver = new FileTemplateSaver(); + templateSaver.save(view.getTemplateText(),dest,view); + } + } + + public String getSelectedTemplate() { + int selectedRow = preferencesView.getTable().getSelectedRow(); + if (selectedRow != -1) { + Object key = preferencesView.getTable().getModel().getValueAt(selectedRow, 0); + return customTemplates.get(key.toString()); + } + return null; + } + + @SuppressWarnings("unused") + public void generateAction() throws Exception { + putTemplateTextInRepository(); + Injector injector = getInjector(); + ClassGenerationAction action = injector + .getInstance(ClassGenerationActionFactory.class) + .createAction(getCgenConfiguration()); + StringWriter writer = injector.getInstance(StringWriter.class); + action.addEntities(Collections.singleton(getSelectedEntity())); + int caretPosition = view.getEditingTemplatePane().getCaretPosition(); + try { + action.execute(); + } catch (Exception e) { + if (e instanceof ParseErrorException) { + caretPosition = getErrorCaretPosition((ParseErrorException) e); + } + writer.write(e.getMessage()); + } + view.getEditingTemplatePane().setCaretPosition(caretPosition); + view.getClassPreviewPane().setText(writer.toString()); + view.getClassPreviewPane().setCaretPosition(0); + } + + private void putTemplateTextInRepository() { + StringResourceLoader.setRepository(TEMPLATE_EDITOR_REPO, new StringResourceRepositoryImpl()); + StringResourceRepository repo = StringResourceLoader.getRepository(TEMPLATE_EDITOR_REPO); + repo.putStringResource(EDITED_TEMPLATE, view.getTemplateText()); + } + + private Injector getInjector() { + DataChannelMetaData metaData = getApplication().getMetaData(); + return new ToolsInjectorBuilder() + .addModule(binder -> binder.bind(DataChannelMetaData.class).toInstance(metaData)) + .addModule(binder -> binder.bind(ClassGenerationActionFactory.class).to(PreviewClassGenerationFactory.class)) + .addModule(binder -> binder.bind(StringWriter.class).to(StringWriter.class)) + .create(); + } + + private CgenConfiguration getCgenConfiguration() { + CgenConfiguration cgenConfiguration = new CgenConfiguration(); + cgenConfiguration.setMakePairs(false); + cgenConfiguration.setTemplate(EDITED_TEMPLATE); + cgenConfiguration.setDataMap(currentDataMap); + return cgenConfiguration; + } + + private int getErrorCaretPosition(ParseErrorException e) throws BadLocationException { + int errorLineNumber = e.getLineNumber(); + return view.getEditingTemplatePane().getLineStartOffset(errorLineNumber - 1); + } + + @SuppressWarnings("unused") + public void findAction() { + new FindController(this).startupAction(); + } + + @SuppressWarnings("unused") + public void findAndReplaceAction() { + new FindAndReplaceController(this).startupAction(); + } + + private ObjEntity getSelectedEntity() { + String selectedEntityName = view.getSelectedEntityName(); + ObjEntity selectedObject = null; + Collection<ObjEntity> objEntities = currentDataMap.getObjEntities(); + for (ObjEntity object : objEntities) { + if (selectedEntityName.equals(object.getName())) { + selectedObject = object; + } + } + return selectedObject; + } + + private List<String> getEntityNames() { + ArrayList<String> names = new ArrayList<>(); + if (currentDataMap != null) { + Object[] objEntities = currentDataMap.getObjEntities().toArray(); + for (Object objEntity : objEntities) { + ObjEntity s = (ObjEntity) objEntity; + names.add(s.getName()); + } + } + return names; + } + +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/TemplateEditorView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/TemplateEditorView.java new file mode 100644 index 000000000..4580dbd34 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/TemplateEditorView.java @@ -0,0 +1,187 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + +import com.jgoodies.forms.builder.PanelBuilder; +import com.jgoodies.forms.layout.CellConstraints; +import com.jgoodies.forms.layout.FormLayout; +import org.apache.cayenne.modeler.pref.ComponentGeometry; +import org.apache.cayenne.modeler.util.ModelerUtil; +import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory; +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; +import org.fife.ui.rsyntaxtextarea.TextEditorPane; +import org.fife.ui.rsyntaxtextarea.TokenMakerFactory; +import org.fife.ui.rtextarea.RTextScrollPane; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.util.List; + +/** + * since 4.3 + */ +public class TemplateEditorView extends JDialog { + + protected RSyntaxTextArea editingTemplatePane; + protected RSyntaxTextArea classPreviewPane; + + protected JButton previewButton; + protected JButton saveButton; + protected JButton findButton; + protected JButton findAndReplaceButton; + protected JComboBox<Object> entityComboBox; + private JSplitPane split; + private JToolBar toolBar; + private JPanel topPanel; + static final String VELOCITY_KEY = "text/velocity"; + + + public TemplateEditorView( List<String> entityNames) { + this.setTitle("Template editor"); + this.editingTemplatePane = new TextEditorPane(); + this.classPreviewPane = new RSyntaxTextArea(); + initToolBoxComponents(entityNames); + mapVelocityTokenMaker(); + buildView(); + bindGeometry(); + } + + private void initToolBoxComponents(List<String> entityNames) { + this.saveButton = new JButton(ModelerUtil.buildIcon("icon-save.png")); + this.saveButton.setToolTipText("Save"); + this.findButton = new JButton(ModelerUtil.buildIcon("icon-query.png")); + this.findButton.setToolTipText("Find"); + this.findAndReplaceButton = new JButton(ModelerUtil.buildIcon("icon-find_and_replace.png")); + this.findAndReplaceButton.setToolTipText("Find and replace"); + this.previewButton = new JButton(ModelerUtil.buildIcon("icon-edit.png")); + this.previewButton.setToolTipText("Generate preview"); + this.entityComboBox = new JComboBox<>(entityNames.toArray()); + this.entityComboBox.setToolTipText("Select an entity for the test"); + } + + private void buildView() { + initSplitPanel(); + initToolBar(); + initTopPanel(); + + getRootPane().setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(topPanel, BorderLayout.NORTH); + getContentPane().add(split, BorderLayout.CENTER); + } + + private void initSplitPanel() { + editingTemplatePane.setSyntaxEditingStyle(VELOCITY_KEY); + editingTemplatePane.setMarkOccurrences(true); + RTextScrollPane leftPanel = new RTextScrollPane(editingTemplatePane); + + classPreviewPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + classPreviewPane.setEnabled(false); + RTextScrollPane rightPanel = new RTextScrollPane(classPreviewPane); + + split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel); + split.setPreferredSize(new Dimension(1200, 700)); + split.setDividerSize(6); + split.setDividerLocation(1.0); + } + + private void initToolBar() { + toolBar = new JToolBar(); + toolBar.setBorder(BorderFactory.createEmptyBorder()); + toolBar.setFloatable(false); + toolBar.add(saveButton); + toolBar.addSeparator(); + toolBar.add(findButton); + toolBar.add(findAndReplaceButton); + toolBar.addSeparator(); + toolBar.add(previewButton); + toolBar.add(entityComboBox); + } + + private void initTopPanel() { + CellConstraints constraintsTop = new CellConstraints(); + PanelBuilder topPanelBuilder = new PanelBuilder(new FormLayout( + "left:pref:grow, right:pref", "p, 3dlu, p, 3dlu, p")); + topPanelBuilder.setDefaultDialogBorder(); + topPanelBuilder.add(toolBar, constraintsTop.xy(1, 1)); + topPanelBuilder.addSeparator("", constraintsTop.xyw(1, 3, 2)); + topPanelBuilder.addLabel("Editing template", constraintsTop.xy(1, 5)); + topPanelBuilder.addLabel("Class preview", constraintsTop.xy(2, 5)); + topPanel = topPanelBuilder.getPanel(); + } + + private void bindGeometry() { + ComponentGeometry geometry = new ComponentGeometry(this.getClass(), "split/divider"); + geometry.bindIntProperty(split, JSplitPane.DIVIDER_LOCATION_PROPERTY, 600); + geometry.bind(this, 1200, 700, 0); + } + + private void mapVelocityTokenMaker() { + AbstractTokenMakerFactory tokenMakerFactory = (AbstractTokenMakerFactory) TokenMakerFactory.getDefaultInstance(); + tokenMakerFactory.putMapping(VELOCITY_KEY, VelocityTokenMaker.class.getName()); + } + + public String getSelectedEntityName() { + Object selectedItem = entityComboBox.getSelectedItem(); + if (selectedItem != null) { + return selectedItem.toString(); + } + return null; + } + + public JButton getPreviewButton() { + return previewButton; + } + + public JButton getSaveButton() { + return saveButton; + } + + public JButton getFindButton() { + return findButton; + } + + public JButton getFindAndReplaceButton() { + return findAndReplaceButton; + } + + public String getTemplateText() { + return editingTemplatePane.getText(); + } + + public RSyntaxTextArea getEditingTemplatePane() { + return editingTemplatePane; + } + + public RSyntaxTextArea getClassPreviewPane() { + return classPreviewPane; + } + +} + + diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/TemplateLoader.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/TemplateLoader.java new file mode 100644 index 000000000..7e5727036 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/TemplateLoader.java @@ -0,0 +1,58 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.templateeditor; + +import org.apache.velocity.exception.ResourceNotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.JOptionPane; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +/** + * since 4.3 + */ +public class TemplateLoader { + + private static final Logger logger = LoggerFactory.getLogger(TemplateLoader.class); + + public String load(TemplateEditorView view, String selectedTemplate) { + StringBuilder stringBuilder = new StringBuilder(); + if (selectedTemplate != null) { + try { + List<String> strings = Files.readAllLines(Paths.get(selectedTemplate)); + for (String string : strings) { + stringBuilder.append(string).append("\n"); + } + } catch (IOException | ResourceNotFoundException e) { + JOptionPane.showMessageDialog( + view, + "File reading error \n" + selectedTemplate, + "Error", + JOptionPane.WARNING_MESSAGE); + logger.warn("File reading error {}", selectedTemplate); + } + } + return stringBuilder.toString(); + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/VelocityTokenMaker.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/VelocityTokenMaker.java new file mode 100644 index 000000000..51b4104d2 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/templateeditor/VelocityTokenMaker.java @@ -0,0 +1,1065 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.modeler.dialog.templateeditor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import javax.swing.text.Segment; + +import org.fife.ui.rsyntaxtextarea.AbstractJFlexCTokenMaker; +import org.fife.ui.rsyntaxtextarea.Token; +import org.fife.ui.rsyntaxtextarea.TokenImpl; + + +/** + * since 4.3 + */ +public class VelocityTokenMaker extends AbstractJFlexCTokenMaker { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int EOL_COMMENT = 2; + public static final int YYINITIAL = 0; + public static final int MLC = 1; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\21\1\10\1\0\1\21\1\17\22\0\1\21\1\43\1\15"+ + "\1\20\1\1\1\47\1\45\1\7\2\44\1\22\1\46\1\41\1\26"+ + "\1\24\1\50\1\4\3\16\4\6\2\3\1\54\1\41\1\71\1\70"+ + "\1\72\1\43\1\42\1\35\1\56\1\5\1\60\1\25\1\33\1\65"+ + "\1\51\1\53\1\67\1\57\1\36\1\64\1\61\1\63\1\52\1\1"+ + "\1\31\1\37\1\27\1\12\1\62\1\55\1\23\1\66\1\1\1\44"+ + "\1\11\1\44\1\73\1\2\1\0\1\35\1\14\1\5\1\60\1\25"+ + "\1\34\1\65\1\75\1\53\1\67\1\57\1\36\1\64\1\13\1\63"+ + "\1\52\1\1\1\32\1\37\1\30\1\12\1\62\1\76\1\23\1\66"+ + "\1\1\1\40\1\74\1\40\1\43\uff81\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\3\0\2\1\2\2\1\3\1\4\1\1\1\5\1\1"+ + "\1\6\1\7\2\1\1\7\3\1\1\10\3\7\2\1"+ + "\3\7\1\11\1\12\10\11\1\13\6\11\1\0\1\14"+ + "\1\0\2\14\1\3\1\15\1\0\1\3\1\1\2\5"+ + "\1\16\1\0\1\17\1\20\7\0\1\21\7\1\1\22"+ + "\2\11\2\0\2\11\2\0\2\11\2\0\2\11\3\0"+ + "\1\21\1\0\1\23\1\3\1\24\2\3\1\15\1\3"+ + "\1\1\1\5\1\25\1\5\11\0\1\26\2\0\10\1"+ + "\2\11\2\0\2\11\2\0\2\11\2\0\2\11\3\0"+ + "\1\3\1\5\11\0\1\1\1\27\6\1\1\11\1\0"+ + "\2\11\1\30\1\0\1\11\1\0\2\11\1\31\2\0"+ + "\1\3\1\5\1\0\1\26\6\0\6\1\1\11\2\0"+ + "\1\11\3\0\1\3\1\5\4\0\3\1\1\32\2\0"+ + "\14\1"; + + private static int [] zzUnpackAction() { + int [] result = new int[224]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\77\0\176\0\275\0\374\0\u013b\0\u017a\0\u01b9"+ + "\0\275\0\u01f8\0\u0237\0\u0276\0\u02b5\0\u02f4\0\u0333\0\u0372"+ + "\0\u03b1\0\u03f0\0\u042f\0\u046e\0\275\0\275\0\u04ad\0\u04ec"+ + "\0\u052b\0\u056a\0\u05a9\0\u05e8\0\u0627\0\u0666\0\275\0\u06a5"+ + "\0\u06e4\0\u0723\0\u0762\0\u07a1\0\u07e0\0\u081f\0\u085e\0\275"+ + "\0\u089d\0\u08dc\0\u091b\0\u095a\0\u0999\0\u09d8\0\u0a17\0\u0a56"+ + "\0\u0333\0\u0a95\0\u0ad4\0\u0b13\0\275\0\u0b52\0\u0b91\0\u0bd0"+ + "\0\u0c0f\0\u0c4e\0\275\0\u0c8d\0\275\0\275\0\u0ccc\0\u0d0b"+ + "\0\u0d4a\0\u0d89\0\u0dc8\0\u0e07\0\u0e46\0\u0e85\0\u0ec4\0\u0f03"+ + "\0\u0f42\0\u0f81\0\u0fc0\0\u0fff\0\u103e\0\275\0\u107d\0\u10bc"+ + "\0\u10fb\0\u113a\0\u1179\0\u11b8\0\u11f7\0\u1236\0\u1275\0\u12b4"+ + "\0\u12f3\0\u1332\0\u1371\0\u13b0\0\u13ef\0\u142e\0\u146d\0\u14ac"+ + "\0\u14eb\0\u0ad4\0\u152a\0\275\0\u1569\0\u15a8\0\u0b52\0\u15e7"+ + "\0\u1626\0\u1665\0\275\0\u16a4\0\u16e3\0\u1722\0\u1761\0\u17a0"+ + "\0\u17df\0\u181e\0\u185d\0\u189c\0\u18db\0\275\0\u191a\0\u1959"+ + "\0\u1998\0\u19d7\0\u1a16\0\u1a55\0\u1a94\0\u1ad3\0\u1b12\0\u1b51"+ + "\0\u1b90\0\u1bcf\0\u1c0e\0\u1c4d\0\u1c8c\0\u1ccb\0\u1d0a\0\u1d49"+ + "\0\u1d88\0\u1dc7\0\u1e06\0\u1e45\0\u1e84\0\u1ec3\0\u1f02\0\u1f41"+ + "\0\u1f80\0\u1fbf\0\u1ffe\0\u203d\0\u207c\0\u20bb\0\u20fa\0\u2139"+ + "\0\u2178\0\u21b7\0\u21f6\0\u2235\0\u2274\0\374\0\u22b3\0\u22f2"+ + "\0\u2331\0\u2370\0\u23af\0\u23ee\0\u242d\0\u246c\0\u24ab\0\u24ea"+ + "\0\u2529\0\u2568\0\u25a7\0\u25e6\0\u2625\0\u2664\0\u26a3\0\u26e2"+ + "\0\u2721\0\u2760\0\u279f\0\u27de\0\u281d\0\u285c\0\u289b\0\u28da"+ + "\0\u2919\0\u2958\0\u2997\0\u29d6\0\u2a15\0\u2a54\0\u2a93\0\u2ad2"+ + "\0\u2b11\0\u2b50\0\u2b8f\0\u2529\0\u2bce\0\u2c0d\0\u26a3\0\u2c4c"+ + "\0\u2c8b\0\u2cca\0\u2d09\0\u2d48\0\u2d87\0\u2dc6\0\u2e05\0\u2e44"+ + "\0\u2e83\0\374\0\u2ec2\0\u2f01\0\u2f40\0\u2f7f\0\u2fbe\0\u2ffd"+ + "\0\u303c\0\u307b\0\u30ba\0\u30f9\0\u3138\0\u3177\0\u31b6\0\u31f5"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[224]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\1\4\2\5\1\6\1\7\1\5\1\6\1\10\1\11"+ + "\1\4\2\5\1\12\1\13\1\6\1\4\1\14\1\15"+ + "\1\16\1\5\1\17\1\20\1\21\2\22\2\5\2\23"+ + "\2\5\1\24\1\25\2\4\1\26\1\25\1\27\1\30"+ + "\2\16\2\5\1\31\1\26\1\5\1\12\4\5\1\32"+ + "\4\5\1\16\1\33\1\34\1\26\1\35\2\5\10\36"+ + "\1\37\11\36\1\40\10\36\1\41\1\42\14\36\1\43"+ + "\3\36\1\44\17\36\1\45\1\46\10\47\1\50\22\47"+ + "\1\51\1\52\14\47\1\53\3\47\1\54\17\47\1\55"+ + "\1\56\100\0\6\5\2\0\1\57\3\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\11\5\11\0\3\5"+ + "\1\0\13\5\5\0\2\5\3\60\2\6\1\60\1\6"+ + "\2\0\4\60\1\0\1\6\1\0\1\60\2\0\1\60"+ + "\1\61\1\62\1\0\11\60\2\0\1\60\6\0\3\60"+ + "\1\0\13\60\5\0\5\60\2\6\1\60\1\6\2\0"+ + "\4\60\1\0\1\6\1\0\1\60\2\0\1\63\1\61"+ + "\1\62\1\0\11\60\2\0\1\60\6\0\3\60\1\0"+ + "\13\60\5\0\2\60\7\64\1\65\1\66\1\67\65\64"+ + "\1\0\6\5\2\0\1\57\3\5\1\0\1\5\4\0"+ + "\1\5\1\0\1\5\1\0\6\5\1\70\2\5\11\0"+ + "\3\5\1\0\13\5\5\0\2\5\10\13\1\71\1\72"+ + "\3\13\1\73\61\13\14\0\1\74\3\0\1\75\1\0"+ + "\1\76\2\0\1\77\5\0\2\100\2\0\1\101\12\0"+ + "\1\102\1\103\2\0\1\74\1\0\1\104\3\0\1\105"+ + "\33\0\1\15\145\0\1\26\11\0\2\106\1\0\1\106"+ + "\7\0\1\106\61\0\6\5\2\0\1\57\1\5\1\107"+ + "\1\5\1\0\1\5\4\0\1\5\1\0\1\5\1\0"+ + "\11\5\11\0\3\5\1\0\4\5\1\107\6\5\5\0"+ + "\2\5\26\0\1\26\41\0\1\26\7\0\6\5\2\0"+ + "\1\57\3\5\1\0\1\5\4\0\1\5\1\0\1\5"+ + "\1\0\2\5\2\110\5\5\11\0\3\5\1\0\13\5"+ + "\5\0\2\5\1\0\6\5\2\0\1\57\3\5\1\0"+ + "\1\5\4\0\1\5\1\0\1\5\1\0\6\5\1\111"+ + "\2\5\11\0\3\5\1\0\13\5\5\0\2\5\1\0"+ + "\6\5\2\0\1\57\1\112\2\5\1\0\1\5\4\0"+ + "\1\5\1\0\1\5\1\0\2\113\7\5\11\0\3\5"+ + "\1\0\13\5\5\0\2\5\45\0\1\26\77\0\1\26"+ + "\21\0\1\26\7\0\6\5\2\0\1\57\3\5\1\0"+ + "\1\5\4\0\1\5\1\0\1\5\1\0\11\5\11\0"+ + "\3\5\1\0\7\5\1\114\3\5\5\0\2\5\1\0"+ + "\6\5\2\0\1\57\2\5\1\115\1\0\1\5\4\0"+ + "\1\5\1\0\1\5\1\0\11\5\11\0\3\5\1\0"+ + "\1\5\1\115\11\5\5\0\2\5\71\0\1\16\77\0"+ + "\1\16\100\0\1\26\2\0\10\36\1\0\11\36\1\0"+ + "\11\36\1\0\40\36\22\0\1\116\56\0\10\36\1\0"+ + "\11\36\1\0\4\36\2\117\3\36\1\0\16\36\1\120"+ + "\21\36\31\0\2\121\22\0\1\122\23\0\10\36\1\0"+ + "\11\36\1\0\4\36\2\123\3\36\1\0\40\36\2\0"+ + "\10\36\1\0\11\36\1\0\11\36\1\0\20\36\1\124"+ + "\17\36\1\0\1\125\27\0\2\126\123\0\1\125\20\0"+ + "\1\125\10\47\1\0\23\47\1\0\40\47\2\0\10\47"+ + "\1\0\16\47\2\127\3\47\1\0\16\47\1\130\21\47"+ + "\31\0\2\131\22\0\1\132\23\0\10\47\1\0\16\47"+ + "\2\133\3\47\1\0\40\47\2\0\10\47\1\0\23\47"+ + "\1\0\20\47\1\134\17\47\1\0\1\135\27\0\2\136"+ + "\123\0\1\135\20\0\1\135\12\0\1\137\64\0\7\60"+ + "\2\0\4\60\1\0\1\60\1\0\1\60\2\0\1\60"+ + "\1\0\1\60\1\0\11\60\2\0\1\60\6\0\3\60"+ + "\1\0\13\60\5\0\5\60\2\140\1\60\1\140\2\0"+ + "\4\60\1\0\1\140\1\0\1\60\2\0\1\60\1\0"+ + "\1\60\1\141\11\60\2\0\1\60\3\0\1\141\2\0"+ + "\3\60\1\0\13\60\5\0\5\60\4\142\2\0\3\60"+ + "\1\142\1\0\1\142\1\0\1\60\2\0\1\60\1\0"+ + "\1\142\1\0\4\60\3\142\2\60\2\0\1\60\6\0"+ + "\3\60\1\0\1\60\1\142\1\60\1\142\7\60\5\0"+ + "\2\60\7\143\1\144\1\0\66\143\7\0\1\144\67\0"+ + "\4\143\1\145\1\143\1\146\1\147\1\0\1\64\1\150"+ + "\3\64\1\145\11\143\1\64\1\143\1\64\1\143\1\64"+ + "\42\143\1\0\6\5\2\0\1\57\3\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\10\5\1\151\11\0"+ + "\3\5\1\0\13\5\5\0\2\5\11\71\1\152\3\71"+ + "\1\153\65\71\1\13\1\71\2\13\1\0\1\13\1\154"+ + "\4\13\11\71\1\13\1\71\1\13\1\71\1\13\42\71"+ + "\31\0\2\155\57\0\1\156\22\0\1\157\22\0\1\156"+ + "\1\160\77\0\1\161\40\0\1\162\1\0\2\163\103\0"+ + "\1\164\54\0\1\165\17\0\2\166\24\0\1\165\42\0"+ + "\1\167\106\0\1\170\41\0\3\60\2\106\1\60\1\106"+ + "\2\0\4\60\1\0\1\106\1\0\1\60\2\0\1\60"+ + "\1\0\1\62\1\0\11\60\2\0\1\60\6\0\3\60"+ + "\1\0\13\60\5\0\2\60\1\0\6\5\2\0\1\57"+ + "\3\5\1\0\1\5\4\0\1\5\1\0\1\5\1\0"+ + "\2\171\7\5\11\0\3\5\1\0\13\5\5\0\2\5"+ + "\1\0\6\5\2\0\1\57\1\172\2\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\11\5\11\0\3\5"+ + "\1\0\13\5\5\0\2\5\1\0\6\5\2\0\1\57"+ + "\3\5\1\0\1\5\4\0\1\5\1\0\1\5\1\0"+ + "\7\5\1\173\1\5\11\0\3\5\1\0\13\5\5\0"+ + "\2\5\1\0\6\5\2\0\1\57\2\5\1\174\1\0"+ + "\1\5\4\0\1\5\1\0\1\5\1\0\11\5\11\0"+ + "\1\5\1\175\1\5\1\0\1\5\1\174\11\5\5\0"+ + "\2\5\1\0\6\5\2\0\1\57\3\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\2\5\2\176\5\5"+ + "\11\0\3\5\1\0\13\5\5\0\2\5\1\0\6\5"+ + "\2\0\1\57\3\5\1\0\1\5\4\0\1\5\1\0"+ + "\1\5\1\0\11\5\11\0\1\5\1\177\1\5\1\0"+ + "\13\5\5\0\2\5\1\0\6\5\2\0\1\57\3\5"+ + "\1\0\1\5\4\0\1\5\1\0\1\5\1\0\11\5"+ + "\11\0\3\5\1\0\12\5\1\200\5\0\2\5\10\36"+ + "\1\0\11\36\1\0\11\36\1\0\15\36\1\201\22\36"+ + "\2\0\10\36\1\0\11\36\1\0\11\36\1\0\1\36"+ + "\1\202\36\36\54\0\1\203\62\0\1\204\40\0\10\36"+ + "\1\0\11\36\1\0\4\36\2\205\3\36\1\0\40\36"+ + "\2\0\10\36\1\0\11\36\1\0\11\36\1\0\20\36"+ + "\1\206\17\36\1\0\1\207\55\0\1\207\20\0\1\207"+ + "\27\0\2\210\46\0\10\47\1\0\23\47\1\0\15\47"+ + "\1\211\22\47\2\0\10\47\1\0\23\47\1\0\1\47"+ + "\1\212\36\47\54\0\1\213\62\0\1\214\40\0\10\47"+ + "\1\0\16\47\2\215\3\47\1\0\40\47\2\0\10\47"+ + "\1\0\23\47\1\0\20\47\1\216\17\47\1\0\1\217"+ + "\55\0\1\217\20\0\1\217\27\0\2\220\51\0\4\221"+ + "\5\0\1\221\1\0\1\221\6\0\1\221\5\0\3\221"+ + "\20\0\1\221\1\0\1\221\16\0\3\60\2\140\1\60"+ + "\1\140\2\0\4\60\1\0\1\140\1\0\1\60\2\0"+ + "\1\60\1\0\1\60\1\0\11\60\2\0\1\60\6\0"+ + "\3\60\1\0\13\60\5\0\2\60\3\0\2\140\1\0"+ + "\1\140\7\0\1\140\60\0\7\143\1\65\1\0\72\143"+ + "\1\146\1\143\1\146\1\144\1\0\5\143\1\146\64\143"+ + "\1\64\1\143\1\64\1\144\1\0\5\143\1\64\63\143"+ + "\4\222\1\65\1\0\3\143\1\222\1\143\1\222\6\143"+ + "\1\222\5\143\3\222\20\143\1\222\1\143\1\222\16\143"+ + "\1\0\6\5\2\0\1\57\3\5\1\0\1\5\4\0"+ + "\1\5\1\0\1\174\1\0\11\5\11\0\3\5\1\0"+ + "\13\5\5\0\2\5\10\71\1\0\71\71\4\223\2\71"+ + "\1\152\2\71\1\223\1\153\1\223\6\71\1\223\5\71"+ + "\3\223\20\71\1\223\1\71\1\223\16\71\25\0\1\224"+ + "\131\0\1\166\55\0\1\225\74\0\1\226\72\0\2\227"+ + "\73\0\2\166\131\0\1\230\44\0\2\231\51\0\1\232"+ + "\124\0\2\233\47\0\1\234\72\0\6\5\2\0\1\57"+ + "\3\5\1\0\1\5\4\0\1\5\1\0\1\5\1\0"+ + "\11\5\11\0\2\5\1\235\1\0\13\5\5\0\2\5"+ + "\1\0\6\5\2\0\1\57\3\5\1\0\1\5\4\0"+ + "\1\5\1\0\1\236\1\0\11\5\11\0\3\5\1\0"+ + "\13\5\5\0\2\5\1\0\6\5\2\0\1\57\3\5"+ + "\1\0\1\5\4\0\1\5\1\0\1\5\1\0\10\5"+ + "\1\172\11\0\3\5\1\0\13\5\5\0\2\5\1\0"+ + "\4\5\1\237\1\5\2\0\1\57\3\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\11\5\11\0\1\5"+ + "\1\240\1\5\1\0\13\5\5\0\2\5\1\0\6\5"+ + "\2\0\1\57\3\5\1\0\1\5\4\0\1\5\1\0"+ + "\1\241\1\0\11\5\11\0\3\5\1\0\13\5\5\0"+ + "\2\5\1\0\6\5\2\0\1\57\3\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\11\5\11\0\2\5"+ + "\1\242\1\0\13\5\5\0\2\5\1\0\6\5\2\0"+ + "\1\57\3\5\1\0\1\5\4\0\1\5\1\0\1\5"+ + "\1\0\11\5\11\0\3\5\1\0\6\5\1\243\4\5"+ + "\5\0\2\5\1\0\6\5\2\0\1\57\3\5\1\0"+ + "\1\5\4\0\1\5\1\0\1\244\1\0\11\5\11\0"+ + "\3\5\1\0\13\5\5\0\2\5\10\36\1\0\11\36"+ + "\1\0\11\36\1\0\17\36\1\245\20\36\2\0\10\36"+ + "\1\0\11\36\1\0\2\36\1\201\6\36\1\0\40\36"+ + "\56\0\1\246\47\0\1\203\51\0\10\36\1\0\11\36"+ + "\1\0\11\36\1\0\15\36\1\247\22\36\2\0\10\36"+ + "\1\0\11\36\1\0\1\36\1\250\7\36\1\0\40\36"+ + "\26\0\1\251\124\0\1\252\24\0\10\47\1\0\23\47"+ + "\1\0\17\47\1\253\20\47\2\0\10\47\1\0\14\47"+ + "\1\211\6\47\1\0\40\47\56\0\1\254\47\0\1\213"+ + "\51\0\10\47\1\0\23\47\1\0\15\47\1\255\22\47"+ + "\2\0\10\47\1\0\13\47\1\256\7\47\1\0\40\47"+ + "\26\0\1\257\124\0\1\260\27\0\4\261\5\0\1\261"+ + "\1\0\1\261\6\0\1\261\5\0\3\261\20\0\1\261"+ + "\1\0\1\261\16\0\3\143\4\262\1\65\1\0\3\143"+ + "\1\262\1\143\1\262\6\143\1\262\5\143\3\262\20\143"+ + "\1\262\1\143\1\262\16\143\3\71\4\263\2\71\1\152"+ + "\2\71\1\263\1\153\1\263\6\71\1\263\5\71\3\263"+ + "\20\71\1\263\1\71\1\263\16\71\35\0\1\264\66\0"+ + "\1\265\107\0\1\266\65\0\1\267\123\0\1\166\63\0"+ + "\1\270\75\0\1\271\113\0\1\272\54\0\2\273\45\0"+ + "\6\5\2\0\1\57\3\5\1\0\1\5\4\0\1\5"+ + "\1\0\1\5\1\0\2\274\7\5\11\0\3\5\1\0"+ + "\13\5\5\0\2\5\1\0\6\5\2\0\1\57\3\5"+ + "\1\0\1\5\4\0\1\5\1\0\1\5\1\0\7\5"+ + "\1\275\1\5\11\0\3\5\1\0\13\5\5\0\2\5"+ + "\1\0\6\5\2\0\1\57\3\5\1\0\1\5\4\0"+ + "\1\5\1\0\1\5\1\0\6\5\1\276\2\5\11\0"+ + "\3\5\1\0\13\5\5\0\2\5\1\0\6\5\2\0"+ + "\1\57\3\5\1\0\1\5\4\0\1\5\1\0\1\5"+ + "\1\0\2\5\2\174\5\5\11\0\3\5\1\0\13\5"+ + "\5\0\2\5\1\0\6\5\2\0\1\57\1\5\1\277"+ + "\1\5\1\0\1\5\4\0\1\5\1\0\1\5\1\0"+ + "\11\5\11\0\3\5\1\0\4\5\1\277\6\5\5\0"+ + "\2\5\1\0\6\5\2\0\1\57\3\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\2\5\2\300\5\5"+ + "\11\0\3\5\1\0\13\5\5\0\2\5\1\0\4\5"+ + "\1\301\1\5\2\0\1\57\3\5\1\0\1\5\4\0"+ + "\1\5\1\0\1\5\1\0\11\5\11\0\3\5\1\0"+ + "\13\5\5\0\2\5\10\36\1\0\11\36\1\0\11\36"+ + "\1\0\13\36\1\302\24\36\52\0\1\303\26\0\10\36"+ + "\1\0\11\36\1\0\11\36\1\0\2\36\1\201\14\36"+ + "\1\245\20\36\2\0\1\36\7\250\1\0\1\36\3\250"+ + "\1\36\1\250\1\36\1\250\1\36\1\304\11\250\1\251"+ + "\3\250\1\36\30\250\4\36\2\251\1\0\1\251\1\304"+ + "\4\251\1\304\2\0\3\251\1\0\1\251\1\0\1\304"+ + "\1\0\1\304\1\251\1\304\1\251\1\304\11\251\1\0"+ + "\7\304\4\251\1\304\13\251\1\304\4\0\2\251\37\0"+ + "\1\203\14\0\1\246\22\0\10\47\1\0\23\47\1\0"+ + "\13\47\1\305\24\47\52\0\1\306\26\0\10\47\1\0"+ + "\23\47\1\0\2\47\1\211\14\47\1\253\20\47\2\0"+ + "\1\47\7\256\1\0\1\47\3\256\1\47\1\256\1\47"+ + "\1\256\1\47\12\256\1\257\3\256\1\47\30\256\4\47"+ + "\2\257\1\0\1\257\1\307\4\257\1\307\2\0\3\257"+ + "\1\0\1\257\1\0\1\307\1\0\1\307\1\257\1\307"+ + "\1\257\1\307\11\257\1\0\7\307\4\257\1\307\13\257"+ + "\1\307\4\0\2\257\37\0\1\213\14\0\1\254\25\0"+ + "\4\310\5\0\1\310\1\0\1\310\6\0\1\310\5\0"+ + "\3\310\20\0\1\310\1\0\1\310\16\0\3\143\4\311"+ + "\1\65\1\0\3\143\1\311\1\143\1\311\6\143\1\311"+ + "\5\143\3\311\20\143\1\311\1\143\1\311\16\143\3\71"+ + "\4\312\2\71\1\152\2\71\1\312\1\153\1\312\6\71"+ + "\1\312\5\71\3\312\20\71\1\312\1\71\1\312\16\71"+ + "\57\0\1\166\72\0\1\313\35\0\1\314\121\0\1\315"+ + "\66\0\1\166\63\0\1\316\77\0\1\270\45\0\1\270"+ + "\100\0\1\166\14\0\6\5\2\0\1\57\3\5\1\0"+ + "\1\5\4\0\1\5\1\0\1\5\1\0\11\5\11\0"+ + "\3\5\1\0\11\5\1\317\1\5\5\0\2\5\1\0"+ + "\6\5\2\0\1\57\3\5\1\0\1\5\4\0\1\5"+ + "\1\0\1\5\1\0\6\5\1\320\2\5\11\0\3\5"+ + "\1\0\13\5\5\0\2\5\1\0\4\5\1\321\1\5"+ + "\2\0\1\57\3\5\1\0\1\5\4\0\1\5\1\0"+ + "\1\5\1\0\11\5\11\0\3\5\1\0\13\5\5\0"+ + "\2\5\1\0\6\5\2\0\1\57\3\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\11\5\11\0\3\5"+ + "\1\0\10\5\1\317\2\5\5\0\2\5\1\0\6\5"+ + "\2\0\1\57\3\5\1\0\1\5\4\0\1\5\1\0"+ + "\1\5\1\0\2\317\7\5\11\0\3\5\1\0\13\5"+ + "\5\0\2\5\1\0\6\5\2\0\1\57\3\5\1\0"+ + "\1\5\4\0\1\5\1\0\1\5\1\0\2\322\7\5"+ + "\11\0\3\5\1\0\13\5\5\0\2\5\10\36\1\0"+ + "\11\36\1\0\11\36\1\0\13\36\1\250\24\36\52\0"+ + "\1\251\26\0\10\47\1\0\23\47\1\0\13\47\1\256"+ + "\24\47\52\0\1\257\31\0\4\5\5\0\1\5\1\0"+ + "\1\5\6\0\1\5\5\0\3\5\20\0\1\5\1\0"+ + "\1\5\16\0\3\143\4\64\1\65\1\0\3\143\1\64"+ + "\1\143\1\64\6\143\1\64\5\143\3\64\20\143\1\64"+ + "\1\143\1\64\16\143\3\71\4\13\2\71\1\152\2\71"+ + "\1\13\1\153\1\13\6\71\1\13\5\71\3\13\20\71"+ + "\1\13\1\71\1\13\16\71\33\0\2\166\77\0\1\323"+ + "\46\0\1\324\151\0\1\270\17\0\6\5\2\0\1\57"+ + "\1\325\2\5\1\0\1\5\4\0\1\5\1\0\1\5"+ + "\1\0\11\5\11\0\3\5\1\0\13\5\5\0\2\5"+ + "\1\0\6\5\2\0\1\57\3\5\1\0\1\5\4\0"+ + "\1\5\1\0\1\5\1\0\10\5\1\326\11\0\3\5"+ + "\1\0\13\5\5\0\2\5\1\0\6\5\2\0\1\57"+ + "\3\5\1\0\1\5\4\0\1\5\1\0\1\5\1\0"+ + "\11\5\11\0\3\5\1\0\2\5\1\327\10\5\5\0"+ + "\2\5\27\0\2\270\117\0\1\166\23\0\1\166\2\0"+ + "\6\5\2\0\1\57\3\5\1\0\1\5\4\0\1\5"+ + "\1\0\1\5\1\0\2\330\7\5\11\0\3\5\1\0"+ + "\13\5\5\0\2\5\1\0\6\5\2\0\1\57\3\5"+ + "\1\0\1\5\4\0\1\5\1\0\1\5\1\0\10\5"+ + "\1\331\11\0\3\5\1\0\13\5\5\0\2\5\1\0"+ + "\6\5\2\0\1\57\3\5\1\0\1\5\4\0\1\5"+ + "\1\0\1\5\1\0\6\5\1\332\2\5\11\0\3\5"+ + "\1\0\13\5\5\0\2\5\1\0\6\5\2\0\1\57"+ + "\3\5\1\0\1\5\4\0\1\5\1\0\1\5\1\0"+ + "\11\5\11\0\2\5\1\333\1\0\13\5\5\0\2\5"+ + "\1\0\6\5\2\0\1\57\1\5\1\334\1\5\1\0"+ + "\1\5\4\0\1\5\1\0\1\5\1\0\11\5\11\0"+ + "\3\5\1\0\4\5\1\334\6\5\5\0\2\5\1\0"+ + "\6\5\2\0\1\57\3\5\1\0\1\5\4\0\1\5"+ + "\1\0\1\5\1\0\11\5\11\0\3\5\1\0\10\5"+ + "\1\335\2\5\5\0\2\5\1\0\6\5\2\0\1\57"+ + "\3\5\1\0\1\5\4\0\1\5\1\0\1\5\1\0"+ + "\7\5\1\336\1\5\11\0\3\5\1\0\13\5\5\0"+ + "\2\5\1\0\6\5\2\0\1\57\3\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\6\5\1\337\2\5"+ + "\11\0\3\5\1\0\13\5\5\0\2\5\1\0\6\5"+ + "\2\0\1\57\3\5\1\0\1\5\4\0\1\5\1\0"+ + "\1\331\1\0\11\5\11\0\3\5\1\0\13\5\5\0"+ + "\2\5\1\0\6\5\2\0\1\57\3\5\1\0\1\5"+ + "\4\0\1\5\1\0\1\5\1\0\10\5\1\322\11\0"+ + "\3\5\1\0\13\5\5\0\2\5\1\0\6\5\2\0"+ + "\1\57\3\5\1\0\1\5\4\0\1\5\1\0\1\5"+ + "\1\0\11\5\11\0\3\5\1\0\7\5\1\340\3\5"+ + "\5\0\2\5\1\0\6\5\2\0\1\57\3\5\1\0"+ + "\1\5\4\0\1\5\1\0\1\322\1\0\11\5\11\0"+ + "\3\5\1\0\13\5\5\0\2\5"; + + private static int [] zzUnpackTrans() { + int [] result = new int[12852]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code> + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\3\0\1\11\4\1\1\11\13\1\2\11\10\1\1\11"+ + "\10\1\1\11\6\1\1\0\1\1\1\0\3\1\1\11"+ + "\1\0\4\1\1\11\1\0\2\11\7\0\10\1\1\11"+ + "\2\1\2\0\2\1\2\0\2\1\2\0\2\1\3\0"+ + "\1\1\1\0\2\1\1\11\6\1\1\11\1\1\11\0"+ + "\1\11\2\0\12\1\2\0\2\1\2\0\2\1\2\0"+ + "\2\1\3\0\2\1\11\0\11\1\1\0\3\1\1\0"+ + "\1\1\1\0\3\1\2\0\2\1\1\0\1\1\6\0"+ + "\7\1\2\0\1\1\3\0\2\1\4\0\4\1\2\0"+ + "\14\1"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[224]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** the input device */ + private Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the textposition at the last state to be included in yytext */ + private int zzPushbackPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /* user code: */ + + + /** + * Constructor. This must be here because JFlex does not generate a + * no-parameter constructor. + */ + public VelocityTokenMaker() { + } + + + /** + * Adds the token specified to the current linked list of tokens. + * + * @param tokenType The token's type. + * @see #addToken(int, int, int) + */ + private void addHyperlinkToken(int start, int end, int tokenType) { + int so = start + offsetShift; + addToken(zzBuffer, start,end, tokenType, so, true); + } + + + /** + * Adds the token specified to the current linked list of tokens. + * + * @param tokenType The token's type. + */ + private void addToken(int tokenType) { + addToken(zzStartRead, zzMarkedPos-1, tokenType); + } + + + /** + * Adds the token specified to the current linked list of tokens. + * + * @param tokenType The token's type. + * @see #addHyperlinkToken(int, int, int) + */ + private void addToken(int start, int end, int tokenType) { + int so = start + offsetShift; + addToken(zzBuffer, start,end, tokenType, so, false); + } + + + /** + * Adds the token specified to the current linked list of tokens. + * + * @param array The character array. + * @param start The starting offset in the array. + * @param end The ending offset in the array. + * @param tokenType The token's type. + * @param startOffset The offset in the document at which this token + * occurs. + * @param hyperlink Whether this token is a hyperlink. + */ + public void addToken(char[] array, int start, int end, int tokenType, + int startOffset, boolean hyperlink) { + super.addToken(array, start,end, tokenType, startOffset, hyperlink); + zzStartRead = zzMarkedPos; + } + + + /** + * {@inheritDoc} + */ + public String[] getLineCommentStartAndEnd(int languageIndex) { + return new String[] { "##", null }; + } + + + /** + * Returns the first token in the linked list of tokens generated + * from <code>text</code>. This method must be implemented by + * subclasses so they can correctly implement syntax highlighting. + * + * @param text The text from which to get tokens. + * @param initialTokenType The token type we should start with. + * @param startOffset The offset into the document at which + * <code>text</code> starts. + * @return The first <code>Token</code> in a linked list representing + * the syntax highlighted text. + */ + public Token getTokenList(Segment text, int initialTokenType, int startOffset) { + + resetTokenList(); + this.offsetShift = -text.offset + startOffset; + + // Start off in the proper state. + int state = Token.NULL; + switch (initialTokenType) { + case Token.COMMENT_MULTILINE: + state = MLC; + start = text.offset; + break; + + /* No documentation comments */ + default: + state = Token.NULL; + } + + s = text; + try { + yyreset(zzReader); + yybegin(state); + return yylex(); + } catch (IOException ioe) { + ioe.printStackTrace(); + return new TokenImpl(); + } + + } + + + /** + * Refills the input buffer. + * + * @return <code>true</code> if EOF was reached, otherwise + * <code>false</code>. + */ + private boolean zzRefill() { + return zzCurrentPos>=s.offset+s.count; + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * <b>cannot</b> be reused (internal buffer is discarded and lost). + * Lexical state is set to <tt>YY_INITIAL</tt>. + * + * @param reader the new input stream + */ + public final void yyreset(Reader reader) { + // 's' has been updated. + zzBuffer = s.array; + /* + * We replaced the line below with the two below it because zzRefill + * no longer "refills" the buffer (since the way we do it, it's always + * "full" the first time through, since it points to the segment's + * array). So, we assign zzEndRead here. + */ + //zzStartRead = zzEndRead = s.offset; + zzStartRead = s.offset; + zzEndRead = zzStartRead + s.count - 1; + zzCurrentPos = zzMarkedPos = zzPushbackPos = s.offset; + zzLexicalState = YYINITIAL; + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + } + + + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + public VelocityTokenMaker(Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + public VelocityTokenMaker(InputStream in) { + this(new InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 192) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) + zzReader.close(); + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position <tt>pos</tt> from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception IOException if any I/O-Error occurs + */ + public Token yylex() throws IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = zzLexicalState; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = zzBufferL[zzCurrentPosL++]; + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 4: + { addNullToken(); return firstToken; + } + case 27: break; + case 20: + { addToken(Token.LITERAL_CHAR); + } + case 28: break; + case 16: + { start = zzMarkedPos-2; yybegin(MLC); + } + case 29: break; + case 6: + { addToken(Token.WHITESPACE); + } + case 30: break; + case 19: + { addToken(Token.LITERAL_NUMBER_HEXADECIMAL); + } + case 31: break; + case 21: + { addToken(Token.ERROR_STRING_DOUBLE); + } + case 32: break; + case 17: + { addToken(Token.LITERAL_NUMBER_FLOAT); + } + case 33: break; + case 22: + { addToken(Token.RESERVED_WORD); + } + case 34: break; + case 8: + { addToken(Token.SEPARATOR); + } + case 35: break; + case 1: + { addToken(Token.IDENTIFIER); + } + case 36: break; + case 11: + { addToken(start,zzStartRead-1, Token.COMMENT_EOL); addNullToken(); return firstToken; + } + case 37: break; + case 15: + { start = zzMarkedPos-2; yybegin(EOL_COMMENT); + } + case 38: break; + case 26: + { addToken(Token.FUNCTION); + } + case 39: break; + case 3: + { addToken(Token.ERROR_CHAR); addNullToken(); return firstToken; + } + case 40: break; + case 5: + { addToken(Token.ERROR_STRING_DOUBLE); addNullToken(); return firstToken; + } + case 41: break; + case 18: + { yybegin(YYINITIAL); addToken(start,zzStartRead+2-1, Token.COMMENT_MULTILINE); + } + case 42: break; + case 13: + { addToken(Token.ERROR_CHAR); + } + case 43: break; + case 23: + { addToken(Token.LITERAL_BOOLEAN); + } + case 44: break; + case 14: + { addToken(Token.LITERAL_STRING_DOUBLE_QUOTE); + } + case 45: break; + case 25: + { int temp=zzStartRead; addToken(start,zzStartRead-1, Token.COMMENT_EOL); addHyperlinkToken(temp,zzMarkedPos-1, Token.COMMENT_EOL); start = zzMarkedPos; + } + case 46: break; + case 24: + { int temp=zzStartRead; addToken(start,zzStartRead-1, Token.COMMENT_MULTILINE); addHyperlinkToken(temp,zzMarkedPos-1, Token.COMMENT_MULTILINE); start = zzMarkedPos; + } + case 47: break; + case 12: + { addToken(Token.ERROR_NUMBER_FORMAT); + } + case 48: break; + case 2: + { addToken(Token.LITERAL_NUMBER_DECIMAL_INT); + } + case 49: break; + case 7: + { addToken(Token.OPERATOR); + } + case 50: break; + case 9: + { + } + case 51: break; + case 10: + { addToken(start,zzStartRead-1, Token.COMMENT_MULTILINE); return firstToken; + } + case 52: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + switch (zzLexicalState) { + case EOL_COMMENT: { + addToken(start,zzStartRead-1, Token.COMMENT_EOL); addNullToken(); return firstToken; + } + case 225: break; + case YYINITIAL: { + addNullToken(); return firstToken; + } + case 226: break; + case MLC: { + addToken(start,zzStartRead-1, Token.COMMENT_MULTILINE); return firstToken; + } + case 227: break; + default: + return null; + } + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-find_and_replace.png b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-find_and_replace.png new file mode 100644 index 000000000..363b512aa Binary files /dev/null and b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-find_and_replace.png differ diff --git a/pom.xml b/pom.xml index 4de1f92cf..9d37e65fa 100644 --- a/pom.xml +++ b/pom.xml @@ -464,6 +464,11 @@ <version>${testcontainers.version}</version> <scope>test</scope> </dependency> + <dependency> + <groupId>com.fifesoft</groupId> + <artifactId>rsyntaxtextarea</artifactId> + <version>3.2.0</version> + </dependency> </dependencies> </dependencyManagement>
