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