package gui;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.ImageIcon;
import javax.swing.table.AbstractTableModel;
import container.ContainerAttribute;
import container.ContainerObject;
import container.ContainerType;
import ctex.Entity;
import ctex.Main;
import database.Db;
public class Model extends AbstractTableModel{
private static final long serialVersionUID = 1L;
private Vector<ContainerObject> tableContent = null;
private Vector<ContainerType> allTypes;
private Vector<ContainerType> usedTypes = new Vector<ContainerType>();
private Vector<Integer> searchResults = new Vector<Integer>();
private boolean showObjects = true;
private Entity myEntity = null;
private Db theDb = null;
private boolean isChanged;
private boolean showPreview;
private String savePath = "";
private int columntype;
public Model (Entity entity) {
this.myEntity = entity;
this.theDb = myEntity.getDb();
this.allTypes = myEntity.getDb().getAllTypes();
this.tableContent = theDb.getAllObject();
this.isChanged = false;
this.showPreview = true;
updateColumns();
}
public void updateColumns() {
columntype = Integer.parseInt(Main.getIniData("columntype"));
switch (columntype) {
case 1:
// Showing default columns declared in app.ini
String columns = Main.getIniData("defaultcolumns");
String[] splitColumns = columns.split(",");
usedTypes.clear();
if (new Integer(Main.getIniData("filecolumn")) == 1) {
usedTypes.add(new ContainerType(Main.fileField, false, false));
}
for (int i = 0; i < splitColumns.length; i++) {
for (int j = 0; j < allTypes.size(); j++) {
if (splitColumns[i].compareToIgnoreCase(allTypes.get(j).getType()) == 0 &&
splitColumns[i].compareToIgnoreCase(Main.fileField) != 0) {
usedTypes.add(allTypes.get(j));
}
}
}
break;
case 2:
// Showing all possible columns, except of entry types
usedTypes.clear();
for (int i = 0; i < allTypes.size(); i++) {
if (!allTypes.get(i).isEntryType()) {
usedTypes.add(allTypes.get(i));
}
}
break;
case 3:
// Showing only columns which contain at least 1 entry
showOnlyUsedTypes();
addUsedTypes();
break;
}
// To refresh the table columns
fireTableStructureChanged();
}
public void setChanged(boolean isChanged) {
this.isChanged = isChanged;
}
public boolean isChanged() {
return isChanged;
}
public void setShowPreview(boolean showPreview) {
this.showPreview = showPreview;
}
public boolean getShowPreview() {
return showPreview;
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
public String getSavePath() {
return savePath;
}
/**
* @procedure: refreshModel
*
* Refresh all objects of the model
*/
public void refreshModel() {
tableContent.clear();
tableContent = theDb.getAllObject();
fireTableDataChanged();
updateColumns();
}
/**
* @procedure: refreshModel
*
* @parameter: obj = edited entry
*
* Do refresh object under Object ID of this model
* when entry is edited
*/
public void refreshModel(ContainerObject obj) {
if(theDb.getObject(obj.getId()) != null) {
obj = theDb.getObject(obj.getId());
int dummy = 0;
while (dummy != tableContent.size() && tableContent.get(dummy).getKey().compareTo(obj.getKey()) != 0){
dummy++;
}
if(dummy == tableContent.size()){
tableContent.add(obj);
} else {
tableContent.remove(dummy);
tableContent.add(dummy, obj);
}
}
fireTableDataChanged();
updateColumns();
}
public void refreshTypes() {
allTypes.clear();
allTypes = theDb.getAllTypes();
updateColumns();
}
public Entity getEntity() {
return myEntity;
}
// Decides if the model resolves links (-> false), or shows the links
// in the table (-> true)
public void setView(boolean showObjects) {
// TODO: might not behave correct always
this.showObjects = showObjects;
}
public Vector<Integer> getSearchResults() {
return searchResults;
}
// SHOWS used Types
public void showOnlyUsedTypes() {
// Hiding all types at first, for restoring defaults
for (int i = 0; i < allTypes.size(); i++) {
allTypes.get(i).setInvisible(true);
}
// Only the type that are used are set visible
for (int i = 0; i < tableContent.size(); i++) {
for (int j = 0; j < tableContent.get(i).getAttributes().size(); j++) {
String typeName = theDb.convTypeIdToTypeName(tableContent.get(i).getAttributes().get(j).getObjectTypeId());
for (int k = 0; k < allTypes.size(); k++) {
if (typeName.compareTo(allTypes.get(k).getType()) == 0) {
allTypes.get(k).setInvisible(false);
}
}
}
}
}
// Toggles if column is shown or not
public void toggleColumn(String type) {
for (int i = 0; i < allTypes.size(); i++) {
if (type == allTypes.get(i).getType()) {
if (allTypes.get(i).isInvisible()) {
allTypes.get(i).setInvisible(false);
} else {
allTypes.get(i).setInvisible(true);
}
}
}
addUsedTypes();
}
public void addUsedTypes() {
usedTypes.clear();
for (int i = 0; i < allTypes.size(); i++) {
if (!allTypes.get(i).isInvisible()) {
usedTypes.add(allTypes.get(i));
}
}
}
public Vector<ContainerType> getAllTypes() {
return allTypes;
}
public Vector<ContainerType> getUsedTypes() {
return usedTypes;
}
public int getColumnCount() {
// + 1 for showing keys, + 1 for showing types
return usedTypes.size() + 2;
}
public int getRowCount() {
return tableContent.size();
}
/* Decides what is shown in the main table of the program */
public Object getValueAt(int row, int col) {
if (col == 0) {
return tableContent.get(row).getKey();
} else if (col == 1) {
return theDb.convTypeIdToTypeName(tableContent.get(row).getTypeId());
} else {
Vector<ContainerAttribute> attributesOfRow = tableContent.get(row).getAttributes();
for (int i = 0; i < attributesOfRow.size(); i++) {
// Current column is the file column
if (Main.fileField.compareTo(usedTypes.get(col - 2).getType()) == 0) {
if (theDb.getAllFiles(tableContent.get(row).getId()) != null && theDb.getAllFiles(tableContent.get(row).getId()).size() > 0) {
return new ImageIcon(getClass().getClassLoader().getResource("images/page.png"));
}
}
if (theDb.convTypeIdToTypeName(attributesOfRow.get(i).getObjectTypeId()).compareTo(usedTypes.get(col - 2).getType()) == 0) {
if (!attributesOfRow.get(i).getLink()) {
// The cell contains a condition
if (attributesOfRow.get(i).getCondition().size() > 0) {
String conditionObjectType = theDb.convTypeIdToTypeName(attributesOfRow.get(i).getObjectTypeId());
String firstConditionLine = "[" + conditionObjectType + "=" + attributesOfRow.get(i).getValue() + "] ";
for (int j = 0; j < tableContent.get(row).getAttributes().get(i).getCondition().size(); j++) {
String conditionAttributeType = theDb.convTypeIdToTypeName(attributesOfRow.get(i).getCondition().get(j).getObjectTypeId());
firstConditionLine = firstConditionLine.concat(conditionAttributeType + " = " + attributesOfRow.get(i).getCondition().get(j).getValue() + ", ");
}
return firstConditionLine;
// The cell contains a normal string or a file
} else {
return attributesOfRow.get(i).getValue();
}
} else {
if (showObjects) {
return ">>" + attributesOfRow.get(i).getValue();
} else {
return resolveLink(attributesOfRow.get(i)).getValue();
}
}
}
}
return "";
}
}
/**
* Trying to resolve Links with the following pattern:
* (1) Only 1 Attribute => Keep the attribute
* (2) More than one Attribute
* (2.1) Look for an Attribute same as the root type
* (2.2) If (2.1) fails: Look for an Attribute with the type "name"
* (2.3) If (2.2) fails: Look for an Attribute with the type "shortname"
*
* @param rootAttribute
* @return resolved Attribute
*/
public ContainerAttribute resolveLink(ContainerAttribute rootAttribute) {
ContainerAttribute root = rootAttribute;
ContainerObject dummy;
while (root.getLink()) {
dummy = theDb.getObject(root.getValue());
if (dummy.getAttributes().size() == 1) {
root = dummy.getAttributes().get(0);
} else {
boolean foundAttribute = false;
for (int i = 0; i < dummy.getAttributes().size(); i++) {
if (root.getObjectTypeId() == dummy.getAttributes().get(i).getObjectTypeId()) {
root = dummy.getAttributes().get(i);
foundAttribute = true;
}
}
if (!foundAttribute) {
// Check if it matches name or shortname
for (int i = 0; i < dummy.getAttributes().size(); i++) {
if (theDb.convTypeIdToTypeName(dummy.getAttributes().get(i).getObjectTypeId()).compareTo("name") == 0) {
root = dummy.getAttributes().get(i);
foundAttribute = true;
} else if (theDb.convTypeIdToTypeName(dummy.getAttributes().get(i).getObjectTypeId()).compareTo("shortname") == 0) {
if (!foundAttribute) {
root = dummy.getAttributes().get(i);
}
}
}
}
}
}
return root;
}
public boolean isCellEditable(int row, int col){
return false;
}
public String getColumnName(int col){
if (col == 0) {
return "key";
} else if (col == 1) {
return "type";
} else {
return usedTypes.get(col - 2).getType();
}
}
public void search(String searchtext) {
searchResults.clear();
Pattern pattern = Pattern.compile(".*" + searchtext + ".*", Pattern.CASE_INSENSITIVE);
for (int i = 0; i < tableContent.size(); i++) {
// Search in "key"
Matcher matcher = pattern.matcher(tableContent.get(i).getKey());
if (matcher.matches()) {
if (!searchResults.contains(i)) {
searchResults.add(i);
}
}
// Search in "Attributes"
for (int j = 0; j < tableContent.get(i).getAttributes().size(); j++) {
matcher = pattern.matcher(tableContent.get(i).getAttributes().get(j).getValue());
if (matcher.matches()) {
if (!searchResults.contains(i)) {
searchResults.add(i);
}
}
}
}
}
// Returns the next smaller index of the searchResults
public int getPreviousIndex(int compareIndex) {
for (int i = searchResults.size() - 1; i >= 0; i--) {
if (searchResults.get(i) < compareIndex) {
return searchResults.get(i);
}
}
return -1;
}
// Returns the next bigger index of the searchResults
public int getNextIndex(int compareIndex) {
for (int i = 0; i < searchResults.size(); i++) {
if (searchResults.get(i) > compareIndex) {
return searchResults.get(i);
}
}
return -1;
}
public Vector<ContainerObject> getTableContent() {
return tableContent;
}
}