001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.schematic.internal.schema;
017
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.Iterator;
021import java.util.List;
022import org.modeshape.schematic.SchemaLibrary;
023import org.modeshape.schematic.annotation.NotThreadSafe;
024import org.modeshape.schematic.document.JsonSchema.Type;
025import org.modeshape.schematic.document.Path;
026
027/**
028 * Basic implementation of {@link SchemaLibrary.Results} to which problems can be added.
029 * 
030 * @author Randall Hauch <rhauch@redhat.com> (C) 2011 Red Hat Inc.
031 */
032@NotThreadSafe
033public class ValidationResult implements SchemaLibrary.Results, Problems {
034
035    private final List<SchemaLibrary.Problem> problems = new ArrayList<>();
036    private int successes;
037
038    @Override
039    public Iterator<SchemaLibrary.Problem> iterator() {
040        return Collections.unmodifiableList(problems).iterator();
041    }
042
043    @Override
044    public boolean hasProblems() {
045        return !problems.isEmpty();
046    }
047
048    @Override
049    public boolean hasErrors() {
050        for (SchemaLibrary.Problem problem : problems) {
051            if (problem.getType() == SchemaLibrary.ProblemType.ERROR) return true;
052        }
053        return false;
054    }
055
056    @Override
057    public boolean hasWarnings() {
058        for (SchemaLibrary.Problem problem : problems) {
059            if (problem.getType() == SchemaLibrary.ProblemType.WARNING) return true;
060        }
061        return false;
062    }
063
064    @Override
065    public boolean hasOnlyTypeMismatchErrors() {
066        boolean foundMismatch = false;
067        for (SchemaLibrary.Problem problem : problems) {
068            if (problem.getType() == SchemaLibrary.ProblemType.ERROR) {
069                if (problem instanceof SchemaLibrary.MismatchedTypeProblem) foundMismatch = true;
070                else return false;
071            }
072        }
073        return foundMismatch;
074    }
075
076    @Override
077    public int errorCount() {
078        int result = 0;
079        for (SchemaLibrary.Problem problem : problems) {
080            if (problem.getType() == SchemaLibrary.ProblemType.ERROR) ++result;
081        }
082        return result;
083    }
084
085    @Override
086    public int warningCount() {
087        int result = 0;
088        for (SchemaLibrary.Problem problem : problems) {
089            if (problem.getType() == SchemaLibrary.ProblemType.WARNING) ++result;
090        }
091        return result;
092    }
093
094    @Override
095    public int problemCount() {
096        return problems.size();
097    }
098
099    public int successCount() {
100        return successes;
101    }
102
103    @Override
104    public void recordSuccess() {
105        ++successes;
106    }
107
108    @Override
109    public void recordError( Path path,
110                             String reason ) {
111        problems.add(new ValidationProblem(SchemaLibrary.ProblemType.ERROR, path, reason, null));
112    }
113
114    @Override
115    public void recordError( Path path,
116                             String reason,
117                             Throwable cause ) {
118        problems.add(new ValidationProblem(SchemaLibrary.ProblemType.ERROR, path, reason, cause));
119    }
120
121    @Override
122    public void recordWarning( Path path,
123                               String reason ) {
124        problems.add(new ValidationProblem(SchemaLibrary.ProblemType.WARNING, path, reason, null));
125    }
126
127    @Override
128    public void recordTypeMismatch( Path path,
129                                    String reason,
130                                    Type actualType,
131                                    Object actualValue,
132                                    Type requiredType,
133                                    Object convertedValue ) {
134        problems.add(new ValidationTypeMismatchProblem(SchemaLibrary.ProblemType.ERROR, path, actualValue, actualType, requiredType,
135                                                       convertedValue, reason, null));
136    }
137
138    public void recordIn( Problems otherProblems ) {
139        if (successes == 0 && problems.isEmpty()) return;
140
141        for (SchemaLibrary.Problem problem : problems) {
142            for (int i = 0; i != successes; ++i) {
143                otherProblems.recordSuccess();
144            }
145            switch (problem.getType()) {
146                case ERROR:
147                    if (problem instanceof SchemaLibrary.MismatchedTypeProblem) {
148                        SchemaLibrary.MismatchedTypeProblem mismatch = (SchemaLibrary.MismatchedTypeProblem)problem;
149                        otherProblems.recordTypeMismatch(mismatch.getPath(),
150                                                         mismatch.getReason(),
151                                                         mismatch.getActualType(),
152                                                         mismatch.getActualValue(),
153                                                         mismatch.getExpectedType(),
154                                                         mismatch.getConvertedValue());
155                    } else {
156                        otherProblems.recordError(problem.getPath(), problem.getReason(), problem.getCause());
157                    }
158                    break;
159                case WARNING:
160                    otherProblems.recordWarning(problem.getPath(), problem.getReason());
161                    break;
162            }
163        }
164    }
165
166    public void add( SchemaLibrary.Problem problem ) {
167        if (problem != null) {
168            problems.add(problem);
169        }
170    }
171
172    public void addAll( Iterable<SchemaLibrary.Problem> results ) {
173        if (results != null) {
174            for (SchemaLibrary.Problem problem : results) {
175                problems.add(problem);
176            }
177        }
178    }
179
180    public void addAll( Iterator<SchemaLibrary.Results> iter ) {
181        if (iter != null) {
182            while (iter.hasNext()) {
183                addAll(iter.next());
184            }
185        }
186    }
187
188    @Override
189    public String toString() {
190        StringBuilder sb = new StringBuilder();
191        for (SchemaLibrary.Problem problem : problems) {
192            sb.append(problem);
193            sb.append('\n');
194        }
195        return sb.toString();
196    }
197
198}