1 | /* This file is part of the project "Hilbert II" - http://www.qedeq.org |
2 | * |
3 | * Copyright 2000-2014, Michael Meyling <mime@qedeq.org>. |
4 | * |
5 | * "Hilbert II" is free software; you can redistribute |
6 | * it and/or modify it under the terms of the GNU General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | */ |
15 | |
16 | package org.qedeq.kernel.bo.service.internal; |
17 | |
18 | import java.util.HashMap; |
19 | import java.util.Map; |
20 | |
21 | import org.qedeq.base.utility.StringUtility; |
22 | import org.qedeq.kernel.bo.common.Element2Latex; |
23 | import org.qedeq.kernel.bo.logic.common.ExistenceChecker; |
24 | import org.qedeq.kernel.bo.module.KernelQedeqBo; |
25 | import org.qedeq.kernel.bo.module.ModuleLabels; |
26 | import org.qedeq.kernel.se.base.list.Element; |
27 | import org.qedeq.kernel.se.base.list.ElementList; |
28 | import org.qedeq.kernel.se.base.module.FunctionDefinition; |
29 | import org.qedeq.kernel.se.base.module.PredicateDefinition; |
30 | import org.qedeq.kernel.se.dto.module.FunctionDefinitionVo; |
31 | import org.qedeq.kernel.se.dto.module.PredicateDefinitionVo; |
32 | |
33 | |
34 | /** |
35 | * Transfer a QEDEQ formulas into LaTeX text. |
36 | * |
37 | * @author Michael Meyling |
38 | */ |
39 | public final class Element2LatexImpl implements Element2Latex { |
40 | |
41 | /** Knows about labels, definitions and external QEDEQ module references. */ |
42 | private ModuleLabels labels; |
43 | |
44 | /** Maps operator strings to {@link ElementList} to LaTeX mappers. */ |
45 | private final Map elementList2ListType = new HashMap(); |
46 | |
47 | /** For mapping an unknown operator. */ |
48 | private final ListType unknown = new Unknown(); |
49 | |
50 | /** Maps predicate identifiers to {@link PredicateDefinition}s. Contains default definitions |
51 | * as a fallback.*/ |
52 | private final Map backupPredicateDefinitions = new HashMap(); |
53 | |
54 | /** Maps function identifiers to {@link FunctionDefinition}s. Contains default definitions. */ |
55 | private final Map backupFunctionDefinitions = new HashMap(); |
56 | |
57 | /** |
58 | * Constructor. |
59 | * |
60 | * @param labels Knows about labels, definitions and external QEDEQ module references. |
61 | */ |
62 | public Element2LatexImpl(final ModuleLabels labels) { |
63 | this.labels = labels; |
64 | |
65 | this.elementList2ListType.put("PREDVAR", new Predvar()); |
66 | this.elementList2ListType.put("FUNVAR", new Funvar()); |
67 | this.elementList2ListType.put("PREDCON", new Predcon()); |
68 | this.elementList2ListType.put("FUNCON", new Funcon()); |
69 | this.elementList2ListType.put("VAR", new Var()); |
70 | |
71 | this.elementList2ListType.put("AND", new BinaryLogical("\\land")); |
72 | this.elementList2ListType.put("OR", new BinaryLogical("\\lor")); |
73 | this.elementList2ListType.put("IMPL", new BinaryLogical("\\rightarrow")); |
74 | this.elementList2ListType.put("EQUI", new BinaryLogical("\\leftrightarrow")); |
75 | |
76 | this.elementList2ListType.put("FORALL", new Quantifier("\\forall")); |
77 | this.elementList2ListType.put("EXISTS", new Quantifier("\\exists")); |
78 | this.elementList2ListType.put("EXISTSU", new Quantifier("\\exists!")); |
79 | |
80 | this.elementList2ListType.put("NOT", new Not()); |
81 | this.elementList2ListType.put("CLASS", new Class()); |
82 | this.elementList2ListType.put("CLASSLIST", new Classlist()); |
83 | |
84 | // // TODO mime 20080126: wrong spelled and not used any longer (?) |
85 | // this.elementList2ListType.put("QUANTOR_INTERSECTION", new QuantorIntersection()); |
86 | // this.elementList2ListType.put("QUANTOR_UNION", new QuantorUnion()); |
87 | |
88 | fillBackup(); |
89 | |
90 | } |
91 | |
92 | /** |
93 | * Fill backup predicate list (if required modules could not be loaded, or the predicate is |
94 | * not yet defined. |
95 | */ |
96 | private void fillBackup() { |
97 | // logical identity operator |
98 | addBackupPredicate(ExistenceChecker.NAME_EQUAL, "2", "#1 \\ = \\ #2"); |
99 | |
100 | // negation of the logical identity operator |
101 | addBackupPredicate("notEqual", "2", "#1 \\ \\neq \\ #2"); |
102 | |
103 | addBackupPredicate("in", "2", "#1 \\in #2"); |
104 | addBackupPredicate("notIn", "2", "#1 \\notin #2"); |
105 | addBackupPredicate("isSet", "1", "\\mathfrak{M}(#1)"); |
106 | addBackupPredicate("subclass", "2", "#1 \\ \\subseteq \\ #2"); |
107 | addBackupPredicate("isOrderedPair", "1", "\\mbox{isOrderedPair}(#1)"); |
108 | addBackupPredicate("isRelation", "1", "\\mathfrak{Rel}(#1)"); |
109 | addBackupPredicate("isFunction", "1", "\\mathfrak{Funct}(#1)"); |
110 | |
111 | addBackupFunction("RussellClass", "0", "\\mathfrak{Ru}"); |
112 | addBackupFunction("universalClass", "0", "\\mathfrak{V}"); |
113 | addBackupFunction("emptySet", "0", "\\emptyset"); |
114 | addBackupFunction("union", "2", "(#1 \\cup #2)"); |
115 | addBackupFunction("intersection", "2", "(#1 \\cap #2)"); |
116 | addBackupFunction("complement", "1", "\\overline{#1}"); |
117 | addBackupFunction("classList", "1", "\\{ #1 \\}"); |
118 | addBackupFunction("classList", "2", "\\{ #1, #2 \\}"); |
119 | addBackupFunction("setProduct", "1", "\\bigcap \\ #1"); |
120 | addBackupFunction("setSum", "1", "\\bigcup \\ #1"); |
121 | addBackupFunction("power", "1", "\\mathfrak{P}(#1)"); |
122 | addBackupFunction("orderedPair", "2", "\\langle #1, #2 \\rangle"); |
123 | addBackupFunction("cartesianProduct", "2", "( #1 \\times #2)"); |
124 | addBackupFunction("domain", "1", "\\mathfrak{Dom}(#1)"); |
125 | addBackupFunction("range", "1", "\\mathfrak{Rng}(#1)"); |
126 | addBackupFunction("successor", "1", "#1'"); |
127 | |
128 | } |
129 | |
130 | /** |
131 | * Add predicate to backup list. |
132 | * |
133 | * @param name Predicate name. |
134 | * @param argNumber Number of arguments. |
135 | * @param latexPattern This is the latex presentation. Variables are marked by "#1", "#2" |
136 | * and so on. |
137 | */ |
138 | private void addBackupPredicate(final String name, final String argNumber, |
139 | final String latexPattern) { |
140 | final String key = name + "_" + argNumber; |
141 | final PredicateDefinitionVo predicate = new PredicateDefinitionVo(); |
142 | predicate.setArgumentNumber(argNumber); |
143 | predicate.setName(name); |
144 | predicate.setLatexPattern(latexPattern); |
145 | backupPredicateDefinitions.put(key, predicate); |
146 | } |
147 | |
148 | /** |
149 | * Add function to backup list. |
150 | * |
151 | * @param name Function name. |
152 | * @param argNumber Number of arguments. |
153 | * @param latexPattern This is the LaTex presentation. Variables are marked by "#1", "#2" |
154 | * and so on. |
155 | */ |
156 | private void addBackupFunction(final String name, final String argNumber, |
157 | final String latexPattern) { |
158 | final String key = name + "_" + argNumber; |
159 | final FunctionDefinitionVo function = new FunctionDefinitionVo(); |
160 | function.setArgumentNumber(argNumber); |
161 | function.setName(name); |
162 | function.setLatexPattern(latexPattern); |
163 | backupFunctionDefinitions.put(key, function); |
164 | } |
165 | |
166 | public String getLatex(final Element element) { |
167 | return getLatex(element, true); |
168 | } |
169 | |
170 | /** |
171 | * Get LaTeX element presentation. |
172 | * |
173 | * @param element Print this element. |
174 | * @param first First level? |
175 | * @return LaTeX form of element. |
176 | */ |
177 | String getLatex(final Element element, final boolean first) { |
178 | if (element == null) { |
179 | return ""; |
180 | } |
181 | if (element.isAtom()) { |
182 | return element.getAtom().getString(); |
183 | } |
184 | final ElementList list = element.getList(); |
185 | |
186 | ListType converter = (ListType) elementList2ListType.get(list.getOperator()); |
187 | |
188 | if (converter == null) { |
189 | converter = this.unknown; |
190 | } |
191 | return converter.getLatex(list, first); |
192 | |
193 | } |
194 | |
195 | /** |
196 | * Get default definition mapping of predicate definitions. Our last hope. |
197 | * |
198 | * @return Mapping of predicate definitions. |
199 | */ |
200 | Map getBackupPredicateDefinitions() { |
201 | return this.backupPredicateDefinitions; |
202 | } |
203 | |
204 | /** |
205 | * Get default definition mapping of function definitions. Our last hope. |
206 | * |
207 | * @return Mapping of predicate definitions. |
208 | */ |
209 | Map getBackupFunctionDefinitions() { |
210 | return this.backupFunctionDefinitions; |
211 | } |
212 | |
213 | /** |
214 | * Describes the interface for an {@link ElementList} to LaTeX converter. |
215 | */ |
216 | interface ListType { |
217 | |
218 | /** |
219 | * Transform list into LaTeX. |
220 | * |
221 | * @param list This list shall be transformed. |
222 | * @param first Is the resulting LaTeX formula or term at top level? If so we possibly |
223 | * can omit some brackets. |
224 | * @return LaTeX formula or term. |
225 | */ |
226 | public String getLatex(ElementList list, boolean first); |
227 | } |
228 | |
229 | /** |
230 | * Transformer for a predicate variable. |
231 | */ |
232 | class Predvar implements ListType { |
233 | public String getLatex(final ElementList list, final boolean first) { |
234 | final StringBuffer buffer = new StringBuffer(); |
235 | final String identifier = list.getElement(0).getAtom().getString(); |
236 | buffer.append(identifier); |
237 | if (list.size() > 1) { |
238 | buffer.append("("); |
239 | for (int i = 1; i < list.size(); i++) { |
240 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
241 | if (i + 1 < list.size()) { |
242 | buffer.append(", "); |
243 | } |
244 | } |
245 | buffer.append(")"); |
246 | } |
247 | return buffer.toString(); |
248 | } |
249 | } |
250 | |
251 | /** |
252 | * Transformer for a function variable. |
253 | */ |
254 | class Funvar implements ListType { |
255 | public String getLatex(final ElementList list, final boolean first) { |
256 | final StringBuffer buffer = new StringBuffer(); |
257 | final String identifier = list.getElement(0).getAtom().getString(); |
258 | buffer.append(identifier); |
259 | if (list.size() > 1) { |
260 | buffer.append("("); |
261 | for (int i = 1; i < list.size(); i++) { |
262 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
263 | if (i + 1 < list.size()) { |
264 | buffer.append(", "); |
265 | } |
266 | } |
267 | buffer.append(")"); |
268 | } |
269 | return buffer.toString(); |
270 | } |
271 | } |
272 | |
273 | /** |
274 | * Transformer for a predicate constant. |
275 | */ |
276 | class Predcon implements ListType { |
277 | public String getLatex(final ElementList list, final boolean first) { |
278 | final StringBuffer buffer = new StringBuffer(); |
279 | final String name = list.getElement(0).getAtom().getString(); |
280 | final int arguments = list.size() - 1; |
281 | String identifier = name + "_" + (arguments); |
282 | // LATER 20060922 m31: is only working for definition name + argument number |
283 | // if argument length is dynamic this dosen't work |
284 | PredicateDefinition definition = (PredicateDefinition) |
285 | Element2LatexImpl.this.labels.getPredicateDefinitions().get(identifier); |
286 | if (definition == null) { |
287 | // try external modules |
288 | try { |
289 | final int external = name.indexOf("."); |
290 | if (external >= 0) { |
291 | final String shortName = name.substring(external + 1); |
292 | identifier = shortName + "_" + (arguments); |
293 | if (Element2LatexImpl.this.labels.getReferences() != null |
294 | && Element2LatexImpl.this.labels.getReferences().size() > 0) { |
295 | final String label = name.substring(0, external); |
296 | final KernelQedeqBo newProp = (KernelQedeqBo) |
297 | Element2LatexImpl.this.labels.getReferences().getQedeqBo(label); |
298 | if (newProp != null) { |
299 | if (newProp.getExistenceChecker().predicateExists(shortName, |
300 | arguments)) { |
301 | definition = newProp.getLabels() |
302 | .getPredicate(shortName, arguments); |
303 | } |
304 | } |
305 | } |
306 | } |
307 | } catch (Exception e) { |
308 | // try failed... |
309 | } |
310 | } |
311 | // we try our backup |
312 | if (definition == null) { |
313 | definition = (PredicateDefinition) Element2LatexImpl.this.getBackupPredicateDefinitions() |
314 | .get(identifier); |
315 | } |
316 | if (definition != null) { |
317 | final StringBuffer define = new StringBuffer(definition.getLatexPattern()); |
318 | for (int i = list.size() - 1; i >= 1; i--) { |
319 | StringUtility.replace(define, "#" + i, Element2LatexImpl.this.getLatex( |
320 | list.getElement(i), false)); |
321 | } |
322 | buffer.append(define); |
323 | } else { |
324 | buffer.append(identifier); |
325 | buffer.append("("); |
326 | for (int i = 1; i < list.size(); i++) { |
327 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
328 | if (i + 1 < list.size()) { |
329 | buffer.append(", "); |
330 | } |
331 | } |
332 | buffer.append(")"); |
333 | } |
334 | return buffer.toString(); |
335 | } |
336 | } |
337 | |
338 | /** |
339 | * Transformer for a function constant. |
340 | */ |
341 | class Funcon implements ListType { |
342 | |
343 | public String getLatex(final ElementList list, final boolean first) { |
344 | final StringBuffer buffer = new StringBuffer(); |
345 | final String name = list.getElement(0).getAtom().getString(); |
346 | final int arguments = list.size() - 1; |
347 | String identifier = name + "_" + (arguments); |
348 | // LATER 20060922 m31: is only working for definition name + argument number |
349 | // if argument length is dynamic this dosen't work |
350 | FunctionDefinition definition = (FunctionDefinition) |
351 | Element2LatexImpl.this.labels.getFunctionDefinitions().get(identifier); |
352 | if (definition == null) { |
353 | // try external modules |
354 | try { |
355 | final int external = name.indexOf("."); |
356 | if (external >= 0) { |
357 | final String shortName = name.substring(external + 1); |
358 | identifier = shortName + "_" + (arguments); |
359 | if (Element2LatexImpl.this.labels.getReferences() != null |
360 | && Element2LatexImpl.this.labels.getReferences().size() > 0) { |
361 | final String label = name.substring(0, external); |
362 | final KernelQedeqBo newProp = (KernelQedeqBo) |
363 | Element2LatexImpl.this.labels.getReferences().getQedeqBo(label); |
364 | if (newProp != null) { |
365 | if (newProp.getExistenceChecker().functionExists(shortName, |
366 | arguments)) { |
367 | definition = newProp.getLabels() |
368 | .getFunction(shortName, arguments); |
369 | } |
370 | } |
371 | } |
372 | } |
373 | } catch (Exception e) { |
374 | // try failed... |
375 | } |
376 | } |
377 | // we try our backup |
378 | if (definition == null) { |
379 | definition = (FunctionDefinition) Element2LatexImpl.this.getBackupFunctionDefinitions() |
380 | .get(identifier); |
381 | } |
382 | if (definition != null) { |
383 | final StringBuffer define = new StringBuffer(definition.getLatexPattern()); |
384 | for (int i = list.size() - 1; i >= 1; i--) { |
385 | StringUtility.replace(define, "#" + i, Element2LatexImpl.this. |
386 | getLatex(list.getElement(i), false)); |
387 | } |
388 | buffer.append(define); |
389 | } else { |
390 | buffer.append(identifier); |
391 | buffer.append("("); |
392 | for (int i = 1; i < list.size(); i++) { |
393 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
394 | if (i + 1 < list.size()) { |
395 | buffer.append(", "); |
396 | } |
397 | } |
398 | buffer.append(")"); |
399 | } |
400 | return buffer.toString(); |
401 | } |
402 | } |
403 | |
404 | /** |
405 | * Transformer for a subject variable. |
406 | */ |
407 | static class Var implements ListType { |
408 | public String getLatex(final ElementList list, final boolean first) { |
409 | final String text = list.getElement(0).getAtom().getString(); |
410 | // interpret variable identifier as number |
411 | try { |
412 | final int index = Integer.parseInt(text); |
413 | final String newText = "" + index; |
414 | if (!text.equals(newText) || newText.startsWith("-")) { |
415 | throw new NumberFormatException("This is no allowed number: " + text); |
416 | } |
417 | switch (index) { |
418 | case 1: |
419 | return "x"; |
420 | case 2: |
421 | return "y"; |
422 | case 3: |
423 | return "z"; |
424 | case 4: |
425 | return "u"; |
426 | case 5: |
427 | return "v"; |
428 | case 6: |
429 | return "w"; |
430 | default: |
431 | return "x_" + (index - 6); |
432 | } |
433 | } catch (NumberFormatException e) { |
434 | // variable identifier is no number, just take it as it is |
435 | return text; |
436 | } |
437 | } |
438 | } |
439 | |
440 | /** |
441 | * Transformer for a binary logical operator written in infix notation. |
442 | */ |
443 | class BinaryLogical implements ListType { |
444 | |
445 | /** LaTeX for operator. */ |
446 | private final String latex; |
447 | |
448 | /** |
449 | * Constructor. |
450 | * |
451 | * @param latex LaTeX for operator. |
452 | */ |
453 | BinaryLogical(final String latex) { |
454 | this.latex = latex; |
455 | } |
456 | |
457 | public String getLatex(final ElementList list, final boolean first) { |
458 | final StringBuffer buffer = new StringBuffer(); |
459 | final String infix = "\\ " + latex + "\\ "; |
460 | if (!first) { |
461 | buffer.append("("); |
462 | } |
463 | // we also handle it if it has not exactly two operands |
464 | for (int i = 0; i < list.size(); i++) { |
465 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
466 | if (i + 1 < list.size()) { |
467 | buffer.append(infix); |
468 | } |
469 | } |
470 | if (!first) { |
471 | buffer.append(")"); |
472 | } |
473 | return buffer.toString(); |
474 | } |
475 | } |
476 | |
477 | /** |
478 | * Transformer for a quantifier operator. |
479 | */ |
480 | class Quantifier implements ListType { |
481 | |
482 | /** LaTeX for quantifier. */ |
483 | private final String latex; |
484 | |
485 | /** |
486 | * Constructor. |
487 | * |
488 | * @param latex LaTeX for quantifier. |
489 | */ |
490 | Quantifier(final String latex) { |
491 | this.latex = latex; |
492 | } |
493 | |
494 | public String getLatex(final ElementList list, final boolean first) { |
495 | final StringBuffer buffer = new StringBuffer(); |
496 | buffer.append(latex + " "); |
497 | for (int i = 0; i < list.size(); i++) { |
498 | if (i != 0 || (i == 0 && list.size() <= 2)) { |
499 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
500 | } |
501 | if (i + 1 < list.size()) { |
502 | buffer.append("\\ "); |
503 | } |
504 | if (list.size() > 2 && i == 1) { |
505 | buffer.append("\\ "); |
506 | } |
507 | } |
508 | return buffer.toString(); |
509 | } |
510 | } |
511 | |
512 | /** |
513 | * Transformer for negation. |
514 | */ |
515 | class Not implements ListType { |
516 | public String getLatex(final ElementList list, final boolean first) { |
517 | final StringBuffer buffer = new StringBuffer(); |
518 | final String prefix = "\\neg "; |
519 | buffer.append(prefix); |
520 | for (int i = 0; i < list.size(); i++) { |
521 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
522 | } |
523 | return buffer.toString(); |
524 | } |
525 | } |
526 | |
527 | /** |
528 | * Transformer for a class operator. |
529 | */ |
530 | class Class implements ListType { |
531 | public String getLatex(final ElementList list, final boolean first) { |
532 | final StringBuffer buffer = new StringBuffer(); |
533 | final String prefix = "\\{ "; |
534 | buffer.append(prefix); |
535 | for (int i = 0; i < list.size(); i++) { |
536 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
537 | if (i + 1 < list.size()) { |
538 | buffer.append(" \\ | \\ "); |
539 | } |
540 | } |
541 | buffer.append(" \\} "); |
542 | return buffer.toString(); |
543 | } |
544 | } |
545 | |
546 | /** |
547 | * Transformer for class list operator. |
548 | */ |
549 | class Classlist implements ListType { |
550 | public String getLatex(final ElementList list, final boolean first) { |
551 | final StringBuffer buffer = new StringBuffer(); |
552 | final String prefix = "\\{ "; |
553 | buffer.append(prefix); |
554 | for (int i = 0; i < list.size(); i++) { |
555 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
556 | if (i + 1 < list.size()) { |
557 | buffer.append(", \\ "); |
558 | } |
559 | } |
560 | buffer.append(" \\} "); |
561 | return buffer.toString(); |
562 | } |
563 | } |
564 | |
565 | // /** |
566 | // * Transformer for a quantifier intersection. |
567 | // */ |
568 | // class QuantorIntersection implements ListType { |
569 | // public String getLatex(final ElementList list, final boolean first) { |
570 | // final StringBuffer buffer = new StringBuffer(); |
571 | // final String prefix = "\\bigcap"; |
572 | // buffer.append(prefix); |
573 | // if (0 < list.size()) { |
574 | // buffer.append("{").append(Element2LatexImpl.this.getLatex(list.getElement(0), false)) |
575 | // .append("}"); |
576 | // } |
577 | // for (int i = 1; i < list.size(); i++) { |
578 | // buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
579 | // if (i + 1 < list.size()) { |
580 | // buffer.append(" \\ \\ "); |
581 | // } |
582 | // } |
583 | // buffer.append(" \\} "); |
584 | // return buffer.toString(); |
585 | // } |
586 | // } |
587 | // |
588 | // /** |
589 | // * LATER mime 20080126: needed? |
590 | // */ |
591 | // class QuantorUnion implements ListType { |
592 | // public String getLatex(final ElementList list, final boolean first) { |
593 | // final StringBuffer buffer = new StringBuffer(); |
594 | // final String prefix = "\\bigcup"; |
595 | // buffer.append(prefix); |
596 | // if (0 < list.size()) { |
597 | // buffer.append("{").append(Element2LatexImpl.this.getLatex(list.getElement(0), false)) |
598 | // .append("}"); |
599 | // } |
600 | // for (int i = 1; i < list.size(); i++) { |
601 | // buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
602 | // if (i + 1 < list.size()) { |
603 | // buffer.append(" \\ \\ "); |
604 | // } |
605 | // } |
606 | // buffer.append(" \\} "); |
607 | // return buffer.toString(); |
608 | // } |
609 | // } |
610 | // |
611 | /** |
612 | * If we don't now what kind of type we have we do this. |
613 | */ |
614 | class Unknown implements ListType { |
615 | public String getLatex(final ElementList list, final boolean first) { |
616 | final StringBuffer buffer = new StringBuffer(); |
617 | buffer.append(list.getOperator()); |
618 | buffer.append("("); |
619 | for (int i = 0; i < list.size(); i++) { |
620 | buffer.append(Element2LatexImpl.this.getLatex(list.getElement(i), false)); |
621 | if (i + 1 < list.size()) { |
622 | buffer.append(", "); |
623 | } |
624 | } |
625 | buffer.append(")"); |
626 | return buffer.toString(); |
627 | } |
628 | } |
629 | |
630 | |
631 | } |