1use std::fmt::{self, Display, Formatter};
8
9use crate::ast::{
10 Acceptability, AcceptabilitySet, ActiveValue, AltIdentifier, Attribute, AttributeSet,
11 AttributeValue, Cardinality, Comparison, ConceptFilter, ConceptReference, ConceptSet,
12 ConcreteString, ConstraintOperator, DefinitionStatus, DescriptionFilter, DialectAlias,
13 DialectIdValue, Equality, ExpressionConstraint, FieldValue, FilterConstraint, FocusConcept,
14 HistorySupplement, MemberFilter, MemberOf, NumericValue, Refinement, RefsetFields,
15 RefsetOperator, Sctid, SubAttributeSet, SubExpressionConstraint, SubRefinement, TimeValue,
16 TypeToken, TypedSearchTerm,
17};
18
19fn join<T: Display>(f: &mut Formatter<'_>, items: &[T], separator: &str) -> fmt::Result {
21 for (i, item) in items.iter().enumerate() {
22 if i > 0 {
23 f.write_str(separator)?;
24 }
25 write!(f, "{item}")?;
26 }
27 Ok(())
28}
29
30fn bare_or_set<T: Display>(f: &mut Formatter<'_>, items: &[T]) -> fmt::Result {
32 match items {
33 [one] => write!(f, "{one}"),
34 many => {
35 f.write_str("(")?;
36 join(f, many, " ")?;
37 f.write_str(")")
38 }
39 }
40}
41
42fn quoted(f: &mut Formatter<'_>, text: &str) -> fmt::Result {
44 write!(f, "\"{text}\"")
45}
46
47impl Display for Sctid {
48 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
49 write!(f, "{}", self.0)
50 }
51}
52
53impl Display for ConceptReference {
54 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
55 write!(f, "{}", self.id)?;
56 if let Some(term) = &self.term {
57 write!(f, " |{term}|")?;
58 }
59 Ok(())
60 }
61}
62
63impl Display for AltIdentifier {
64 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
65 let bare = self
66 .code
67 .chars()
68 .all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '.' | '_'));
69 if bare {
70 write!(f, "{}#{}", self.scheme, self.code)?;
71 } else {
72 write!(f, "\"{}#{}\"", self.scheme, self.code)?;
73 }
74 if let Some(term) = &self.term {
75 write!(f, " |{term}|")?;
76 }
77 Ok(())
78 }
79}
80
81impl Display for FocusConcept {
82 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
83 match self {
84 Self::Reference(reference) => write!(f, "{reference}"),
85 Self::Wildcard => f.write_str("*"),
86 Self::AltIdentifier(alt) => write!(f, "{alt}"),
87 Self::Nested(inner) => write!(f, "( {inner} )"),
88 }
89 }
90}
91
92impl Display for ConstraintOperator {
93 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
94 f.write_str(match self {
95 Self::DescendantOf => "<",
96 Self::DescendantOrSelfOf => "<<",
97 Self::ChildOf => "<!",
98 Self::ChildOrSelfOf => "<<!",
99 Self::AncestorOf => ">",
100 Self::AncestorOrSelfOf => ">>",
101 Self::ParentOf => ">!",
102 Self::ParentOrSelfOf => ">>!",
103 Self::Top => "!!>",
104 Self::Bottom => "!!<",
105 })
106 }
107}
108
109impl Display for MemberOf {
110 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
111 f.write_str("^")?;
112 match &self.fields {
113 None => Ok(()),
114 Some(RefsetFields::Any) => f.write_str(" [*]"),
115 Some(RefsetFields::Names(names)) => {
116 f.write_str(" [")?;
117 join(f, names, ", ")?;
118 f.write_str("]")
119 }
120 }
121 }
122}
123
124impl Display for RefsetOperator {
125 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
126 match self {
127 Self::MemberOf(member_of) => write!(f, "{member_of}"),
128 Self::ContainingAny => f.write_str("^R"),
129 }
130 }
131}
132
133impl Display for SubExpressionConstraint {
134 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
135 if let Some(operator) = self.operator {
136 write!(f, "{operator} ")?;
137 }
138 if let Some(refset_operator) = &self.refset_operator {
139 write!(f, "{refset_operator} ")?;
140 }
141 write!(f, "{}", self.focus)?;
142 for filters in &self.member_filters {
143 f.write_str(" {{ M ")?;
144 join(f, filters, ", ")?;
145 f.write_str(" }}")?;
146 }
147 for filter in &self.filters {
148 write!(f, " {filter}")?;
149 }
150 if let Some(history) = &self.history {
151 write!(f, " {history}")?;
152 }
153 Ok(())
154 }
155}
156
157impl Display for FilterConstraint {
158 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
159 match self {
160 Self::Description(filters) => {
161 f.write_str("{{ D ")?;
162 join(f, filters, ", ")?;
163 f.write_str(" }}")
164 }
165 Self::Concept(filters) => {
166 f.write_str("{{ C ")?;
167 join(f, filters, ", ")?;
168 f.write_str(" }}")
169 }
170 }
171 }
172}
173
174impl Display for ExpressionConstraint {
175 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
176 match self {
177 Self::Refined { focus, refinement } => write!(f, "{focus} : {refinement}"),
178 Self::Conjunction(operands) => join(f, operands, " AND "),
179 Self::Disjunction(operands) => join(f, operands, " OR "),
180 Self::Exclusion { left, right } => write!(f, "{left} MINUS {right}"),
181 Self::Dotted { focus, attributes } => {
182 write!(f, "{focus}")?;
183 for attribute in attributes {
184 write!(f, " . {attribute}")?;
185 }
186 Ok(())
187 }
188 Self::Sub(sub) => write!(f, "{sub}"),
189 }
190 }
191}
192
193impl Display for Refinement {
194 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
195 match self {
196 Self::Single(one) => write!(f, "{one}"),
197 Self::Conjunction(items) => join(f, items, ", "),
198 Self::Disjunction(items) => join(f, items, " OR "),
199 }
200 }
201}
202
203impl Display for SubRefinement {
204 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
205 match self {
206 Self::AttributeSet(set) => write!(f, "{set}"),
207 Self::Group {
208 cardinality,
209 attributes,
210 } => {
211 if let Some(cardinality) = cardinality {
212 write!(f, "{cardinality} ")?;
213 }
214 write!(f, "{{ {attributes} }}")
215 }
216 Self::Nested(inner) => write!(f, "( {inner} )"),
217 }
218 }
219}
220
221impl Display for AttributeSet {
222 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
223 match self {
224 Self::Single(one) => write!(f, "{one}"),
225 Self::Conjunction(items) => join(f, items, ", "),
226 Self::Disjunction(items) => join(f, items, " OR "),
227 }
228 }
229}
230
231impl Display for SubAttributeSet {
232 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
233 match self {
234 Self::Attribute(attribute) => write!(f, "{attribute}"),
235 Self::Nested(inner) => write!(f, "( {inner} )"),
236 }
237 }
238}
239
240impl Display for Attribute {
241 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
242 if let Some(cardinality) = self.cardinality {
243 write!(f, "{cardinality} ")?;
244 }
245 if self.reverse {
246 f.write_str("R ")?;
247 }
248 write!(f, "{} {}", self.name, self.value)
249 }
250}
251
252impl Display for AttributeValue {
253 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
254 match self {
255 Self::Expression { operator, value } => write!(f, "{operator} {value}"),
256 Self::Numeric { operator, value } => write!(f, "{operator} {value}"),
257 Self::String { operator, values } => {
258 write!(f, "{operator} ")?;
259 bare_or_set(f, values)
260 }
261 Self::Boolean { operator, value } => write!(f, "{operator} {value}"),
262 }
263 }
264}
265
266impl Display for ConcreteString {
267 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
268 f.write_str("\"")?;
269 for c in self.0.chars() {
270 if matches!(c, '"' | '\\') {
271 f.write_str("\\")?;
272 }
273 write!(f, "{c}")?;
274 }
275 f.write_str("\"")
276 }
277}
278
279impl Display for ActiveValue {
280 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
281 f.write_str(match self {
282 Self::Active => "true",
283 Self::Inactive => "false",
284 Self::Any => "*",
285 })
286 }
287}
288
289impl Display for Cardinality {
290 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
291 match self.max {
292 Some(max) => write!(f, "[{}..{max}]", self.min),
293 None => write!(f, "[{}..*]", self.min),
294 }
295 }
296}
297
298impl Display for Equality {
299 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
300 f.write_str(match self {
301 Self::Equal => "=",
302 Self::NotEqual => "!=",
303 })
304 }
305}
306
307impl Display for Comparison {
308 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
309 f.write_str(match self {
310 Self::Equal => "=",
311 Self::NotEqual => "!=",
312 Self::Less => "<",
313 Self::LessOrEqual => "<=",
314 Self::Greater => ">",
315 Self::GreaterOrEqual => ">=",
316 })
317 }
318}
319
320impl Display for NumericValue {
321 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
322 write!(f, "#{}", self.0)
323 }
324}
325
326impl Display for TypedSearchTerm {
327 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
328 match self {
329 Self::Match(words) => {
330 f.write_str("\"")?;
331 join(f, words, " ")?;
332 f.write_str("\"")
333 }
334 Self::Wild(pattern) => {
335 f.write_str("wild:")?;
336 quoted(f, pattern)
337 }
338 }
339 }
340}
341
342impl Display for DescriptionFilter {
343 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
344 match self {
345 Self::Term { operator, terms } => {
346 write!(f, "term {operator} ")?;
347 bare_or_set(f, terms)
348 }
349 Self::Language { operator, codes } => {
350 write!(f, "language {operator} ")?;
351 bare_or_set(f, codes)
352 }
353 Self::TypeId { operator, value } => write!(f, "typeId {operator} {value}"),
354 Self::Type { operator, tokens } => {
355 write!(f, "type {operator} ")?;
356 bare_or_set(f, tokens)
357 }
358 Self::DialectId {
359 operator,
360 value,
361 acceptability,
362 } => {
363 write!(f, "dialectId {operator} {value}")?;
364 if let Some(acceptability) = acceptability {
365 write!(f, " {acceptability}")?;
366 }
367 Ok(())
368 }
369 Self::Dialect {
370 operator,
371 aliases,
372 acceptability,
373 } => {
374 write!(f, "dialect {operator} ")?;
375 match aliases.as_slice() {
376 [
377 DialectAlias {
378 alias,
379 acceptability: None,
380 },
381 ] => f.write_str(alias)?,
382 many => {
383 f.write_str("(")?;
384 join(f, many, " ")?;
385 f.write_str(")")?;
386 }
387 }
388 if let Some(acceptability) = acceptability {
389 write!(f, " {acceptability}")?;
390 }
391 Ok(())
392 }
393 Self::Module { operator, value } => write!(f, "moduleId {operator} {value}"),
394 Self::EffectiveTime { operator, values } => {
395 write!(f, "effectiveTime {operator} ")?;
396 bare_or_set(f, values)
397 }
398 Self::Active { operator, value } => write!(f, "active {operator} {value}"),
399 Self::Id { operator, ids } => {
400 write!(f, "id {operator} ")?;
401 bare_or_set(f, ids)
402 }
403 }
404 }
405}
406
407impl Display for ConceptSet {
408 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
409 match self {
410 Self::Expression(sub) => write!(f, "{sub}"),
411 Self::Set(references) => {
412 f.write_str("(")?;
413 join(f, references, " ")?;
414 f.write_str(")")
415 }
416 }
417 }
418}
419
420impl Display for TypeToken {
421 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
422 f.write_str(match self {
423 Self::Synonym => "syn",
424 Self::FullySpecifiedName => "fsn",
425 Self::Definition => "def",
426 })
427 }
428}
429
430impl Display for DialectIdValue {
431 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
432 match self {
433 Self::Expression(sub) => write!(f, "{sub}"),
434 Self::Set(items) => {
435 f.write_str("(")?;
436 for (i, (reference, acceptability)) in items.iter().enumerate() {
437 if i > 0 {
438 f.write_str(" ")?;
439 }
440 write!(f, "{reference}")?;
441 if let Some(acceptability) = acceptability {
442 write!(f, " {acceptability}")?;
443 }
444 }
445 f.write_str(")")
446 }
447 }
448 }
449}
450
451impl Display for DialectAlias {
452 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
453 f.write_str(&self.alias)?;
454 if let Some(acceptability) = &self.acceptability {
455 write!(f, " {acceptability}")?;
456 }
457 Ok(())
458 }
459}
460
461impl Display for AcceptabilitySet {
462 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
463 f.write_str("(")?;
464 match self {
465 Self::Concepts(references) => join(f, references, " ")?,
466 Self::Tokens(tokens) => join(f, tokens, " ")?,
467 }
468 f.write_str(")")
469 }
470}
471
472impl Display for Acceptability {
473 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
474 f.write_str(match self {
475 Self::Acceptable => "accept",
476 Self::Preferred => "prefer",
477 })
478 }
479}
480
481impl Display for TimeValue {
482 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
483 quoted(f, &self.0)
484 }
485}
486
487impl Display for ConceptFilter {
488 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
489 match self {
490 Self::DefinitionStatusId { operator, value } => {
491 write!(f, "definitionStatusId {operator} {value}")
492 }
493 Self::DefinitionStatus { operator, tokens } => {
494 write!(f, "definitionStatus {operator} ")?;
495 bare_or_set(f, tokens)
496 }
497 Self::Module { operator, value } => write!(f, "moduleId {operator} {value}"),
498 Self::EffectiveTime { operator, values } => {
499 write!(f, "effectiveTime {operator} ")?;
500 bare_or_set(f, values)
501 }
502 Self::Active { operator, value } => write!(f, "active {operator} {value}"),
503 }
504 }
505}
506
507impl Display for DefinitionStatus {
508 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
509 f.write_str(match self {
510 Self::Primitive => "primitive",
511 Self::Defined => "defined",
512 })
513 }
514}
515
516impl Display for MemberFilter {
517 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
518 match self {
519 Self::Module { operator, value } => write!(f, "moduleId {operator} {value}"),
520 Self::EffectiveTime { operator, values } => {
521 write!(f, "effectiveTime {operator} ")?;
522 bare_or_set(f, values)
523 }
524 Self::Active { operator, value } => write!(f, "active {operator} {value}"),
525 Self::Field { name, value } => write!(f, "{name} {value}"),
526 }
527 }
528}
529
530impl Display for FieldValue {
531 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
532 match self {
533 Self::Expression { operator, value } => write!(f, "{operator} {value}"),
534 Self::Numeric { operator, value } => write!(f, "{operator} {value}"),
535 Self::String { operator, terms } => {
536 write!(f, "{operator} ")?;
537 bare_or_set(f, terms)
538 }
539 Self::Boolean { operator, value } => write!(f, "{operator} {value}"),
540 Self::Time { operator, values } => {
541 write!(f, "{operator} ")?;
542 bare_or_set(f, values)
543 }
544 }
545 }
546}
547
548impl Display for HistorySupplement {
549 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
550 match self {
551 Self::Default => f.write_str("{{ + HISTORY }}"),
552 Self::Minimum => f.write_str("{{ + HISTORY-MIN }}"),
553 Self::Moderate => f.write_str("{{ + HISTORY-MOD }}"),
554 Self::Maximum => f.write_str("{{ + HISTORY-MAX }}"),
555 Self::Subset(inner) => write!(f, "{{{{ + HISTORY ( {inner} ) }}}}"),
556 }
557 }
558}