/*******************************************************************************
* LogDruid : Generate charts and reports using data gathered in log files
* Copyright (C) 2016 Frederic Valente (frederic.valente@gmail.com)
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
*******************************************************************************/
package logdruid.ui.table;
import javax.swing.JPanel;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextPane;
import javax.swing.ListSelectionModel;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import org.apache.log4j.Logger;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import logdruid.data.Repository;
import logdruid.data.Source;
import logdruid.data.mine.ChartData;
import logdruid.data.mine.FileRecord;
import logdruid.data.record.MetadataRecording;
import logdruid.data.record.Recording;
import logdruid.data.record.RecordingItem;
import logdruid.ui.NoProcessingRegexTableRenderer;
import logdruid.util.DataMiner;
import logdruid.util.PatternCache;
public class MetadataRecordingEditorTable extends JPanel {
private static Logger logger = Logger.getLogger(DataMiner.class.getName());
private boolean DEBUG = false;
static Matcher m;
static ArrayList<RecordingItem> records = null;
private MyTableModel model;
private String[] header = { "Name", "Before", "Inside type", "Inside regex", "After", "Active", "Show", "Value" };
private ArrayList<Object[]> data = new ArrayList<Object[]>();
JTable table = null;
private JTextPane examplePane;
private Repository rep = null;
private Recording recording;
private Source src;
private Document groupDoc;
private Document filesDoc;
public MetadataRecordingEditorTable(JTextPane textPane, Source source) {
super(new GridLayout(1, 0));
model = new MyTableModel(data, header);
table = new JTable(model);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setFont(new Font("SansSerif", Font.PLAIN, 11));
// table.setPreferredScrollableViewportSize(new Dimension(500, 200));
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.setFillsViewportHeight(true);
textPane.getText();
this.examplePane = textPane;
// Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
src=source;
// Set up column sizes.
initColumnSizes(table);
// Fiddle with the Type column's cell editors/renderers.
setUpTypeColumn(table, table.getColumnModel().getColumn(2));
setUpInsideRegexColumn(table, table.getColumnModel().getColumn(1));
setUpInsideRegexColumn(table, table.getColumnModel().getColumn(3));
setUpInsideRegexColumn(table, table.getColumnModel().getColumn(4));
// Add the scroll pane to this panel.
add(scrollPane);
//Add();
// FixValues();
}
public MetadataRecordingEditorTable(Repository repo, Recording re, JTextPane textPane, Source source) {
super(new GridLayout(1, 0));
this.examplePane = textPane;
model = new MyTableModel(data, header);
table = new JTable(model);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
rep = repo;
textPane.getText();
recording = re;
// Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
// Set up column sizes.
initColumnSizes(table);
// Fiddle with the Type column's cell editors/renderers.
setUpTypeColumn(table, table.getColumnModel().getColumn(2));
setUpInsideRegexColumn(table, table.getColumnModel().getColumn(3));
setUpInsideRegexColumn(table, table.getColumnModel().getColumn(1));
setUpInsideRegexColumn(table, table.getColumnModel().getColumn(4));
src=source;
// Add the scroll pane to this panel.
add(scrollPane);
records = ((MetadataRecording) re).getRecordingItem();
// Collections.sort(records);
if (records != null) {
Iterator<RecordingItem> it = records.iterator();
while (it.hasNext()) {
RecordingItem rI = it.next();
String inside="";
inside= DataMiner.getMainRegex( rI.getType(),rI.getInside(), repo.getDateFormat(re.getDateFormatID())) ;
logger.debug("inside: " + inside);
data.add(new Object[] { rI.getName(), rI.getBefore(), rI.getType(), inside,rI.getAfter(), rI.isSelected(),rI.isShow(), "" });
logger.debug("added: " + rI.getName());
}
FixValues();
}
}
public void FixValues() {
String patternString = "";
Matcher matcher;
PatternCache patternCache=new PatternCache();
Iterator<Object[]> it = data.iterator();
Object[] obj;
while (it.hasNext()) {
obj = (Object[]) it.next();
String stBefore = (String) obj[1];
String stType = (String) obj[2];
String stInside = (String) obj[3];
String stAfter = (String) obj[4];
logger.debug("stType: " + stType);
if (stType.equals("date") && rep.getDateFormat(recording.getDateFormatID()).getPattern() != null) {
patternString += stBefore + "(" + rep.getDateFormat(recording.getDateFormatID()).getPattern() + ")" + stAfter;
logger.debug("getTypeString(stType) getPattern -: " + rep.getDateFormat(recording.getDateFormatID()).getPattern());
logger.debug("getTypeString(stType) getDateFormat -: " + rep.getDateFormat(recording.getDateFormatID()).getDateFormat());
} else {
if (stType.equals("manual")){
patternString += stBefore + "(" + stInside + ")" + stAfter;
logger.debug("getTypeString(stType) -: " + stInside);
}else{
patternString += stBefore + "(" + DataMiner.getTypeString(stType) + ")" + stAfter;
logger.debug("getTypeString(stType) -: " + DataMiner.getTypeString(stType));
}
}
}
logger.info( patternCache.getPattern(patternString,recording.isCaseSensitive()));
examplePane.setText("");
Highlighter h = examplePane.getHighlighter();
h.removeAllHighlights();
//Pattern pattern = patternCache.getPattern(txtRegularExp.getText(),re.isCaseSensitive());
if (rep != null && rep.getBaseSourcePath() != null && src!=null && src.getActiveMetadata()!=null) {
ChartData cd = DataMiner.gatherSourceData(rep,false);
Map<String, ArrayList<FileRecord>> hm = cd.getGroupFilesMap(src);
logger.debug("source: "+src.getSourceName()+", map: "+hm+", map size: "+ hm.size());
filesDoc = examplePane.getDocument();
Iterator it2 = hm.entrySet().iterator();
int nbFiles = 0;
long size=0;
logger.debug("---patternString: "+patternString);
int currIndex = 0;
while (it2.hasNext()) {
try {
// int currGroupIndex = groupDoc.getLength();
int currFilesIndex = filesDoc.getLength();
final Map.Entry sourcePairs = (Map.Entry) it2.next();
final String groupString = (String) sourcePairs.getKey();
logger.debug("groupString: "+groupString);
ArrayList files = (ArrayList) sourcePairs.getValue();
/* nbFiles += files.size();
Iterator<FileRecord> iterator =files.iterator();
while (iterator.hasNext())
{
FileRecord fr = iterator.next();
size=size+((File)fr.getFile()).length();
logger.debug(fr.getFile().getName()+" "+((File)fr.getFile()).length());
}*/
// groupDoc.insertString(groupDoc.getLength(), groupString + "(" + files.size() + " file"+(nbFiles>1?"s":"")+")\n", null);
filesDoc.insertString(filesDoc.getLength(), groupString + "\n", null);
currIndex+=filesDoc.getLength()+1;
SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setBold(sas, true);
examplePane.getStyledDocument().setCharacterAttributes(currFilesIndex , groupString.length()-1, sas, false);
// textPane_1.getStyledDocument().setCharacterAttributes(currGroupIndex , groupString.length()-1, sas, false);
// h.addHighlight(currIndex , currIndex + groupString.length()-1, DefaultHighlighter.DefaultPainter);
if (files!=null){
Iterator vecIt = files.iterator();
while (vecIt.hasNext()) {
String filePath=new File(rep.getBaseSourcePath()).toURI().relativize(new File(((FileRecord)vecIt.next()).getCompletePath()).toURI()).getPath();
filesDoc.insertString(filesDoc.getLength(),"- "+ filePath + "\n", null);
/* logger.debug(filePath);
matcher = patternCache.getPattern(patternString,recording.isCaseSensitive()).matcher(filePath);
if (matcher.find()){
for (int i2 = 1; i2 <= matcher.groupCount(); i2++) {
logger.debug("matched");
h.addHighlight(currIndex+matcher.start(i2)+1, +currIndex+matcher.end(i2)+1, new DefaultHighlighter.DefaultHighlightPainter(Color.ORANGE));
}
}
currIndex += filePath.length()+3 ;
*/
}}
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
examplePane.setCaretPosition(0);
//textPane_1.setCaretPosition(0);
//nbFilesValueLabel.setText("" + nbFiles);
//filesSize.setText(""+size/1024000+"MB");
} else {
try {
logger.debug("theLine: " + examplePane.getText());
logger.debug("patternString: " + patternString);
Highlighter h2 = examplePane.getHighlighter();
h2.removeAllHighlights();
int currIndex = 0;
String[] lines = examplePane.getText().split(System.getProperty("line.separator"));
if (lines.length>=1){
for (int i=0; i<lines.length ; i++){
matcher = patternCache.getPattern(patternString,recording.isCaseSensitive()).matcher(lines[i]);
if (matcher.find()) {
// int currIndex = 0;
// doc.insertString(doc.getLength(),line+"\n", null);
for (int i2 = 1; i2 <= matcher.groupCount(); i2++) {
model.setValueAt(matcher.group(i2), i2 - 1, 7);
h2.addHighlight(currIndex+matcher.start(i2), +currIndex+matcher.end(i2), new DefaultHighlighter.DefaultHighlightPainter(Color.ORANGE));
}
}
logger.debug("currIndex: " + currIndex + "matcher.end(i2): " + lines[i].length()+",l: "+lines[i]);
currIndex += lines[i].length()+1 ;
}
}
} catch (Exception e1) {
e1.printStackTrace();
// System.exit(1);
}
}
}
private void initColumnSizes(JTable theTable) {
TableColumn column = null;
Component comp = null;
int headerWidth = 0;
int cellWidth = 0;
TableCellRenderer headerRenderer = theTable.getTableHeader().getDefaultRenderer();
for (int i = 0; i < 8; i++) {
column = theTable.getColumnModel().getColumn(i);
comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0);
headerWidth = comp.getPreferredSize().width;
cellWidth = comp.getPreferredSize().width;
if (DEBUG) {
logger.debug("Initializing width of column " + i + ". " + "headerWidth = " + headerWidth + "; cellWidth = " + cellWidth);
}
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
}
}
public void setUpInsideRegexColumn(JTable theTable, TableColumn typeColumn) {
DefaultTableCellRenderer renderer = new NoProcessingRegexTableRenderer();
// renderer.setBackground(Color.GRAY);
typeColumn.setCellRenderer(renderer);
}
public void setUpTypeColumn(JTable theTable, TableColumn typeColumn) {
// Set up the editor for the Type cells.
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.addItem("date");
comboBox.addItem("double");
comboBox.addItem("long");
comboBox.addItem("manual");
comboBox.addItem("percent");
comboBox.addItem("string");
comboBox.addItem("stringminimum");
comboBox.addItem("word");
typeColumn.setCellEditor(new DefaultCellEditor(comboBox));
DefaultTableCellRenderer renderer = new NoProcessingRegexTableRenderer();
renderer.setToolTipText("Click for combo box");
typeColumn.setCellRenderer(renderer);
comboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JComboBox combo = (JComboBox) e.getSource();
Object selected = combo.getSelectedItem();
if (table.getSelectedRow()!=-1){
model.setValueAt(DataMiner.getMainRegex( (String) selected.toString(),(String) model.getValueAt(table.getSelectedRow(), 3), rep.getDateFormat(recording.getDateFormatID())), table.getSelectedRow(), 3);
model.fireTableCellUpdated(table.getSelectedRow(), 3);
}
}
}
);
}
class MyTableModel extends AbstractTableModel {
private String[] header;
private ArrayList<Object[]> data;
public MyTableModel(ArrayList<Object[]> data, String[] header) {
this.header = header;
this.data = data;
}
@Override
public int getColumnCount() {
if (header == null) {
return 0;
} else
return header.length;
}
@Override
public String getColumnName(int column) {
return header[column];
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public Object getValueAt(int row, int column) {
return data.get(row)[column];
}
@Override
public void setValueAt(Object value, int row, int column) {
data.get(row)[column] = value;
fireTableCellUpdated(row, column);
}
public Class<? extends Object> getColumnClass(int c) {
if (getValueAt(0, c)!=null){
return getValueAt(0, c).getClass();
} else return String.class;
}
public boolean isCellEditable(int row, int col) {
// Note that the data/cell address is constant,
// no matt&er where the cell appears onscreen.
if (col > 6) {
return false;
} else {if (col==3 && !data.get(row)[2].equals("manual")){
return false;
} else{
return true;
}
}
}
}
public ArrayList<RecordingItem> getRecordingItems() {
ArrayList<RecordingItem> toReturn = new ArrayList<RecordingItem>();
for (int i = 0; i < data.size(); i++) { // model.getRowCount()
toReturn.add(new RecordingItem((String) model.getValueAt(i, 0), (String) model.getValueAt(i, 1),
(String) model.getValueAt(i, 2), (String) model.getValueAt(i,3),
(String) model.getValueAt(i, 4),(Boolean) model.getValueAt(i, 5),
(Boolean) model.getValueAt(i, 6), (String) model.getValueAt(i, 7)));
}
return toReturn;
}
public void Add() {
data.add(new Object[] { "default", ".*", "long",DataMiner.getTypeString("long"), "", Boolean.TRUE,Boolean.TRUE, "" });
table.repaint();
}
public void Insert() {
data.add(((table.getSelectedRow() != -1) ? table.convertRowIndexToModel(table.getSelectedRow()) : -1), new Object[] { "default", ".*", "long",DataMiner.getTypeString("long"), "", Boolean.TRUE,Boolean.TRUE, "" });
table.repaint();
}
public void Remove() {
data.remove(((table.getSelectedRow() != -1) ? table.convertRowIndexToModel(table.getSelectedRow()) : -1));
table.repaint();
}
}