1
2
3
4
5
6 package gov.nist.secauto.metaschema.databind.io;
7
8 import gov.nist.secauto.metaschema.core.configuration.IConfiguration;
9 import gov.nist.secauto.metaschema.core.configuration.IMutableConfiguration;
10 import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
11 import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem;
12 import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
13 import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
14 import gov.nist.secauto.metaschema.core.model.IBoundObject;
15 import gov.nist.secauto.metaschema.core.model.constraint.DefaultConstraintValidator;
16 import gov.nist.secauto.metaschema.core.model.constraint.IConstraintValidationHandler;
17 import gov.nist.secauto.metaschema.core.model.constraint.LoggingConstraintValidationHandler;
18 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
19 import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly;
20
21 import java.io.IOException;
22 import java.io.Reader;
23 import java.net.URI;
24
25 import edu.umd.cs.findbugs.annotations.NonNull;
26
27
28
29
30
31
32
33 public abstract class AbstractDeserializer<CLASS extends IBoundObject>
34 extends AbstractSerializationBase<DeserializationFeature<?>>
35 implements IDeserializer<CLASS> {
36
37 private IConstraintValidationHandler constraintValidationHandler;
38
39
40
41
42
43
44
45
46 protected AbstractDeserializer(@NonNull IBoundDefinitionModelAssembly definition) {
47 super(definition);
48 }
49
50
51
52
53
54
55
56 @Override
57 @NonNull
58 public IConstraintValidationHandler getConstraintValidationHandler() {
59 synchronized (this) {
60 if (constraintValidationHandler == null) {
61 constraintValidationHandler = new LoggingConstraintValidationHandler();
62 }
63 return ObjectUtils.notNull(constraintValidationHandler);
64 }
65 }
66
67 @Override
68 public void setConstraintValidationHandler(@NonNull IConstraintValidationHandler constraintValidationHandler) {
69 synchronized (this) {
70 this.constraintValidationHandler = constraintValidationHandler;
71 }
72 }
73
74 @Override
75 public INodeItem deserializeToNodeItem(Reader reader, URI documentUri) throws IOException {
76
77 INodeItem nodeItem;
78 try {
79 nodeItem = deserializeToNodeItemInternal(reader, documentUri);
80 } catch (Exception ex) {
81 throw new IOException(ex);
82 }
83
84 if (isValidating()) {
85 validate(nodeItem);
86 }
87 return nodeItem;
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101 @NonNull
102 protected abstract INodeItem deserializeToNodeItemInternal(@NonNull Reader reader, @NonNull URI documentUri)
103 throws IOException;
104
105 @Override
106 public final CLASS deserializeToValue(Reader reader, URI documentUri) throws IOException {
107 CLASS retval;
108
109 if (isValidating()) {
110 INodeItem nodeItem = deserializeToNodeItemInternal(reader, documentUri);
111 validate(nodeItem);
112 retval = ObjectUtils.asType(ObjectUtils.requireNonNull(nodeItem.getValue()));
113 } else {
114 retval = deserializeToValueInternal(reader, documentUri);
115 }
116 return retval;
117 }
118
119 private void validate(@NonNull INodeItem nodeItem) {
120 IDefinitionNodeItem<?, ?> definitionNodeItem;
121 if (nodeItem instanceof IDocumentNodeItem) {
122 definitionNodeItem = ((IDocumentNodeItem) nodeItem).getRootAssemblyNodeItem();
123 } else if (nodeItem instanceof IDefinitionNodeItem) {
124 definitionNodeItem = (IDefinitionNodeItem<?, ?>) nodeItem;
125 } else {
126 throw new UnsupportedOperationException(String.format(
127 "The node item type '%s' is not supported for validation.",
128 nodeItem.getClass().getName()));
129 }
130
131 DynamicContext dynamicContext = new DynamicContext(nodeItem.getStaticContext());
132 dynamicContext.setDocumentLoader(getBindingContext().newBoundLoader());
133 DefaultConstraintValidator validator = new DefaultConstraintValidator(getConstraintValidationHandler());
134 validator.validate(definitionNodeItem, dynamicContext);
135 validator.finalizeValidation(dynamicContext);
136 }
137
138 @NonNull
139 protected abstract CLASS deserializeToValueInternal(@NonNull Reader reader, @NonNull URI documentUri)
140 throws IOException;
141
142 @Override
143 public IDeserializer<CLASS> enableFeature(DeserializationFeature<?> feature) {
144 return set(feature, true);
145 }
146
147 @Override
148 public IDeserializer<CLASS> disableFeature(DeserializationFeature<?> feature) {
149 return set(feature, false);
150 }
151
152 @Override
153 public IDeserializer<CLASS> applyConfiguration(
154 @NonNull IConfiguration<DeserializationFeature<?>> other) {
155 IMutableConfiguration<DeserializationFeature<?>> config = getConfiguration();
156 config.applyConfiguration(other);
157 configurationChanged(config);
158 return this;
159 }
160
161 @Override
162 public IDeserializer<CLASS> set(DeserializationFeature<?> feature, Object value) {
163 IMutableConfiguration<DeserializationFeature<?>> config = getConfiguration();
164 config.set(feature, value);
165 configurationChanged(config);
166 return this;
167 }
168 }