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