1 | |
package net.sf.jabref; |
2 | |
|
3 | |
import java.io.IOException; |
4 | |
import java.io.Writer; |
5 | |
import java.util.ArrayList; |
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
public class CustomEntryType extends BibtexEntryType { |
12 | |
|
13 | |
private String name; |
14 | |
private String[] req, opt; |
15 | 0 | private String[][] reqSets = null; |
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 | |
|
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 | |
|
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 | |
|
98 | |
|
99 | |
|
100 | |
|
101 | |
|
102 | |
|
103 | |
public boolean hasAllRequiredFields(BibtexEntry entry, BibtexDatabase database) { |
104 | |
|
105 | 0 | if (entry.getField(BibtexFields.KEY_FIELD) == null) |
106 | 0 | return false; |
107 | |
|
108 | 0 | boolean[] isSet = new boolean[req.length]; |
109 | |
|
110 | 0 | for (int i=0; i<req.length; i++) |
111 | 0 | isSet[i] = BibtexDatabase.getResolvedField(req[i], entry, database) != null; |
112 | |
|
113 | |
|
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 | |
|
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 | |
|
131 | 0 | if (reqSets[i][j].equalsIgnoreCase(field)) |
132 | 0 | takesPart = true; |
133 | |
|
134 | 0 | else if (BibtexDatabase.getResolvedField(reqSets[i][j], entry, database) != null) |
135 | 0 | oneSet = true; |
136 | |
} |
137 | |
|
138 | 0 | if (takesPart && oneSet) |
139 | 0 | return true; |
140 | |
} |
141 | |
|
142 | 0 | return false; |
143 | |
} |
144 | |
|
145 | |
|
146 | |
|
147 | |
|
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 | |
|
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 | |
|
182 | |
|
183 | |
|
184 | |
|
185 | |
|
186 | |
|
187 | |
|
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 | |
|
202 | |
|
203 | |
|
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 | |
|
215 | 0 | int oPos = rest.indexOf(']', rPos+1); |
216 | 0 | String optFields = rest.substring(rPos+6, oPos); |
217 | |
|
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 | |
} |