You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2022/09/29 14:35:53 UTC
[cayenne] 01/03: template editor feature
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 <70...@users.noreply.github.com>
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>