This is an automated email from the ASF dual-hosted git repository.
doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git
The following commit(s) were added to refs/heads/master by this push:
new eb97e01 EMPIREDB-362 SampleAdvApp improvement
eb97e01 is described below
commit eb97e01a09557835ee6bba69b95158337aabe6c5
Author: Rainer Döbele <[email protected]>
AuthorDate: Sat Feb 19 18:25:15 2022 +0100
EMPIREDB-362 SampleAdvApp improvement
---
.../empire/samples/db/advanced/HtmlGenUtil.java | 263 +++++++++++++++++++++
.../empire/samples/db/advanced/SampleAdvApp.java | 96 +++++++-
.../main/java/org/apache/empire/db/DBCommand.java | 29 ++-
pom.xml | 22 +-
4 files changed, 384 insertions(+), 26 deletions(-)
diff --git
a/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/HtmlGenUtil.java
b/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/HtmlGenUtil.java
new file mode 100644
index 0000000..df2f028
--- /dev/null
+++
b/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/HtmlGenUtil.java
@@ -0,0 +1,263 @@
+/*
+ * 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
+ *
+ * http://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.empire.samples.db.advanced;
+
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.db.DBColumn;
+import org.apache.empire.db.DBDatabase;
+import org.apache.empire.db.DBTable;
+
+/**
+ * Temporary class for HTML-generation of code and SQL
+ * Will be removed again later
+ * @author rainer
+ */
+public class HtmlGenUtil
+{
+ public static final String codeModelQuery = "// create command\r\n" +
+ "DBCommand cmd = context.createCommand()\r\n" +
+ " .select (BRAND.NAME, MODEL.CONFIG_NAME,
MODEL.BASE_PRICE)\r\n" +
+ " .select (SALES.MODEL_ID.count(), SALES.PRICE.avg())\r\n" +
+ " .select
(SALES.PRICE.avg().minus(MODEL.BASE_PRICE.avg()).round(2).as(\"DIFFERENCE\"))\r\n"
+
+ " .join (MODEL.WMI, BRAND.WMI)\r\n" +
+ " .joinLeft(MODEL.ID, SALES.MODEL_ID, SALES.YEAR.is(2021)) //
only year 2021\r\n" +
+ " .where (MODEL.ENGINE_TYPE.in(EngineType.P, EngineType.H,
EngineType.E)) // Petrol, Hybrid, Electric\r\n" +
+ " .where (MODEL.BASE_PRICE.isGreaterThan(30000))\r\n" +
+ " .groupBy (BRAND.NAME, MODEL.CONFIG_NAME,
MODEL.BASE_PRICE)\r\n" +
+ " .having (SALES.MODEL_ID.count().isGreaterThan(5)) // more
than 5 sales\r\n" +
+ " .orderBy (BRAND.NAME.desc(), MODEL.CONFIG_NAME.asc());\r\n" +
+ " \r\n" +
+ "// Returns a list of Java beans (needs matching fields
constructor or setter methods) \r\n" +
+ "// This is just one of several options to obtain an process query
results \r\n" +
+ "List<QueryResult> list = context.getUtils().queryBeanList(cmd,
QueryResult.class, null);\r\n" +
+ "log.info(\"queryBeanList returnes {} items\", list.size());";
+
+ public static final String codePriceUpdate = "// create command\r\n" +
+ "DBCommand cmd = context.createCommand()\r\n" +
+ " // increase model base prices by 5%\r\n" +
+ " .set
(MODEL.BASE_PRICE.to(MODEL.BASE_PRICE.multiplyWith(105).divideBy(100).round(0)))\r\n"
+
+ " .join (MODEL.WMI, BRAND.WMI)\r\n" +
+ " // on all Volkswagen Tiguan with Diesel engine\r\n" +
+ " .where(BRAND.NAME.is(\"Volkswagen\"))\r\n" +
+ "
.where(MODEL.NAME.is(\"Tiguan\").and(MODEL.ENGINE_TYPE.is(EngineType.D)));\r\n"
+
+ "\r\n" +
+ "// execute Update statement\r\n" +
+ "int count = context.executeUpdate(cmd);\r\n" +
+ "log.info(\"{} models affected\", count);";
+
+
+ public static String codeToHtml(DBDatabase db, String code, Number...
literals)
+ {
+ code = prepareHtml(code);
+ // String Literals must go first
+ code = replaceFragment(code, '"', '"', true, "<span
class=\"literal\">", "</span>", null);
+ // other literals
+ for (int i=0; i<literals.length; i++)
+ code = replaceWord(code, literals[i].toString(), ' ', "<span
class=\"literal\">", "</span>");
+ // null
+ code = replaceWord(code, "null", ' ', "<span class=\"literal\">",
"</span>");
+ // types
+ String[] types = new String[] { "CarSalesDB", "DBCommand",
"QueryResult", "EngineType", "int ", "long ", "String " };
+ for (int i=0; i<types.length; i++)
+ code = replaceWord(code, types[i], ' ', "<span class=\"type\">",
"</span>");
+ // Tables and columns
+ for (DBTable t : db.getTables())
+ {
+ code = replaceWord(code, t.getName(), ' ', "<span class=\"obj\">",
"</span>");
+ for (DBColumn c : t.getColumns())
+ {
+ code = replaceWord(code, "."+c.getName(), '.', "<span
class=\"var\">", "</span>");
+ }
+ }
+ // functions
+ code = replaceFragment(code, '.', '(', false, "<span class=\"func\">",
"</span>", new char[] { 'a', 'z' });
+ // literals
+ return replaceComment(code, "<span class=\"comment\">", "</span>");
+ }
+
+ public static String sqlToHtml(DBDatabase db, String sql, Number...
literals)
+ {
+ sql = prepareHtml(sql);
+ /*
+ UPDATE t2
+ SET BASE_PRICE=round(t2.BASE_PRICE*105/100,0)
+ FROM MODEL t2 INNER JOIN BRAND t1 ON t1.WMI = t2.WMI
+ WHERE t1.NAME='Volkswagen' AND t2.NAME='Tiguan' AND t2.ENGINE_TYPE='D'
+ */
+ String[] words = new String[] { "SELECT ", "UPDATE ", "INSERT ", "SET"
, "FROM ", "WHERE ", "GROUP BY ", "HAVING ", "ORDER BY", " IN ", " ON ", " AND
", " INNER JOIN ", " LEFT JOIN ", " RIGHT_JOIN " };
+ for (int i=0; i<words.length; i++)
+ sql = replaceWord(sql, words[i], ' ', "<span class=\"word\">",
"</span>");
+ for (DBTable t : db.getTables())
+ sql = replaceWord(sql, t.getAlias(), ' ', "<span
class=\"alias\">", "</span>");
+ // functions
+ String[] func = new String[] { "count", "round", "avg" };
+ for (int i=0; i<func.length; i++)
+ sql = replaceWord(sql, func[i], ' ', "<span class=\"func\">",
"</span>");
+ // finally literals
+ for (int i=0; i<literals.length; i++)
+ sql = replaceWord(sql, literals[i].toString(), ' ', "<span
class=\"literal\">", "</span>");
+ // String literals
+ sql = sql.replace("N'", "'");
+ return replaceFragment(sql, '\'', '\'', true, "<span
class=\"param\"><span class=\"literal\">", "</span></span>", null);
+ }
+
+ /*
+ * helpers
+ */
+
+ public static String prepareHtml(String str)
+ {
+ str = StringUtils.replace(str, "\t", " ");
+ str = StringUtils.replace(str, "&", "&");
+ str = StringUtils.replace(str, "<", "<");
+ return StringUtils.replace(str, ">", ">");
+ }
+
+ public static String replaceWord(String str, String word, char intro,
String htmlBeg, String htmlEnd)
+ {
+ // not present
+ if (str.indexOf(word)<0)
+ return str;
+ // replace
+ String wtrim = word.trim();
+ if (wtrim.charAt(0)==intro)
+ wtrim = wtrim.substring(1);
+ StringBuilder s = new StringBuilder();
+ int i = 0;
+ int p = 0;
+ while ((i=str.indexOf(word, p))>=0)
+ {
+ if (word.charAt(0)==intro)
+ i++;
+ s.append(str.substring(p, i));
+ s.append(htmlBeg);
+ s.append(wtrim);
+ s.append(htmlEnd);
+ // next
+ p = i + wtrim.length();
+ }
+ s.append(str.substring(p));
+ return s.toString();
+ }
+
+ public static String replaceFragment(String str, char beg, char end,
boolean include, String htmlBeg, String htmlEnd, char[] nextRange)
+ {
+ StringBuilder s = new StringBuilder();
+ int i = 0;
+ int p = 0;
+ while ((i=str.indexOf(beg, p))>=0)
+ {
+ // function special
+ if (nextRange!=null)
+ { // check range of next char
+ char next = str.charAt(i+1);
+ if (next<nextRange[0] || next>nextRange[1])
+ { // ignore
+ s.append(str.substring(p, ++i));
+ p = i;
+ continue;
+ }
+ }
+ int j = str.indexOf(end, ++i);
+ if (!include)
+ { // remove whitespace
+ while(str.charAt(j-1)==' ') j--;
+ }
+ int o = (include) ? 1 : 0;
+ s.append(str.substring(p, i-o));
+ s.append(htmlBeg);
+ s.append(str.substring(i-o, j+o));
+ s.append(htmlEnd);
+ // next
+ p = j + o;
+ }
+ s.append(str.substring(p));
+ return s.toString();
+ }
+
+ public static String replaceComment(String str, String htmlBeg, String
htmlEnd)
+ {
+ StringBuilder s = new StringBuilder();
+ String beg = "//";
+ String end ="\r\n";
+ int i = 0;
+ int p = 0;
+ while ((i=str.indexOf(beg, p))>=0)
+ {
+ int j = str.indexOf(end, i+1);
+ s.append(str.substring(p, i));
+ s.append(htmlBeg);
+ s.append(str.substring(i, j));
+ s.append(htmlEnd);
+ // next
+ p = j;
+ }
+ s.append(str.substring(p));
+ return s.toString();
+ }
+
+ /*
+ public static String replaceSqlWord(String sql, String word, String
htmlBeg, String htmlEnd)
+ {
+ // not present
+ if (sql.indexOf(word)<0)
+ return sql;
+ // replace
+ String wtrim = word.trim();
+ StringBuilder s = new StringBuilder();
+ int i = 0;
+ int p = 0;
+ while ((i=sql.indexOf(word, p))>=0)
+ {
+ if (word.charAt(0)==' ')
+ i++;
+ s.append(sql.substring(p, i));
+ s.append(htmlBeg);
+ s.append(wtrim);
+ s.append(htmlEnd);
+ // next
+ p = i + wtrim.length();
+ }
+ s.append(sql.substring(p));
+ return s.toString();
+ }
+ */
+
+ /*
+ public static String replaceSqlStringLiteral(String sql, String htmlBeg,
String htmlEnd)
+ {
+ StringBuilder s = new StringBuilder();
+ int i = 0;
+ int p = 0;
+ while ((i=sql.indexOf('\'', p))>=0)
+ {
+ int j = sql.indexOf('\'', ++i);
+ s.append(sql.substring(p, i-1));
+ s.append(htmlBeg);
+ s.append(sql.substring(i-1, j+1));
+ s.append(htmlEnd);
+ // next
+ p = j + 1;
+ }
+ s.append(sql.substring(p));
+ return s.toString();
+ }
+ */
+
+}
diff --git
a/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/SampleAdvApp.java
b/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/SampleAdvApp.java
index 74d4279..c6413ac 100644
---
a/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/SampleAdvApp.java
+++
b/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/SampleAdvApp.java
@@ -135,9 +135,10 @@ public class SampleAdvApp
context.commit();
}
// do simple stuff
- queryViewDemo();
- simpleQueryDemo();
- simpleUpdateDemo();
+ // simpleQueryDemo();
+ // simpleUpdateDemo();
+ // queryViewDemo();
+ paramQueryDemo();
/*
// STEP 5: Clear Database (Delete all records)
@@ -398,19 +399,33 @@ public class SampleAdvApp
CarSalesDB.Brand BRAND = carSales.BRAND;
CarSalesDB.Model MODEL = carSales.MODEL;
CarSalesDB.Sales SALES = carSales.SALES;
+
+ // .selectQualified(BRAND.NAME, MODEL.CONFIG_NAME)
+
// create command
DBCommand cmd = context.createCommand()
- .selectQualified(BRAND.NAME, MODEL.CONFIG_NAME)
- .select (MODEL.BASE_PRICE)
+ .select (BRAND.NAME, MODEL.CONFIG_NAME, MODEL.BASE_PRICE)
.select (SALES.MODEL_ID.count(), SALES.PRICE.avg())
- .select (SALES.PRICE.avg().minus(MODEL.BASE_PRICE.avg()).round(2))
+ .select
(SALES.PRICE.avg().minus(MODEL.BASE_PRICE.avg()).round(2).as("DIFFERENCE"))
.join (MODEL.WMI, BRAND.WMI)
.joinLeft(MODEL.ID, SALES.MODEL_ID, SALES.YEAR.is(2021)) // only
year 2021
.where (MODEL.ENGINE_TYPE.in(EngineType.P, EngineType.H,
EngineType.E)) // Petrol, Hybrid, Electric
.where (MODEL.BASE_PRICE.isGreaterThan(30000))
.groupBy (BRAND.NAME, MODEL.CONFIG_NAME, MODEL.BASE_PRICE)
- .having (SALES.MODEL_ID.count().isGreaterThan(5))
+ .having (SALES.MODEL_ID.count().isGreaterThan(5)) // more than 5
sales
.orderBy (BRAND.NAME.desc(), MODEL.CONFIG_NAME.asc());
+
+ // Returns a list of Java beans (needs matching fields constructor or
setter methods)
+ // This is just one of several options to obtain an process query
results
+ List<QueryResult> list = context.getUtils().queryBeanList(cmd,
QueryResult.class, null);
+ log.info("queryBeanList returnes {} items", list.size());
+
+ Number[] literals = new Number[] { 2021, 30000 };
+ System.out.println("---------------------------------");
+ System.out.println(HtmlGenUtil.codeToHtml(carSales,
HtmlGenUtil.codeModelQuery, literals));
+ System.out.println("---------------------------------");
+ System.out.println(HtmlGenUtil.sqlToHtml(carSales, cmd.getSelect(),
literals));
+ System.out.println("---------------------------------");
/*
List<DataListEntry> list = context.getUtils().queryDataList(cmd);
@@ -419,12 +434,47 @@ public class SampleAdvApp
System.out.println(dle.toString());
}
*/
+ /*
DataListEntry entry = context.getUtils().queryDataEntry(cmd);
for (int i=0; i<entry.getFieldCount(); i++)
log.info("col {} -> {}", entry.getColumn(i).getName(),
entry.getColumn(i).getBeanPropertyName());
-
- List<QueryResult> list = context.getUtils().queryBeanList(cmd,
QueryResult.class, null);
- log.info("queryBeanList returnes {} items", list.size());
+ */
+ }
+
+ public void paramQueryDemo()
+ {
+ // shortcuts (for convenience)
+ CarSalesDB.Brand BRAND = carSales.BRAND;
+ CarSalesDB.Model MODEL = carSales.MODEL;
+
+ // create command
+ DBCommand cmd = context.createCommand();
+ // create params
+ DBCmdParam brandParam = cmd.addParam();
+ DBCmdParam engineTypeParam = cmd.addParam();
+
+ // create the command
+ cmd.select (BRAND.NAME, MODEL.CONFIG_NAME, MODEL.BASE_PRICE,
MODEL.ENGINE_TYPE, MODEL.ENGINE_POWER)
+ .join (MODEL.WMI, BRAND.WMI)
+ .where (BRAND.NAME.is(brandParam))
+ .where (MODEL.ENGINE_TYPE.is(engineTypeParam))
+ .orderBy (BRAND.NAME.desc(), MODEL.CONFIG_NAME.asc());
+
+ // set the params
+ brandParam.setValue("Tesla");
+ engineTypeParam.setValue(EngineType.E);
+ // and run
+ List<DataListEntry> list = context.getUtils().queryDataList(cmd);
+ for (DataListEntry dle : list)
+ System.out.println(dle.toString());
+
+ // change params
+ brandParam.setValue("Volkswagen");
+ engineTypeParam.setValue(EngineType.P);
+ // and run again
+ list = context.getUtils().queryDataList(cmd);
+ for (DataListEntry dle : list)
+ System.out.println(dle.toString());
}
@@ -434,12 +484,33 @@ public class SampleAdvApp
CarSalesDB.Brand BRAND = carSales.BRAND;
CarSalesDB.Model MODEL = carSales.MODEL;
// create command
+ /*
DBCommand cmd = context.createCommand()
.set (MODEL.BASE_PRICE.to(55000)) // set the price-tag
.join (MODEL.WMI, BRAND.WMI)
.where(BRAND.NAME.is("Tesla"))
.where(MODEL.NAME.is("Model 3").and(MODEL.TRIM.is("Performance")));
+ */
+ // create command
+ DBCommand cmd = context.createCommand()
+ // increase model base prices by 5%
+ .set
(MODEL.BASE_PRICE.to(MODEL.BASE_PRICE.multiplyWith(105).divideBy(100).round(0)))
+ .join (MODEL.WMI, BRAND.WMI)
+ // on all Volkswagen Tiguan with Diesel engine
+ .where(BRAND.NAME.is("Volkswagen"))
+
.where(MODEL.NAME.is("Tiguan").and(MODEL.ENGINE_TYPE.is(EngineType.D)));
+
+ // execute Update statement
+ int count = context.executeUpdate(cmd);
+ log.info("{} models affected", count);
+
+ System.out.println("---------------------------------");
+ System.out.println(HtmlGenUtil.codeToHtml(carSales,
HtmlGenUtil.codePriceUpdate));
+ System.out.println("---------------------------------");
+ System.out.println(HtmlGenUtil.sqlToHtml(carSales, cmd.getUpdate()));
+ System.out.println("---------------------------------");
+
/*
* Clone test
DBCommand cl1 = cmd.clone();
@@ -449,8 +520,6 @@ public class SampleAdvApp
log.info("cmd= {} params={}", cl1.getUpdate(), cl1.getParamValues());
*/
- // and off you go...
- context.executeUpdate(cmd);
}
private void queryViewDemo()
@@ -489,7 +558,6 @@ public class SampleAdvApp
{
System.out.println(dle.toString());
}
-
}
/**
@@ -1065,4 +1133,6 @@ public class SampleAdvApp
reader.close();
}
}
+
+
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
b/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
index d1a4549..d202322 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
@@ -688,7 +688,16 @@ public abstract class DBCommand extends DBCommandExpr
// additional constraints
DBCompareExpr where = null;
for (int i=0; i<addlConstraints.length; i++)
- where = (where!=null ? where.and(addlConstraints[i]) :
addlConstraints[i]);
+ {
+ DBCompareExpr cmpExpr = addlConstraints[i];
+ // Check if prepared statements are enabled
+ if (isPreparedStatementsEnabled())
+ { // use command params
+ cmpExpr.prepareCommand(this);
+ }
+ // Chain with previouss
+ where = (where!=null ? where.and(cmpExpr) : cmpExpr);
+ }
if (where!=null)
join.where(where);
// done
@@ -715,15 +724,29 @@ public abstract class DBCommand extends DBCommandExpr
* TODO: Find a better solution / Make DBColumnJoinExpr multi-column
*/
DBColumnJoinExpr join = new DBColumnJoinExpr(left[0], right[0],
joinType);
- // additional constraints
+ // compare the columns except the first
DBCompareExpr where = null;
for (int i=1; i<left.length; i++)
{ // add to where list
DBCompareExpr cmpExpr = right[i].is(left[i]);
+ // Check if prepared statements are enabled
+ if (isPreparedStatementsEnabled())
+ { // use command params
+ cmpExpr.prepareCommand(this);
+ }
where = (where!=null ? where.and(cmpExpr) : cmpExpr);
}
+ // additional constraints
for (int i=0; i<addlConstraints.length; i++)
- where = (where!=null ? where.and(addlConstraints[i]) :
addlConstraints[i]);
+ {
+ DBCompareExpr cmpExpr = addlConstraints[i];
+ // Check if prepared statements are enabled
+ if (isPreparedStatementsEnabled())
+ { // use command params
+ cmpExpr.prepareCommand(this);
+ }
+ where = (where!=null ? where.and(cmpExpr) : cmpExpr);
+ }
if (where!=null)
join.where(where);
// done
diff --git a/pom.xml b/pom.xml
index b5204b4..a8547ff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -198,23 +198,23 @@
</profiles>
-
- <url>http://empire-db.apache.org/${project.artifactId}</url>
+ <!-- project info -->
+ <url>https://empire-db.apache.org</url>
<organization>
<name>Apache Software Foundation</name>
- <url>http://apache.org</url>
+ <url>https://apache.org</url>
</organization>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
-
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
-
<connection>scm:git:http://git-wip-us.apache.org/repos/asf/empire-db.git</connection>
-
<developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/empire-db.git</developerConnection>
-
<url>http://git-wip-us.apache.org/repos/asf/wicket/repo?p=empire-db.git</url>
+
<connection>scm:git:https://gitbox.apache.org/repos/asf?p=empire-db.git</connection>
+
<developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf?p=empire-db.git</developerConnection>
+
<url>https://gitbox.apache.org/repos/asf/wicket/repo?p=empire-db.git</url>
<tag>HEAD</tag>
</scm>
@@ -224,26 +224,28 @@
<post>[email protected]</post>
<subscribe>[email protected]</subscribe>
<unsubscribe>[email protected]</unsubscribe>
-
<archive>http://mail-archives.apache.org/mod_mbox/empire-user/</archive>
+
<archive>https://lists.apache.org/[email protected]</archive>
</mailingList>
<mailingList>
<name>Empire-db Development List</name>
<post>[email protected]</post>
<subscribe>[email protected]</subscribe>
<unsubscribe>[email protected]</unsubscribe>
-
<archive>http://mail-archives.apache.org/mod_mbox/empire-dev/</archive>
+
<archive>https://lists.apache.org/[email protected]</archive>
</mailingList>
<mailingList>
<name>Empire-db commit List</name>
<subscribe>[email protected]</subscribe>
<unsubscribe>[email protected]</unsubscribe>
-
<archive>http://mail-archives.apache.org/mod_mbox/empire-commits/</archive>
+
<archive>https://lists.apache.org/[email protected]</archive>
</mailingList>
</mailingLists>
+
<issueManagement>
<system>jira</system>
<url>https://issues.apache.org/jira/browse/EMPIREDB</url>
</issueManagement>
+
<dependencyManagement>
<dependencies>
<dependency>