Coverage Report - net.sf.jabref.CustomEntryType
 
Classes in this File Line Coverage Branch Coverage Complexity
CustomEntryType
0%
0/110
0%
0/70
3.733
 
 1  
 package net.sf.jabref;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.io.Writer;
 5  
 import java.util.ArrayList;
 6  
 
 7  
 /**
 8  
  * This class is used to represent customized entry types.
 9  
  *
 10  
  */
 11  
 public class CustomEntryType extends BibtexEntryType {
 12  
 
 13  
     private String name;
 14  
     private String[] req, opt;
 15  0
     private String[][] reqSets = null; // Sets of either-or required fields, if any
 16  
 
 17  0
     public CustomEntryType(String name_, String[] req_, String[] opt_) {
 18  0
         name = name_;
 19  0
         parseRequiredFields(req_);
 20  0
         opt = opt_;
 21  0
     }
 22  
 
 23  0
     public CustomEntryType(String name_, String reqStr, String optStr) {
 24  0
         name = name_;
 25  0
         if (reqStr.length() == 0)
 26  0
             req = new String[0];
 27  
         else {
 28  0
             parseRequiredFields(reqStr);
 29  
 
 30  
         }
 31  0
         if (optStr.length() == 0)
 32  0
             opt = new String[0];
 33  
         else
 34  0
             opt = optStr.split(";");
 35  0
     }
 36  
 
 37  
     protected void parseRequiredFields(String reqStr) {
 38  0
         String[] parts = reqStr.split(";");
 39  0
         parseRequiredFields(parts);
 40  0
     }
 41  
 
 42  
     protected void parseRequiredFields(String[] parts) {
 43  0
         ArrayList<String> fields = new ArrayList<String>();
 44  0
         ArrayList<String[]> sets = new ArrayList<String[]>();
 45  0
         for (int i = 0; i < parts.length; i++) {
 46  0
             String[] subParts = parts[i].split("/");
 47  0
             for (int j = 0; j < subParts.length; j++) {
 48  0
                 fields.add(subParts[j]);
 49  
             }
 50  
             // Check if we have either/or fields:
 51  0
             if (subParts.length > 1) {
 52  0
                 sets.add(subParts);
 53  
             }
 54  
         }
 55  0
         req = fields.toArray(new String[fields.size()]);
 56  0
         if (sets.size() > 0) {
 57  0
             reqSets = sets.toArray(new String[sets.size()][]);
 58  
         }
 59  0
     }
 60  
 
 61  
     public String getName() {
 62  0
         return name;
 63  
     }
 64  
 
 65  
     public String[] getOptionalFields() {
 66  0
         return opt;
 67  
     }
 68  
     public String[] getRequiredFields() {
 69  0
         return req;
 70  
     }
 71  
 
 72  
     public String[] getRequiredFieldsForCustomization() {
 73  0
         return getRequiredFieldsString().split(";");
 74  
     }
 75  
 
 76  
     //    public boolean isTemporary
 77  
 
 78  
     public String describeRequiredFields() {
 79  0
         StringBuffer sb = new StringBuffer();
 80  0
         for (int i=0; i<req.length; i++) {
 81  0
             sb.append(req[i]);
 82  0
             sb.append(((i<=req.length-1)&&(req.length>1))?", ":"");
 83  
         }
 84  0
         return sb.toString();
 85  
     }
 86  
 
 87  
     public String describeOptionalFields() {
 88  0
         StringBuffer sb = new StringBuffer();
 89  0
         for (int i=0; i<opt.length; i++) {
 90  0
             sb.append(opt[i]);
 91  0
             sb.append(((i<=opt.length-1)&&(opt.length>1))?", ":"");
 92  
         }
 93  0
         return sb.toString();
 94  
     }
 95  
 
 96  
     /**
 97  
      * Check whether this entry's required fields are set, taking crossreferenced entries and
 98  
      * either-or fields into account:
 99  
      * @param entry The entry to check.
 100  
      * @param database The entry's database.
 101  
      * @return True if required fields are set, false otherwise.
 102  
      */
 103  
     public boolean hasAllRequiredFields(BibtexEntry entry, BibtexDatabase database) {
 104  
         // First check if the bibtex key is set:
 105  0
         if (entry.getField(BibtexFields.KEY_FIELD) == null)
 106  0
                 return false;
 107  
         // Then check other fields:
 108  0
         boolean[] isSet = new boolean[req.length];
 109  
         // First check for all fields, whether they are set here or in a crossref'd entry:
 110  0
             for (int i=0; i<req.length; i++)
 111  0
             isSet[i] = BibtexDatabase.getResolvedField(req[i], entry, database) != null;
 112  
         // Then go through all fields. If a field is not set, see if it is part of an either-or
 113  
         // set where another field is set. If not, return false:
 114  0
             for (int i=0; i<req.length; i++) {
 115  0
             if (!isSet[i]) {
 116  0
                 if (!isCoupledFieldSet(req[i], entry, database))
 117  0
                     return false;
 118  
             }
 119  
         }
 120  
         // Passed all fields, so return true:
 121  0
         return true;
 122  
     }
 123  
 
 124  
     protected boolean isCoupledFieldSet(String field, BibtexEntry entry, BibtexDatabase database) {
 125  0
         if (reqSets == null)
 126  0
             return false;
 127  0
         for (int i=0; i<reqSets.length; i++) {
 128  0
             boolean takesPart = false, oneSet = false;
 129  0
             for (int j=0; j<reqSets[i].length; j++) {
 130  
                 // If this is the field we're looking for, note that the field is part of the set:
 131  0
                 if (reqSets[i][j].equalsIgnoreCase(field))
 132  0
                     takesPart = true;
 133  
                 // If it is a different field, check if it is set:
 134  0
                 else if (BibtexDatabase.getResolvedField(reqSets[i][j], entry, database) != null)
 135  0
                     oneSet = true;
 136  
             }
 137  
             // Ths the field is part of the set, and at least one other field is set, return true:
 138  0
             if (takesPart && oneSet)
 139  0
                 return true;
 140  
         }
 141  
         // No hits, so return false:
 142  0
         return false;
 143  
     }
 144  
 
 145  
     /**
 146  
      * Get a String describing the required field set for this entry type.
 147  
      * @return Description of required field set for storage in preferences or bib file.
 148  
      */
 149  
     public String getRequiredFieldsString() {
 150  0
         StringBuilder sb = new StringBuilder();
 151  0
         int reqSetsPiv = 0;
 152  0
         for (int i=0; i<req.length; i++) {
 153  0
             if ((reqSets == null) || (reqSetsPiv == reqSets.length)) {
 154  0
                 sb.append(req[i]);
 155  
             }
 156  0
             else if (req[i].equals(reqSets[reqSetsPiv][0])) {
 157  0
                 for (int j = 0; j < reqSets[reqSetsPiv].length; j++) {
 158  0
                     sb.append(reqSets[reqSetsPiv][j]);
 159  0
                     if (j < reqSets[reqSetsPiv].length-1)
 160  0
                         sb.append("/");
 161  
                 }
 162  
                 // Skip next n-1 fields:
 163  0
                 i += reqSets[reqSetsPiv].length-1;
 164  0
                 reqSetsPiv++;
 165  
             }
 166  0
             else sb.append(req[i]);
 167  0
             if (i < req.length-1)
 168  0
                 sb.append(";");
 169  
 
 170  
         }
 171  0
         return sb.toString();
 172  
     }
 173  
 
 174  
 
 175  
     public void save(Writer out) throws IOException {
 176  0
         out.write("@comment{");
 177  0
         out.write(GUIGlobals.ENTRYTYPE_FLAG);
 178  0
         out.write(getName());
 179  0
         out.write(": req[");
 180  0
     out.write(getRequiredFieldsString());
 181  
         /*StringBuffer sb = new StringBuffer();
 182  
         for (int i=0; i<req.length; i++) {
 183  
             sb.append(req[i]);
 184  
             if (i<req.length-1)
 185  
                 sb.append(";");
 186  
         }
 187  
         out.write(sb.toString());*/
 188  0
         out.write("] opt[");
 189  0
         StringBuilder sb = new StringBuilder();
 190  0
         for (int i=0; i<opt.length; i++) {
 191  0
             sb.append(opt[i]);
 192  0
             if (i<opt.length-1)
 193  0
                 sb.append(";");
 194  
         }
 195  0
         out.write(sb.toString());
 196  0
         out.write("]}"+Globals.NEWLINE);
 197  0
     }
 198  
 
 199  
     public static CustomEntryType parseEntryType(String comment) { 
 200  
         try {
 201  
             //if ((comment.length() < 9+GUIGlobals.ENTRYTYPE_FLAG.length())
 202  
             //        || comment
 203  
             //System.out.println(">"+comment+"<");
 204  
             String rest;
 205  0
             rest = comment.substring(GUIGlobals.ENTRYTYPE_FLAG.length());
 206  0
             int nPos = rest.indexOf(':');
 207  0
             String name = rest.substring(0, nPos);
 208  0
             rest = rest.substring(nPos+2);
 209  
 
 210  0
             int rPos = rest.indexOf(']');
 211  0
             if (rPos < 4)
 212  0
                 throw new IndexOutOfBoundsException();
 213  0
             String reqFields = rest.substring(4, rPos);
 214  
             //System.out.println(name+"\nr '"+reqFields+"'");
 215  0
             int oPos = rest.indexOf(']', rPos+1);
 216  0
             String optFields = rest.substring(rPos+6, oPos);
 217  
             //System.out.println("o '"+optFields+"'");
 218  0
             return new CustomEntryType(name, reqFields, optFields);
 219  0
         } catch (IndexOutOfBoundsException ex) {
 220  0
             Globals.logger("Ill-formed entrytype comment in BibTeX file.");
 221  0
             return null;
 222  
         }
 223  
 
 224  
     }
 225  
 }