Skip to content

Commit 031f08c

Browse files
Merge pull request #69 from PhilippSalvisberg/feature/issue_60_snippets
#60 - add snippets for annotations and expectations
2 parents e8130c6 + 1f124cc commit 031f08c

File tree

7 files changed

+498
-1
lines changed

7 files changed

+498
-1
lines changed

sqldev/src/main/java/org/utplsql/sqldev/model/XMLTools.xtend

+31-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
*/
1515
package org.utplsql.sqldev.model
1616

17+
import java.io.StringWriter
18+
import javax.xml.transform.OutputKeys
19+
import javax.xml.transform.TransformerFactory
20+
import javax.xml.transform.dom.DOMSource
21+
import javax.xml.transform.stream.StreamResult
1722
import javax.xml.xpath.XPathConstants
1823
import javax.xml.xpath.XPathFactory
1924
import org.w3c.dom.Node
@@ -34,4 +39,29 @@ class XMLTools {
3439
val Node node = expr.evaluate(doc, XPathConstants.NODE) as Node
3540
return node
3641
}
37-
}
42+
43+
def void trimWhitespace(Node node) {
44+
val children = node.childNodes
45+
for (i : 0 ..< children.length) {
46+
val child = children.item(i)
47+
if (child.nodeType == Node.TEXT_NODE) {
48+
child.textContent = child.textContent.trim
49+
}
50+
trimWhitespace(child);
51+
}
52+
}
53+
54+
def nodeToString(Node node, String cdataSectionElements) {
55+
node.trimWhitespace
56+
val writer = new StringWriter()
57+
val factory = TransformerFactory.newInstance().newTransformer()
58+
factory.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
59+
factory.setOutputProperty(OutputKeys.INDENT, "yes")
60+
factory.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
61+
factory.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, cdataSectionElements)
62+
factory.transform(new DOMSource(node), new StreamResult(writer))
63+
val result = writer.toString()
64+
val fixedResult = result.replaceAll('''<!\[CDATA\[\s*\]\]>''',"")
65+
return fixedResult
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2019 Philipp Salvisberg <[email protected]>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.utplsql.sqldev.snippet
17+
18+
import java.io.BufferedReader
19+
import java.io.File
20+
import java.io.IOException
21+
import java.io.InputStreamReader
22+
import java.io.StringReader
23+
import java.nio.charset.Charset
24+
import java.nio.file.Files
25+
import java.nio.file.Paths
26+
import java.util.stream.Collectors
27+
import javax.xml.parsers.DocumentBuilderFactory
28+
import oracle.dbtools.util.Resource
29+
import org.utplsql.sqldev.model.XMLTools
30+
import org.xml.sax.InputSource
31+
32+
class SnippetMerger {
33+
val extension XMLTools xmlTools = new XMLTools
34+
File userSnippetsFile
35+
String utplsqlSnippets
36+
37+
def getUtplsqlSnippetsAsString() throws IOException {
38+
val stream = class.getResourceAsStream("/org/utplsql/sqldev/resources/UtplsqlSnippets.xml")
39+
val reader = new BufferedReader(new InputStreamReader(stream, Charset.defaultCharset))
40+
return reader.lines.collect(Collectors.joining(System.lineSeparator))
41+
}
42+
43+
new() {
44+
// works in SQL Developer only, otherwise a ExceptionInInitializerError is thrown
45+
this (new File(Resource.RAPTOR_USER.absolutePath + File.separator + "UserSnippets.xml"))
46+
}
47+
48+
new(File file) {
49+
utplsqlSnippets = utplsqlSnippetsAsString
50+
userSnippetsFile = file
51+
}
52+
53+
def merge() {
54+
var String result
55+
if (userSnippetsFile.exists) {
56+
// file exists, proper merge required
57+
val userSnippets = new String(Files.readAllBytes(Paths.get(userSnippetsFile.absolutePath)))
58+
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
59+
val userSnippetsDoc = docBuilder.parse(new InputSource(new StringReader(userSnippets)))
60+
val userSnippetsGroups = userSnippetsDoc.getNodeList('''/snippets/group[not(@category="utPLSQL Annotations" or @category="utPLSQL Expectations")]''')
61+
val utplsqlSnippetsDoc = docBuilder.parse(new InputSource(new StringReader(utplsqlSnippets)))
62+
val utplsqlSnippetsGroups = utplsqlSnippetsDoc.getNodeList('''/snippets/group''')
63+
result = '''
64+
<?xml version = '1.0' encoding = 'UTF-8'?>
65+
<snippets>
66+
«FOR i : 0 ..< userSnippetsGroups.length»
67+
«userSnippetsGroups.item(i).nodeToString("code")»
68+
«ENDFOR»
69+
«FOR i : 0 ..< utplsqlSnippetsGroups.length»
70+
«utplsqlSnippetsGroups.item(i).nodeToString("code")»
71+
«ENDFOR»
72+
</snippets>
73+
'''
74+
} else {
75+
// just copy
76+
result = utplsqlSnippets
77+
78+
}
79+
Files.write(Paths.get(userSnippetsFile.absolutePath), result.bytes)
80+
}
81+
82+
def getTemplate() {
83+
return utplsqlSnippets
84+
}
85+
86+
def getFile() {
87+
return userSnippetsFile
88+
}
89+
90+
}

sqldev/src/main/java/org/utplsql/sqldev/ui/preference/PreferencePanel.xtend

+20
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import java.awt.event.ActionListener
2020
import java.util.Map
2121
import javax.swing.JButton
2222
import javax.swing.JCheckBox
23+
import javax.swing.JOptionPane
2324
import javax.swing.JPanel
2425
import javax.swing.JSpinner
2526
import javax.swing.JTabbedPane
@@ -33,6 +34,7 @@ import oracle.ide.panels.TraversalException
3334
import oracle.javatools.ui.layout.FieldLayoutBuilder
3435
import org.utplsql.sqldev.model.preference.PreferenceModel
3536
import org.utplsql.sqldev.resources.UtplsqlResources
37+
import org.utplsql.sqldev.snippet.SnippetMerger
3638
import org.utplsql.sqldev.ui.common.DirectoryChooser
3739

3840
class PreferencePanel extends DefaultTraversablePanel {
@@ -43,6 +45,7 @@ class PreferencePanel extends DefaultTraversablePanel {
4345
val JCheckBox clearScreenCheckBox = new JCheckBox
4446
val JCheckBox autoExecuteCheckBox = new JCheckBox
4547
val JCheckBox checkRunUtplsqlTestCheckBox = new JCheckBox
48+
val JButton importSnippetsButton = new JButton(UtplsqlResources.getString("PREF_IMPORT_SNIPPETS_BUTTON_LABEL"))
4649
val JPanel realtimeReporterPanel = new JPanel
4750
val SpinnerNumberModel numberOfRunsInHistoryModel = new SpinnerNumberModel(1, 1, 100, 1);
4851
val JSpinner numberOfRunsInHistorySpinner = new JSpinner(numberOfRunsInHistoryModel);
@@ -101,6 +104,7 @@ class PreferencePanel extends DefaultTraversablePanel {
101104
runTab.add(
102105
runTab.field.label.withText(UtplsqlResources.getString("PREF_CHECK_RUN_UTPLSQL_TEST_LABEL")).component(
103106
checkRunUtplsqlTestCheckBox))
107+
runTab.addRow(importSnippetsButton)
104108
runTab.addVerticalSpring
105109

106110
// realtime reporter group
@@ -200,6 +204,13 @@ class PreferencePanel extends DefaultTraversablePanel {
200204
builder.addVerticalField("", tabbedPane)
201205
builder.addVerticalSpring
202206

207+
// register action listener for import snippets button
208+
importSnippetsButton.addActionListener(new ActionListener() {
209+
override actionPerformed(ActionEvent event) {
210+
importSnippets
211+
}
212+
})
213+
203214
// register action listener for create code template button
204215
createCodeTemplatesButton.addActionListener(new ActionListener() {
205216
override actionPerformed(ActionEvent event) {
@@ -216,6 +227,15 @@ class PreferencePanel extends DefaultTraversablePanel {
216227
})
217228
}
218229

230+
private def importSnippets() {
231+
val snippetMerger = new SnippetMerger
232+
snippetMerger.merge
233+
val file = snippetMerger.file.absolutePath
234+
val message = String.format(UtplsqlResources.getString("PREF_CONFIRM_IMPORT_MESSAGE"), file)
235+
JOptionPane.showMessageDialog(null, message, UtplsqlResources.getString("PREF_CONFIRM_IMPORT_TITLE"),
236+
JOptionPane.INFORMATION_MESSAGE);
237+
}
238+
219239
private def loadCodeTemplates() {
220240
val Map<String, String> map = CodeTemplateUtil.loadFiles()
221241
for (key : map.keySet) {

sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ PREF_RESET_PACKAGE_LABEL=Reset package before running utPLSQL?
3131
PREF_CLEAR_SCREEN_LABEL=Clear script output panel before running utPLSQL?
3232
PREF_AUTO_EXECUTE_LABEL=Execute unit test automatically?
3333
PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Check availability of menu option?
34+
PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Import Snippets
3435
MENU_REALTIME_REPORTER_LABEL=Realtime Reporter
3536
PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Number of runs in history
3637
PREF_SHOW_DISABLED_COUNTER_LABEL=Show disabled counter?
@@ -56,6 +57,8 @@ PREF_GENERATE_FILES_LABEL=Generate files?
5657
PREF_OUTPUT_DIRECTORY_LABEL=Output directory
5758
PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Browse
5859
PREF_DELETE_EXISTING_FILES_LABEL=Delete existing files in output directory?
60+
PREF_CONFIRM_IMPORT_TITLE=Snippets imported
61+
PREF_CONFIRM_IMPORT_MESSAGE=Snippets imported into %s. Please restart SQL Developer for this change to take effect.
5962
MENU_RUN_TEST_LABEL=Run utPLSQL test
6063
MENU_CODE_COVERAGE_LABEL=Code coverage...
6164
MENU_GENERATE_TEST_LABEL=Generate utPLSQL test

sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ PREF_RESET_PACKAGE_LABEL=Package vor der Ausf
88
PREF_CLEAR_SCREEN_LABEL=Skriptausgabe-Fenster vor der Ausführung von utPLSQL leeren?
99
PREF_AUTO_EXECUTE_LABEL=Unit Test automatisch ausführen?
1010
PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Verfügbarkeit der Menüoption prüfen?
11+
PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Code-Schnipsel importieren
1112
MENU_REALTIME_REPORTER_LABEL=Realtime Reporter
1213
PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Anzahl Ausführungen in der Historie
1314
PREF_SHOW_DISABLED_COUNTER_LABEL=Deaktiviert-Zähler anzeigen?
@@ -33,6 +34,8 @@ PREF_GENERATE_FILES_LABEL=Dateien generieren?
3334
PREF_OUTPUT_DIRECTORY_LABEL=Ausgabeverzeichnis
3435
PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Auswählen
3536
PREF_DELETE_EXISTING_FILES_LABEL=Bestehende Dateien im Ausgabeverzeichnis löschen?
37+
PREF_CONFIRM_IMPORT_TITLE=Code-Schnipsel importiert
38+
PREF_CONFIRM_IMPORT_MESSAGE=Code-Schnipsel in %s importiert. Bitte starten Sie den SQL Developer neu, um diese Änderung zu aktivieren.
3639
MENU_RUN_TEST_LABEL=utPLSQL Test ausführen
3740
MENU_CODE_COVERAGE_LABEL=Codeabdeckung...
3841
MENU_GENERATE_TEST_LABEL=utPLSQL Test generieren

0 commit comments

Comments
 (0)