This is an automated email from the ASF dual-hosted git repository.
cgarcia pushed a commit to branch feature/merlot
in repository https://gitbox.apache.org/repos/asf/plc4x-extras.git
The following commit(s) were added to refs/heads/feature/merlot by this push:
new 3aab1ae Update RT Database.
3aab1ae is described below
commit 3aab1aef6336065bc469189173aefa7378d0dbc9
Author: César García <[email protected]>
AuthorDate: Wed Aug 21 13:46:13 2024 -0400
Update RT Database.
---
.../java/org/apache/plc4x/merlot/api/PlcItem.java | 2 +-
.../apache/plc4x/merlot/api/PlcItemListener.java | 2 +-
.../merlot/api/impl/PlcGeneralFunctionImpl.java | 2 +-
.../apache/plc4x/merlot/api/impl/PlcItemImpl.java | 165 ++++++++++++---------
.../plc4x/merlot/das/base/impl/BaseItemImpl.java | 2 +-
.../merlot/org.apache.plc4x.merlot.db/pom.xml | 1 +
.../plc4x/merlot/db/command/DBAddCommand.java | 2 +-
.../plc4x/merlot/db/command/DBDumpBorrar.java | 75 ++++++++++
.../plc4x/merlot/db/core/DBShortFactory.java | 37 ++++-
.../resources/OSGI-INF/blueprint/db-service.xml | 7 +
.../src/main/feature/feature.xml | 1 +
11 files changed, 222 insertions(+), 74 deletions(-)
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/PlcItem.java
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/PlcItem.java
index 9ae529e..cf9ffa6 100644
---
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/PlcItem.java
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/PlcItem.java
@@ -181,7 +181,7 @@ public interface PlcItem {
/*
*
*/
- public byte[] getItemBytes();
+ public byte[] getInnerBuffer();
/*
*
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/PlcItemListener.java
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/PlcItemListener.java
index 8ad1804..909c8eb 100644
---
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/PlcItemListener.java
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/PlcItemListener.java
@@ -23,7 +23,7 @@ import io.netty.buffer.ByteBuf;
public interface PlcItemListener {
- void atach(final PlcItem plcitem);
+ void atach(final PlcItem plcItem);
void detach();
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/impl/PlcGeneralFunctionImpl.java
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/impl/PlcGeneralFunctionImpl.java
index 0fe564a..61030e5 100644
---
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/impl/PlcGeneralFunctionImpl.java
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/impl/PlcGeneralFunctionImpl.java
@@ -594,7 +594,7 @@ public class PlcGeneralFunctionImpl implements
PlcGeneralFunction {
@Override
public byte[] getPlcItemBytes(UUID item_uid) {
final PlcItem item = getPlcItem(item_uid);
- return item.getItemBytes();
+ return item.getInnerBuffer();
}
@Override
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/impl/PlcItemImpl.java
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/impl/PlcItemImpl.java
index aecae77..5b9f80f 100644
---
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/impl/PlcItemImpl.java
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.api/src/main/java/org/apache/plc4x/merlot/api/impl/PlcItemImpl.java
@@ -20,6 +20,7 @@ package org.apache.plc4x.merlot.api.impl;
import com.lmax.disruptor.RingBuffer;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import java.time.LocalDate;
import java.time.ZoneOffset;
@@ -33,6 +34,7 @@ import org.apache.plc4x.java.api.messages.PlcReadResponse;
import org.apache.plc4x.java.api.model.PlcTag;
import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.spi.values.PlcList;
import org.apache.plc4x.merlot.api.PlcItem;
import org.apache.plc4x.merlot.api.PlcItemListener;
@@ -60,6 +62,8 @@ public class PlcItemImpl implements PlcItem {
private PlcValue itemPlcValue = null;
private LinkedList<PlcItemListener> itemClients = null;
+
+ private byte[] itemInnerBuffer = null;
private ByteBuf itemBuffer = null;
private long itemTransmit = 0;
@@ -220,64 +224,82 @@ public class PlcItemImpl implements PlcItem {
@Override
public void setPlcValue(PlcValue plcvalue) {
+ if (null == itemInnerBuffer) {
+ int size = (plcvalue instanceof PlcList) ?
+ ((PlcList) plcvalue).getLength() *
+ ((PlcList) plcvalue).getList().get(0).getRaw().length :
+ -1;
+ itemInnerBuffer = (size == -1) ? new
byte[plcvalue.getRaw().length] :
+ new byte[size];
+ itemBuffer = Unpooled.wrappedBuffer(itemInnerBuffer);
+ }
- lock.lock();
- try {
- this.itemPlcValue = plcvalue;
- itemBuffer.clear();
- switch (itemPlcTag.getPlcValueType()){
- case BYTE:
- itemPlcValue.getList().forEach(p ->
{itemBuffer.writeByte(p.getByte());});
- break;
- case CHAR:
- case STRING:
- plcResponse.getAllStrings(itemUid.toString()).forEach(s ->
{
- itemBuffer.writeBytes(s.getBytes());
- });
- itemPlcValue.getList().forEach(p ->
{itemBuffer.writeBytes(p.getRaw());});
- break;
- case WORD:
- case USINT:
- case SINT:
- case UINT:
- case INT:
- case DINT:
- itemPlcValue.getList().forEach(p ->
{itemBuffer.writeShort(p.getShort());});
- break;
- case UDINT:
- case ULINT:
- case LINT:
- itemPlcValue.getList().forEach(p ->
{itemBuffer.writeLong(p.getLong());});
- break;
- case BOOL:
- itemPlcValue.getList().forEach(p ->
{itemBuffer.writeBoolean(p.getBoolean());});
- break;
- case REAL:
- case LREAL:
- itemPlcValue.getList().forEach(p ->
{itemBuffer.writeFloat(p.getFloat());});
- break;
- case DATE_AND_TIME:
- itemPlcValue.getList().forEach(p ->
{itemBuffer.writeLong(p.getDateTime().toEpochSecond(ZoneOffset.UTC));});
- break;
- case DATE:
- plcResponse.getAllDates(itemUid.toString()).forEach(dt -> {
- itemBuffer.writeLong(dt.toEpochDay());
- });
- itemPlcValue.getList().forEach(p ->
{itemBuffer.writeLong(p.getDateTime().toLocalDate().toEpochDay());});
- break;
- case TIME:
- break;
- case TIME_OF_DAY:
- itemPlcValue.getList().forEach(p ->
{itemBuffer.writeLong(p.getTime().toEpochSecond(LocalDate.MAX,
ZoneOffset.UTC));});
- break;
- default:
- throw new NotImplementedException("The response type for
datatype " + itemPlcValue.getPlcValueType() + " is not yet implemented");
- }
- } catch (Exception ex) {
-
- } finally {
- lock.unlock();
+ itemBuffer.resetWriterIndex();
+ if (plcvalue instanceof PlcList) {
+ ((PlcList) plcvalue).getList().forEach(v ->
itemBuffer.writeBytes(v.getRaw()));
+ } else {
+ itemBuffer.writeBytes(plcvalue.getRaw());
}
+
+ itemClients.forEach(c -> c.update());
+//
+// lock.lock();
+// try {
+// this.itemPlcValue = plcvalue;
+// itemBuffer.clear();
+// switch (itemPlcTag.getPlcValueType()){
+// case BYTE:
+// itemPlcValue.getList().forEach(p ->
{itemBuffer.writeByte(p.getByte());});
+// break;
+// case CHAR:
+// case STRING:
+// plcResponse.getAllStrings(itemUid.toString()).forEach(s
-> {
+// itemBuffer.writeBytes(s.getBytes());
+// });
+// itemPlcValue.getList().forEach(p ->
{itemBuffer.writeBytes(p.getRaw());});
+// break;
+// case WORD:
+// case USINT:
+// case SINT:
+// case UINT:
+// case INT:
+// case DINT:
+// itemPlcValue.getList().forEach(p ->
{itemBuffer.writeShort(p.getShort());});
+// break;
+// case UDINT:
+// case ULINT:
+// case LINT:
+// itemPlcValue.getList().forEach(p ->
{itemBuffer.writeLong(p.getLong());});
+// break;
+// case BOOL:
+// itemPlcValue.getList().forEach(p ->
{itemBuffer.writeBoolean(p.getBoolean());});
+// break;
+// case REAL:
+// case LREAL:
+// itemPlcValue.getList().forEach(p ->
{itemBuffer.writeFloat(p.getFloat());});
+// break;
+// case DATE_AND_TIME:
+// itemPlcValue.getList().forEach(p ->
{itemBuffer.writeLong(p.getDateTime().toEpochSecond(ZoneOffset.UTC));});
+// break;
+// case DATE:
+// plcResponse.getAllDates(itemUid.toString()).forEach(dt
-> {
+// itemBuffer.writeLong(dt.toEpochDay());
+// });
+// itemPlcValue.getList().forEach(p ->
{itemBuffer.writeLong(p.getDateTime().toLocalDate().toEpochDay());});
+// break;
+// case TIME:
+// break;
+// case TIME_OF_DAY:
+// itemPlcValue.getList().forEach(p ->
{itemBuffer.writeLong(p.getTime().toEpochSecond(LocalDate.MAX,
ZoneOffset.UTC));});
+// break;
+// default:
+// throw new NotImplementedException("The response type for
datatype " + itemPlcValue.getPlcValueType() + " is not yet implemented");
+// }
+// } catch (Exception ex) {
+//
+// } finally {
+// lock.unlock();
+// }
}
@Override
@@ -305,15 +327,8 @@ public class PlcItemImpl implements PlcItem {
}
@Override
- public byte[] getItemBytes() {
- lock.lock();
- byte[] bytebuffer;
- try {
- bytebuffer = itemBuffer.array();
- } finally {
- lock.unlock();
- }
- return bytebuffer;
+ public byte[] getInnerBuffer() {
+ return itemInnerBuffer;
}
@Override
@@ -374,10 +389,26 @@ public class PlcItemImpl implements PlcItem {
@Override
public String toString() {
- return "";
+ StringBuilder sb = new StringBuilder(100);
+ sb.append("Name: ").append(itemName).append("\r\n").
+ append("Description: ").append(itemDescription).append("\r\n").
+ append("Id: ").append(itemId).append("\r\n").
+ append("UID: ").append(itemUid).append("\r\n").
+ append("Is enable: ").append(itemEnable).append("\r\n").
+ append("Access rigths: ").append(itemAccessrigths).append("\r\n").
+ append("Disable output:
").append(itemDisableOutput).append("\r\n").
+ append("Number of clients: ").append(itemClients).append("\r\n").
+ append("Transmits: ").append(itemClients).append("\r\n").
+ append("Last transmits date:
").append(lastWriteDate).append("\r\n").
+ append("Receives: ").append(itemClients).append("\r\n").
+ append("Last receives date:
").append(lastReadDate).append("\r\n").
+ append("Errors: ").append(itemClients).append("\r\n").
+ append("Last error date: ").append(lastErrorDate).append("\r\n").
+ append("Data buffer: ").append("\r\n").
+ append(ByteBufUtil.prettyHexDump(itemBuffer)).append("\r\n");
+ return sb.toString();
}
-
public static class PlcItemBuilder {
private final String itemName;
private UUID itemUid;
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.base/src/main/java/org/apache/plc4x/merlot/das/base/impl/BaseItemImpl.java
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.base/src/main/java/org/apache/plc4x/merlot/das/base/impl/BaseItemImpl.java
index 40e1039..70833ff 100644
---
a/plc4j/tools/merlot/org.apache.plc4x.merlot.das.base/src/main/java/org/apache/plc4x/merlot/das/base/impl/BaseItemImpl.java
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.das.base/src/main/java/org/apache/plc4x/merlot/das/base/impl/BaseItemImpl.java
@@ -72,7 +72,7 @@ public class BaseItemImpl implements PlcItem {
}
@Override
- public byte[] getItemBytes() {
+ public byte[] getInnerBuffer() {
throw new UnsupportedOperationException("Not supported yet."); //
Generated from
nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
diff --git a/plc4j/tools/merlot/org.apache.plc4x.merlot.db/pom.xml
b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/pom.xml
index 4dfdc58..968dd90 100644
--- a/plc4j/tools/merlot/org.apache.plc4x.merlot.db/pom.xml
+++ b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/pom.xml
@@ -46,6 +46,7 @@
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>0.13.0-SNAPSHOT</Bundle-Version>
<Export-Package>org.apache.plc4x.merlot.db*;version=0.13.0-SNAPSHOT</Export-Package>
+
<Karaf-Commands>org.apache.plc4x.merlot.db*</Karaf-Commands>
<Import-Package>*</Import-Package>
</instructions>
</configuration>
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/command/DBAddCommand.java
b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/command/DBAddCommand.java
index 0ccb182..0ee9cac 100644
---
a/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/command/DBAddCommand.java
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/command/DBAddCommand.java
@@ -119,7 +119,7 @@ public class DBAddCommand implements Action {
//TODO: Devolver "true" si se pudo agregar el record.
//dbControl.attach(record);
//TODO: Agregar solamente si se pudo agregar al driver
- //master.addRecord(record);
+ master.addRecord(record);
System.out.println("Record: \r\n" + record.toString());
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/command/DBDumpBorrar.java
b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/command/DBDumpBorrar.java
new file mode 100644
index 0000000..ac01b2b
--- /dev/null
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/command/DBDumpBorrar.java
@@ -0,0 +1,75 @@
+/*
+ * 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.plc4x.merlot.db.command;
+
+import java.util.List;
+import java.util.Random;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.epics.pvdata.pv.PVShort;
+import org.epics.pvdata.pv.PVStructure;
+import org.epics.pvdatabase.PVDatabase;
+import org.epics.pvdatabase.PVRecord;
+import org.osgi.framework.BundleContext;
+
+
+@Command(scope = "db", name = "borrar", description = "Dump information from a
list of records.")
+@Service
+public class DBDumpBorrar implements Action {
+ @Reference
+ BundleContext bundleContext;
+
+ @Reference
+ PVDatabase master;
+
+ @Argument(index = 0, name = "records", description = "List of records to
dump information", required = true, multiValued = true)
+ List<String> records;
+
+ Random rand = new Random();
+
+ @Override
+ public Object execute() throws Exception {
+ for (String record:records){
+ PVRecord pvRecord = master.findRecord(record);
+ PVStructure structure = pvRecord.getPVStructure();
+ PVShort pvShort = structure.getShortField("value");
+
+ pvShort.put((short) rand.nextInt(1000));
+ }
+ return null;
+ }
+
+ private void PrintPVRecord(String record, PVRecord pvRecord) {
+ ShellTable table = new ShellTable();
+ table.column("Field");
+ table.column("Value");;
+ table.emptyTableText("Record not found.");
+ if (!(pvRecord == null)){
+ System.out.println(pvRecord.toString()+"\r\n");
+ } else {
+ System.out.println("Record \"" + record + "\" not found.");
+ }
+ //table.print(System.out);
+ }
+
+}
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/core/DBShortFactory.java
b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/core/DBShortFactory.java
index c6c8ec1..38e0779 100644
---
a/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/core/DBShortFactory.java
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/java/org/apache/plc4x/merlot/db/core/DBShortFactory.java
@@ -18,6 +18,10 @@
*/
package org.apache.plc4x.merlot.db.core;
+import io.grpc.netty.shaded.io.netty.buffer.ByteBuf;
+import io.grpc.netty.shaded.io.netty.buffer.Unpooled;
+import org.apache.plc4x.merlot.api.PlcItem;
+import org.apache.plc4x.merlot.api.PlcItemListener;
import org.epics.nt.NTScalar;
import org.epics.nt.NTScalarArray;
import org.epics.nt.NTScalarArrayBuilder;
@@ -27,6 +31,7 @@ import org.epics.pvdata.pv.FieldBuilder;
import org.epics.pvdata.pv.FieldCreate;
import org.epics.pvdata.pv.PVShort;
import org.epics.pvdata.pv.PVShortArray;
+import org.epics.pvdata.pv.PVString;
import org.epics.pvdata.pv.PVStructure;
import org.epics.pvdata.pv.ScalarType;
import org.epics.pvdatabase.PVRecord;
@@ -81,13 +86,22 @@ public class DBShortFactory extends DBBaseFactory {
return pvRecord;
}
- class DBShortRecord extends PVRecord {
+ class DBShortRecord extends PVRecord implements PlcItemListener {
- private PVShort value;
+ private PVShort value;
+ private PlcItem plcItem = null;
+ private ByteBuf innerBuffer = null;
+ private int offset = 0;
public DBShortRecord(String recordName,PVStructure pvStructure) {
super(recordName, pvStructure);
value = pvStructure.getShortField("value");
+ PVString id = pvStructure.getStringField("id");
+ String strId = id.get();
+ String[] strParts = strId.split("\\/");
+ if (strParts.length == 2) {
+ offset = Integer.getInteger(strParts[1]) * Short.BYTES;
+ }
}
/**
@@ -97,6 +111,25 @@ public class DBShortFactory extends DBBaseFactory {
public void process()
{
super.process();
+ if (null != plcItem )
+ plcItem.itemWrite();
+ }
+
+ @Override
+ public void atach(final PlcItem plcItem) {
+ this.plcItem = plcItem;
+ innerBuffer = Unpooled.wrappedBuffer(plcItem.getInnerBuffer(),
offset, Short.BYTES);
+ }
+
+ @Override
+ public void detach() {
+ this.plcItem = null;
+ }
+
+ @Override
+ public void update() {
+ if (null != plcItem)
+ value.put(innerBuffer.getShort(0));
}
}
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/resources/OSGI-INF/blueprint/db-service.xml
b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/resources/OSGI-INF/blueprint/db-service.xml
index a361cf0..8d09aea 100644
---
a/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/resources/OSGI-INF/blueprint/db-service.xml
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.db/src/main/resources/OSGI-INF/blueprint/db-service.xml
@@ -65,6 +65,13 @@
<argument ref="DBBean"/>
</bean>
+ <bean id="beanServer"
+ class="org.epics.pvaccess.ServerFactory"
+ init-method="start">
+ </bean>
+
+
+
<reference-list id="refRPCService"
interface="org.epics.pvaccess.server.rpc.RPCService"
availability="optional">
diff --git
a/plc4j/tools/merlot/org.apache.plc4x.merlot.features/src/main/feature/feature.xml
b/plc4j/tools/merlot/org.apache.plc4x.merlot.features/src/main/feature/feature.xml
index a4559c9..2106da1 100644
---
a/plc4j/tools/merlot/org.apache.plc4x.merlot.features/src/main/feature/feature.xml
+++
b/plc4j/tools/merlot/org.apache.plc4x.merlot.features/src/main/feature/feature.xml
@@ -110,6 +110,7 @@
<bundle
start-level="100">mvn:org.apache.plc4x.merlot.das.base/org.apache.plc4x.merlot.das.base/${project.version}</bundle>
<configfile
finalname="/etc/org.apache.plc4x.merlot.das.devices.cfg">mvn:org.apache.plc4x.merlot.das.base/org.apache.plc4x.merlot.das.base/${project.version}/cfg</configfile>
+ <bundle
start-level="60">mvn:org.apache.plc4x.merlot.db/org.apache.plc4x.merlot.db/${project.version}</bundle>
<!-- <bundle
start-level="40">mvn:org.apache.plc4x.dummy/org.apache.plc4x.dummy/${project.version}</bundle>
-->
</feature>