567 lines
20 KiB
Java
567 lines
20 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* javax.baja.naming.BOrdList
|
|
* javax.baja.nre.util.SortUtil
|
|
* javax.baja.sys.BAbsTime
|
|
* javax.baja.sys.Context
|
|
* javax.baja.sys.Cursor
|
|
* javax.baja.ui.table.TableModel
|
|
* javax.baja.util.BUuid
|
|
*/
|
|
package com.tridium.alarm.ui;
|
|
|
|
import com.tridium.alarm.BConsoleRecipient;
|
|
import com.tridium.alarm.ui.AlarmTableModel;
|
|
import com.tridium.alarm.ui.BIAlarmServiceView;
|
|
import com.tridium.alarm.ui.ConsoleColumns;
|
|
import com.tridium.alarm.ui.ConsoleTableModel;
|
|
import java.util.ArrayList;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import javax.baja.alarm.BAckState;
|
|
import javax.baja.alarm.BAlarmRecord;
|
|
import javax.baja.naming.BOrdList;
|
|
import javax.baja.nre.util.SortUtil;
|
|
import javax.baja.sys.BAbsTime;
|
|
import javax.baja.sys.Context;
|
|
import javax.baja.sys.Cursor;
|
|
import javax.baja.ui.table.TableModel;
|
|
import javax.baja.util.BUuid;
|
|
|
|
public class SourceTableModel
|
|
extends ConsoleTableModel {
|
|
protected BConsoleRecipient recip;
|
|
private ArrayList srcList = new ArrayList();
|
|
private HashMap bySrc = new HashMap();
|
|
private UuidList byUuid = new UuidList();
|
|
private boolean holdUpdates = false;
|
|
private boolean updatePending = false;
|
|
BIAlarmServiceView alarmServiceView;
|
|
public Context context;
|
|
|
|
public SourceTableModel(ConsoleColumns consoleColumns, BConsoleRecipient bConsoleRecipient, Context context) {
|
|
super(consoleColumns);
|
|
this.recip = bConsoleRecipient;
|
|
this.context = context;
|
|
}
|
|
|
|
public void init(BIAlarmServiceView bIAlarmServiceView, Context context) {
|
|
super.init(bIAlarmServiceView, context);
|
|
this.alarmServiceView = bIAlarmServiceView;
|
|
this.context = context;
|
|
}
|
|
|
|
public synchronized void load(Cursor cursor) {
|
|
this.setHoldUpdates(true);
|
|
this.clear();
|
|
this.doAdd(cursor);
|
|
this.setHoldUpdates(false);
|
|
}
|
|
|
|
public synchronized void add(Cursor cursor) {
|
|
this.setHoldUpdates(true);
|
|
this.doAdd(cursor);
|
|
this.setHoldUpdates(false);
|
|
}
|
|
|
|
private synchronized void doAdd(Cursor cursor) {
|
|
while (cursor.next()) {
|
|
BAlarmRecord bAlarmRecord = (BAlarmRecord)cursor.get();
|
|
this.recip.lease();
|
|
if (!this.recip.accept(bAlarmRecord)) continue;
|
|
bAlarmRecord = this.updateAlarmRecord(bAlarmRecord);
|
|
this.update(bAlarmRecord, false);
|
|
}
|
|
this.sortByColumn(this.getLastSortColumn(), this.getLastSortAscending());
|
|
}
|
|
|
|
protected BAlarmRecord updateAlarmRecord(BAlarmRecord bAlarmRecord) {
|
|
return bAlarmRecord;
|
|
}
|
|
|
|
public synchronized BAlarmRecord getRecord(int n) {
|
|
if (n < this.srcList.size()) {
|
|
return ((AlarmList)this.srcList.get(n)).getMostRecentRecord();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public synchronized int getRecordCount(int n) {
|
|
return ((AlarmList)this.srcList.get(n)).size();
|
|
}
|
|
|
|
public synchronized BAlarmRecord getRecordAt(int n, int n2) {
|
|
AlarmList alarmList = (AlarmList)this.srcList.get(n);
|
|
AlarmEntry alarmEntry = alarmList.getEntry(n2);
|
|
return alarmEntry.rec;
|
|
}
|
|
|
|
public synchronized void clear() {
|
|
this.srcList.clear();
|
|
this.bySrc.clear();
|
|
this.byUuid.clear();
|
|
this.updateTable();
|
|
}
|
|
|
|
public int getAlarmCount() {
|
|
return this.byUuid.getAlarmCount();
|
|
}
|
|
|
|
public int getSourceCount() {
|
|
return this.getRowCount();
|
|
}
|
|
|
|
private synchronized void add(BAlarmRecord bAlarmRecord, boolean bl) {
|
|
BOrdList bOrdList = (bAlarmRecord = this.updateAlarmRecord(bAlarmRecord)).getSource();
|
|
AlarmList alarmList = (AlarmList)this.bySrc.get(bOrdList);
|
|
if (alarmList == null) {
|
|
alarmList = new AlarmList(bOrdList);
|
|
this.srcList.add(alarmList);
|
|
this.bySrc.put(bOrdList, alarmList);
|
|
AlarmEntry alarmEntry = alarmList.add(bAlarmRecord);
|
|
this.byUuid.put(bAlarmRecord.getUuid(), alarmEntry);
|
|
} else {
|
|
AlarmEntry alarmEntry = alarmList.add(bAlarmRecord);
|
|
this.byUuid.put(bAlarmRecord.getUuid(), alarmEntry);
|
|
}
|
|
if (bl) {
|
|
this.sortListByColumn(alarmList, this.getLastSortColumn(), this.getLastSortAscending());
|
|
this.sortByColumn(this.getLastSortColumn(), this.getLastSortAscending());
|
|
}
|
|
this.updateTable();
|
|
}
|
|
|
|
public synchronized void update(BAlarmRecord bAlarmRecord) {
|
|
this.update(bAlarmRecord, true);
|
|
}
|
|
|
|
public synchronized void update(BAlarmRecord bAlarmRecord, boolean bl) {
|
|
AlarmEntry alarmEntry = this.byUuid.get(bAlarmRecord.getUuid(), bAlarmRecord.getSource());
|
|
if (alarmEntry != null && alarmEntry.rec.getSource().equals((Object)bAlarmRecord.getSource())) {
|
|
BAlarmRecord bAlarmRecord2 = alarmEntry.rec;
|
|
alarmEntry.rec = bAlarmRecord = this.updateAlarmRecord(bAlarmRecord);
|
|
if (!bAlarmRecord2.isAcknowledged() && !bAlarmRecord2.isAckPending() && alarmEntry.rec.isAckPending()) {
|
|
alarmEntry.list.ackPendingCount++;
|
|
alarmEntry.list.unackedCount--;
|
|
} else if (bAlarmRecord2.isAckPending() && alarmEntry.rec.isAcknowledged()) {
|
|
alarmEntry.list.ackPendingCount--;
|
|
alarmEntry.list.ackedCount++;
|
|
} else if (bAlarmRecord2.isAckPending() && !alarmEntry.rec.isAcknowledged() && !alarmEntry.rec.isAckPending()) {
|
|
alarmEntry.list.ackPendingCount--;
|
|
alarmEntry.list.unackedCount++;
|
|
} else if (bAlarmRecord2.isAcknowledged() && !alarmEntry.rec.isAcknowledged() && !alarmEntry.rec.isAckPending()) {
|
|
alarmEntry.list.ackedCount--;
|
|
alarmEntry.list.unackedCount++;
|
|
} else if (bAlarmRecord2.isAcknowledged() && alarmEntry.rec.isAckPending()) {
|
|
alarmEntry.list.ackedCount--;
|
|
alarmEntry.list.ackPendingCount++;
|
|
} else if (alarmEntry.rec.isAcknowledged() && !bAlarmRecord2.isAcknowledged() && !bAlarmRecord2.isAckPending()) {
|
|
alarmEntry.list.ackedCount++;
|
|
alarmEntry.list.unackedCount--;
|
|
}
|
|
alarmEntry.list.fireModified();
|
|
this.updateTable();
|
|
} else {
|
|
this.add(bAlarmRecord, bl);
|
|
}
|
|
}
|
|
|
|
public synchronized void remove(BAlarmRecord bAlarmRecord) {
|
|
BUuid bUuid = bAlarmRecord.getUuid();
|
|
AlarmEntry[] alarmEntryArray = this.byUuid.get(bUuid);
|
|
for (int i = 0; i < alarmEntryArray.length; ++i) {
|
|
AlarmEntry alarmEntry = alarmEntryArray[i];
|
|
if (alarmEntry == null) {
|
|
return;
|
|
}
|
|
this.byUuid.remove(bUuid);
|
|
AlarmList alarmList = alarmEntry.list;
|
|
alarmList.remove(alarmEntry);
|
|
if (alarmList.size() != 0) continue;
|
|
this.bySrc.remove(alarmList.getSource());
|
|
this.srcList.remove(alarmList);
|
|
}
|
|
this.sortByColumn(this.getLastSortColumn(), this.getLastSortAscending());
|
|
this.updateTable();
|
|
}
|
|
|
|
public synchronized void removeSource(BOrdList bOrdList) {
|
|
AlarmList alarmList = (AlarmList)this.bySrc.get(bOrdList);
|
|
for (int i = 0; i < alarmList.size(); ++i) {
|
|
AlarmEntry alarmEntry = alarmList.getEntry(i);
|
|
this.byUuid.remove(alarmEntry.rec.getUuid());
|
|
}
|
|
this.bySrc.remove(bOrdList);
|
|
this.srcList.remove(alarmList);
|
|
this.updateTable();
|
|
}
|
|
|
|
public synchronized int getRowCount() {
|
|
return this.srcList.size();
|
|
}
|
|
|
|
public synchronized Object getValueAt(int n, int n2) {
|
|
if (n2 == 3) {
|
|
ConsoleColumns.Column column = this.getColumns().getColumn(n2);
|
|
BAlarmRecord bAlarmRecord = this.getRecord(n);
|
|
if (bAlarmRecord == null) {
|
|
return "";
|
|
}
|
|
AlarmList alarmList = (AlarmList)this.bySrc.get(bAlarmRecord.getSource());
|
|
if (alarmList == null) {
|
|
return "";
|
|
}
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
stringBuffer.append(alarmList.getAckedCount() + " " + BAckState.acked.getDisplayTag(this.context) + " / " + alarmList.getUnackedCount() + " " + BAckState.unacked.getDisplayTag(this.context));
|
|
if (alarmList.getAckPendingCount() > 0) {
|
|
stringBuffer.append(" / " + alarmList.getAckPendingCount() + " " + BAckState.ackPending.getDisplayTag(this.context));
|
|
}
|
|
return stringBuffer.toString();
|
|
}
|
|
return super.getValueAt(n, n2);
|
|
}
|
|
|
|
public synchronized AlarmTableModel getModelForSource(BOrdList bOrdList) {
|
|
AlarmList alarmList = (AlarmList)this.bySrc.get(bOrdList);
|
|
if (alarmList == null) {
|
|
return null;
|
|
}
|
|
AlarmTableModel alarmTableModel = new AlarmTableModel(this.getColumns(), alarmList);
|
|
alarmTableModel.sortByColumn(this.getLastSortColumn(), this.getLastSortAscending());
|
|
alarmTableModel.init(this.alarmServiceView, this.context);
|
|
return alarmTableModel;
|
|
}
|
|
|
|
public synchronized int getUnackedCountForSource(BOrdList bOrdList) {
|
|
if (this.bySrc.get(bOrdList) == null) {
|
|
return 0;
|
|
}
|
|
return ((AlarmList)this.bySrc.get(bOrdList)).getUnackedCount();
|
|
}
|
|
|
|
public synchronized int getAckedCountForSource(BOrdList bOrdList) {
|
|
if (this.bySrc.get(bOrdList) == null) {
|
|
return 0;
|
|
}
|
|
return ((AlarmList)this.bySrc.get(bOrdList)).getAckedCount();
|
|
}
|
|
|
|
public synchronized int getAckPendingCountForSource(BOrdList bOrdList) {
|
|
if (this.bySrc.get(bOrdList) == null) {
|
|
return 0;
|
|
}
|
|
return ((AlarmList)this.bySrc.get(bOrdList)).getAckPendingCount();
|
|
}
|
|
|
|
public synchronized int getAlarmCount(BOrdList bOrdList) {
|
|
if (bOrdList == null) {
|
|
return 0;
|
|
}
|
|
AlarmList alarmList = (AlarmList)this.bySrc.get(bOrdList);
|
|
if (alarmList != null) {
|
|
return alarmList.size();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public synchronized BAlarmRecord getRecord(BOrdList bOrdList, int n) {
|
|
if (bOrdList == null) {
|
|
return null;
|
|
}
|
|
AlarmList alarmList = (AlarmList)this.bySrc.get(bOrdList);
|
|
if (alarmList == null || alarmList.size() == 0) {
|
|
return null;
|
|
}
|
|
return alarmList.getRecord(n);
|
|
}
|
|
|
|
private synchronized void setHoldUpdates(boolean bl) {
|
|
this.holdUpdates = bl;
|
|
if (!this.holdUpdates && this.updatePending) {
|
|
this.updatePending = false;
|
|
this.updateTable();
|
|
}
|
|
}
|
|
|
|
public synchronized void updateTable() {
|
|
if (this.holdUpdates) {
|
|
this.updatePending = true;
|
|
} else {
|
|
super.updateTable();
|
|
}
|
|
}
|
|
|
|
public synchronized void updateTable(boolean bl) {
|
|
if (this.holdUpdates) {
|
|
this.updatePending = true;
|
|
} else {
|
|
super.updateTable(bl);
|
|
}
|
|
}
|
|
|
|
public synchronized void sortByColumn(int n, boolean bl) {
|
|
if (n < 0 || n >= super.getColumnCount()) {
|
|
return;
|
|
}
|
|
this.setInitialSort(n, bl);
|
|
ConsoleColumns.Column column = this.getColumns().getColumn(n);
|
|
if (bl) {
|
|
this.sortSrcList(column, SortUtil.ASCENDING);
|
|
} else {
|
|
this.sortSrcList(column, SortUtil.DESCENDING);
|
|
}
|
|
}
|
|
|
|
public void sortSrcList(ConsoleColumns.Column column, Comparator comparator) {
|
|
int n = this.srcList.size();
|
|
for (int i = n / 2; i >= 1; i /= 2) {
|
|
for (int j = i; j < n; ++j) {
|
|
int n2;
|
|
AlarmList alarmList = (AlarmList)this.srcList.get(j);
|
|
Object object = column.getValue(alarmList.getMostRecentRecord());
|
|
for (n2 = j; n2 >= i && comparator.compare(object, column.getValue(((AlarmList)this.srcList.get(n2 - i)).getMostRecentRecord())) <= 0; n2 -= i) {
|
|
if (comparator.compare(object, column.getValue(((AlarmList)this.srcList.get(n2 - i)).getMostRecentRecord())) == 0) {
|
|
BAbsTime bAbsTime = alarmList.getMostRecentRecord().getTimestamp();
|
|
BAbsTime bAbsTime2 = ((AlarmList)this.srcList.get(n2 - i)).getMostRecentRecord().getTimestamp();
|
|
if (!bAbsTime2.isBefore(bAbsTime)) break;
|
|
this.srcList.set(n2, this.srcList.get(n2 - i));
|
|
continue;
|
|
}
|
|
this.srcList.set(n2, this.srcList.get(n2 - i));
|
|
}
|
|
this.srcList.set(n2, alarmList);
|
|
}
|
|
}
|
|
}
|
|
|
|
public synchronized void sortListByColumn(AlarmList alarmList, int n, boolean bl) {
|
|
if (n < 0 || n >= super.getColumnCount()) {
|
|
return;
|
|
}
|
|
this.setInitialSort(n, bl);
|
|
ConsoleColumns.Column column = this.getColumns().getColumn(n);
|
|
if (bl) {
|
|
alarmList.sort(column, SortUtil.ASCENDING);
|
|
} else {
|
|
alarmList.sort(column, SortUtil.DESCENDING);
|
|
}
|
|
}
|
|
|
|
class UuidList {
|
|
private HashMap byUuid = new HashMap();
|
|
|
|
UuidList() {
|
|
}
|
|
|
|
public void put(BUuid bUuid, AlarmEntry alarmEntry) {
|
|
HashMap<BOrdList, AlarmEntry> hashMap = (HashMap<BOrdList, AlarmEntry>)this.byUuid.get(bUuid);
|
|
if (hashMap == null) {
|
|
hashMap = new HashMap<BOrdList, AlarmEntry>();
|
|
}
|
|
hashMap.put(alarmEntry.rec.getSource(), alarmEntry);
|
|
this.byUuid.put(bUuid, hashMap);
|
|
}
|
|
|
|
public AlarmEntry get(BUuid bUuid, BOrdList bOrdList) {
|
|
HashMap hashMap = (HashMap)this.byUuid.get(bUuid);
|
|
if (hashMap == null) {
|
|
return null;
|
|
}
|
|
return (AlarmEntry)hashMap.get(bOrdList);
|
|
}
|
|
|
|
public AlarmEntry[] get(BUuid bUuid) {
|
|
HashMap hashMap = (HashMap)this.byUuid.get(bUuid);
|
|
if (hashMap == null) {
|
|
return new AlarmEntry[0];
|
|
}
|
|
Object[] objectArray = hashMap.values().toArray();
|
|
AlarmEntry[] alarmEntryArray = new AlarmEntry[objectArray.length];
|
|
for (int i = 0; i < objectArray.length; ++i) {
|
|
alarmEntryArray[i] = (AlarmEntry)objectArray[i];
|
|
}
|
|
return alarmEntryArray;
|
|
}
|
|
|
|
public int size() {
|
|
return this.byUuid.size();
|
|
}
|
|
|
|
public int getAlarmCount() {
|
|
int n = 0;
|
|
Iterator iterator = this.byUuid.values().iterator();
|
|
while (iterator.hasNext()) {
|
|
HashMap hashMap = (HashMap)iterator.next();
|
|
if (hashMap == null) continue;
|
|
n += hashMap.size();
|
|
}
|
|
return n;
|
|
}
|
|
|
|
public void clear() {
|
|
this.byUuid.clear();
|
|
}
|
|
|
|
public void remove(BUuid bUuid) {
|
|
this.byUuid.remove(bUuid);
|
|
}
|
|
}
|
|
|
|
class AlarmEntry {
|
|
public AlarmList list;
|
|
public BAlarmRecord rec;
|
|
|
|
public AlarmEntry(AlarmList alarmList, BAlarmRecord bAlarmRecord) {
|
|
this.list = alarmList;
|
|
this.rec = bAlarmRecord;
|
|
}
|
|
}
|
|
|
|
class AlarmList {
|
|
private BOrdList src;
|
|
private ArrayList entries;
|
|
private TableModel tableModel;
|
|
private AlarmEntry mostRecentEntry;
|
|
private int ackedCount = 0;
|
|
private int unackedCount = 0;
|
|
private int ackPendingCount = 0;
|
|
|
|
public AlarmList(BOrdList bOrdList) {
|
|
this.src = bOrdList;
|
|
this.entries = new ArrayList(1);
|
|
}
|
|
|
|
public void setModel(TableModel tableModel) {
|
|
this.tableModel = tableModel;
|
|
}
|
|
|
|
public TableModel getModel() {
|
|
return this.tableModel;
|
|
}
|
|
|
|
public void fireModified() {
|
|
if (this.tableModel != null) {
|
|
this.tableModel.updateTable();
|
|
}
|
|
}
|
|
|
|
public BOrdList getSource() {
|
|
return this.src;
|
|
}
|
|
|
|
public int size() {
|
|
return this.entries.size();
|
|
}
|
|
|
|
public AlarmEntry getEntry(int n) {
|
|
return (AlarmEntry)this.entries.get(n);
|
|
}
|
|
|
|
public AlarmEntry getEntry(BUuid bUuid) {
|
|
for (int i = 0; i < this.entries.size(); ++i) {
|
|
AlarmEntry alarmEntry = (AlarmEntry)this.entries.get(i);
|
|
if (!alarmEntry.rec.getUuid().equals((Object)bUuid)) continue;
|
|
return alarmEntry;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int getAckedCount() {
|
|
return this.ackedCount;
|
|
}
|
|
|
|
public int getUnackedCount() {
|
|
return this.unackedCount;
|
|
}
|
|
|
|
public int getAckPendingCount() {
|
|
return this.ackPendingCount;
|
|
}
|
|
|
|
public BAlarmRecord getMostRecentRecord() {
|
|
return this.mostRecentEntry.rec;
|
|
}
|
|
|
|
public BAlarmRecord getRecord(int n) {
|
|
return this.getEntry((int)n).rec;
|
|
}
|
|
|
|
public AlarmEntry add(BAlarmRecord bAlarmRecord) {
|
|
BAbsTime bAbsTime = bAlarmRecord.getTimestamp();
|
|
AlarmEntry alarmEntry = new AlarmEntry(this, bAlarmRecord);
|
|
this.entries.add(alarmEntry);
|
|
if (alarmEntry.rec.isAcknowledged()) {
|
|
++this.ackedCount;
|
|
} else if (alarmEntry.rec.getAckState() == BAckState.ackPending) {
|
|
++this.ackPendingCount;
|
|
} else {
|
|
++this.unackedCount;
|
|
}
|
|
if (this.mostRecentEntry == null || bAbsTime.isAfter(this.mostRecentEntry.rec.getTimestamp())) {
|
|
this.mostRecentEntry = alarmEntry;
|
|
}
|
|
this.fireModified();
|
|
return alarmEntry;
|
|
}
|
|
|
|
public void remove(AlarmEntry alarmEntry) {
|
|
this.entries.remove(alarmEntry);
|
|
if (alarmEntry.rec.isAcknowledged()) {
|
|
--this.ackedCount;
|
|
} else if (alarmEntry.rec.getAckState() == BAckState.ackPending) {
|
|
--this.ackPendingCount;
|
|
} else {
|
|
--this.unackedCount;
|
|
}
|
|
if (alarmEntry.rec.getUuid().equals((Object)this.mostRecentEntry.rec.getUuid())) {
|
|
int n = this.entries.size();
|
|
this.mostRecentEntry = null;
|
|
for (int i = 0; i < n; ++i) {
|
|
if (this.mostRecentEntry == null) {
|
|
this.mostRecentEntry = (AlarmEntry)this.entries.get(i);
|
|
}
|
|
AlarmEntry alarmEntry2 = (AlarmEntry)this.entries.get(i);
|
|
if (!alarmEntry2.rec.getTimestamp().isAfter(this.mostRecentEntry.rec.getTimestamp())) continue;
|
|
this.mostRecentEntry = alarmEntry2;
|
|
}
|
|
}
|
|
this.fireModified();
|
|
}
|
|
|
|
public void removeAll() {
|
|
this.entries.clear();
|
|
this.mostRecentEntry = null;
|
|
this.ackedCount = 0;
|
|
this.unackedCount = 0;
|
|
this.ackPendingCount = 0;
|
|
this.fireModified();
|
|
}
|
|
|
|
public void sort(ConsoleColumns.Column column, Comparator comparator) {
|
|
int n = this.entries.size();
|
|
for (int i = n / 2; i >= 1; i /= 2) {
|
|
for (int j = i; j < n; ++j) {
|
|
int n2;
|
|
AlarmEntry alarmEntry = (AlarmEntry)this.entries.get(j);
|
|
Object object = column.getValue(alarmEntry.rec);
|
|
for (n2 = j; n2 >= i && comparator.compare(object, column.getValue(((AlarmEntry)this.entries.get((int)(n2 - i))).rec)) <= 0; n2 -= i) {
|
|
if (comparator.compare(object, column.getValue(((AlarmEntry)this.entries.get((int)(n2 - i))).rec)) == 0) {
|
|
BAbsTime bAbsTime = alarmEntry.rec.getTimestamp();
|
|
BAbsTime bAbsTime2 = ((AlarmEntry)this.entries.get((int)(n2 - i))).rec.getTimestamp();
|
|
if (!bAbsTime2.isBefore(bAbsTime)) break;
|
|
this.entries.set(n2, this.entries.get(n2 - i));
|
|
continue;
|
|
}
|
|
this.entries.set(n2, this.entries.get(n2 - i));
|
|
}
|
|
this.entries.set(n2, alarmEntry);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|