diff options
| author | RncLsn <rnc.lsn@gmail.com> | 2015-06-05 12:22:31 +0100 |
|---|---|---|
| committer | RncLsn <rnc.lsn@gmail.com> | 2015-06-05 12:22:31 +0100 |
| commit | 8c04e4d8003f33848ee84011f8427fe92d55001f (patch) | |
| tree | ee750152d2403cdb78503dbb41c70f0c3cfb1125 /src/uk | |
| parent | b0148d89a76b8fcbeb2e021442842e4e89690ef3 (diff) | |
| download | ACQuA-8c04e4d8003f33848ee84011f8427fe92d55001f.tar.gz ACQuA-8c04e4d8003f33848ee84011f8427fe92d55001f.zip | |
Violation statistics.
Diffstat (limited to 'src/uk')
6 files changed, 94 insertions, 12 deletions
diff --git a/src/uk/ac/ox/cs/pagoda/multistage/MultiStageQueryEngine.java b/src/uk/ac/ox/cs/pagoda/multistage/MultiStageQueryEngine.java index af1b413..479905d 100644 --- a/src/uk/ac/ox/cs/pagoda/multistage/MultiStageQueryEngine.java +++ b/src/uk/ac/ox/cs/pagoda/multistage/MultiStageQueryEngine.java | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | package uk.ac.ox.cs.pagoda.multistage; | 1 | package uk.ac.ox.cs.pagoda.multistage; |
| 2 | 2 | ||
| 3 | import org.semanticweb.HermiT.model.DLClause; | ||
| 3 | import uk.ac.ox.cs.JRDFox.JRDFStoreException; | 4 | import uk.ac.ox.cs.JRDFox.JRDFStoreException; |
| 4 | import uk.ac.ox.cs.pagoda.constraints.BottomStrategy; | 5 | import uk.ac.ox.cs.pagoda.constraints.BottomStrategy; |
| 5 | import uk.ac.ox.cs.pagoda.multistage.treatement.Pick4NegativeConceptNaive; | 6 | import uk.ac.ox.cs.pagoda.multistage.treatement.Pick4NegativeConceptNaive; |
| @@ -9,14 +10,26 @@ import uk.ac.ox.cs.pagoda.query.GapByStore4ID; | |||
| 9 | import uk.ac.ox.cs.pagoda.query.QueryRecord; | 10 | import uk.ac.ox.cs.pagoda.query.QueryRecord; |
| 10 | import uk.ac.ox.cs.pagoda.rules.DatalogProgram; | 11 | import uk.ac.ox.cs.pagoda.rules.DatalogProgram; |
| 11 | import uk.ac.ox.cs.pagoda.rules.Program; | 12 | import uk.ac.ox.cs.pagoda.rules.Program; |
| 13 | import uk.ac.ox.cs.pagoda.util.PagodaProperties; | ||
| 12 | import uk.ac.ox.cs.pagoda.util.Timer; | 14 | import uk.ac.ox.cs.pagoda.util.Timer; |
| 13 | import uk.ac.ox.cs.pagoda.util.Utility; | 15 | import uk.ac.ox.cs.pagoda.util.Utility; |
| 14 | import uk.ac.ox.cs.pagoda.util.disposable.DisposedException; | 16 | import uk.ac.ox.cs.pagoda.util.disposable.DisposedException; |
| 15 | 17 | ||
| 18 | import java.io.BufferedWriter; | ||
| 19 | import java.io.IOException; | ||
| 20 | import java.nio.file.Files; | ||
| 21 | import java.nio.file.Path; | ||
| 22 | import java.nio.file.Paths; | ||
| 23 | import java.util.ArrayList; | ||
| 16 | import java.util.Collection; | 24 | import java.util.Collection; |
| 25 | import java.util.HashMap; | ||
| 26 | import java.util.List; | ||
| 27 | import java.util.stream.Collectors; | ||
| 17 | 28 | ||
| 18 | public class MultiStageQueryEngine extends StageQueryEngine { | 29 | public class MultiStageQueryEngine extends StageQueryEngine { |
| 19 | 30 | ||
| 31 | private HashMap<String, List> statistics = new HashMap<>(); | ||
| 32 | |||
| 20 | public MultiStageQueryEngine(String name, boolean checkValidity) { | 33 | public MultiStageQueryEngine(String name, boolean checkValidity) { |
| 21 | super(name, checkValidity); | 34 | super(name, checkValidity); |
| 22 | } | 35 | } |
| @@ -94,6 +107,14 @@ public class MultiStageQueryEngine extends StageQueryEngine { | |||
| 94 | return ret; | 107 | return ret; |
| 95 | } | 108 | } |
| 96 | 109 | ||
| 110 | @Override | ||
| 111 | public void dispose() { | ||
| 112 | super.dispose(); | ||
| 113 | |||
| 114 | if(PagodaProperties.isDebuggingMode()) | ||
| 115 | outputStatistics(); | ||
| 116 | } | ||
| 117 | |||
| 97 | private int materialise(MultiStageUpperProgram program, Treatment treatment, GapByStore4ID gap) { | 118 | private int materialise(MultiStageUpperProgram program, Treatment treatment, GapByStore4ID gap) { |
| 98 | if(gap != null) | 119 | if(gap != null) |
| 99 | treatment.addAdditionalGapTuples(); | 120 | treatment.addAdditionalGapTuples(); |
| @@ -169,7 +190,11 @@ public class MultiStageQueryEngine extends StageQueryEngine { | |||
| 169 | subTimer.reset(); | 190 | subTimer.reset(); |
| 170 | oldTripleCount = store.getTriplesCount(); | 191 | oldTripleCount = store.getTriplesCount(); |
| 171 | 192 | ||
| 172 | Utility.logInfo("Number of violations: " + violations.size()); | 193 | Utility.logDebug("Number of violations: " + violations.size()); |
| 194 | |||
| 195 | updateStatistics("violationClauses", violations.stream() | ||
| 196 | .map(Violation::getClause) | ||
| 197 | .collect(Collectors.toList())); | ||
| 173 | 198 | ||
| 174 | for(Violation v : violations) { | 199 | for(Violation v : violations) { |
| 175 | 200 | ||
| @@ -198,5 +223,21 @@ public class MultiStageQueryEngine extends StageQueryEngine { | |||
| 198 | return 0; | 223 | return 0; |
| 199 | } | 224 | } |
| 200 | 225 | ||
| 226 | private void updateStatistics(String key, List<DLClause> value) { | ||
| 227 | if(!statistics.containsKey(key)) | ||
| 228 | statistics.put(key, new ArrayList<List>()); | ||
| 229 | statistics.get(key).add(value.stream().map(DLClause::toString).collect(Collectors.toList())); | ||
| 230 | } | ||
| 231 | |||
| 232 | private void outputStatistics() { | ||
| 233 | Path statisticsPath = PagodaProperties.getDefaultStatisticsDir() | ||
| 234 | .resolve(Paths.get("MultiStageQueryEngine-ViolationSequence.json")); | ||
| 235 | try(BufferedWriter writer = Files.newBufferedWriter(statisticsPath)) { | ||
| 236 | QueryRecord.GsonCreator.getInstance().toJson(statistics, writer); | ||
| 237 | } catch(IOException e) { | ||
| 238 | e.printStackTrace(); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 201 | } | 242 | } |
| 202 | 243 | ||
diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java index 727f80d..e6e508a 100644 --- a/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java +++ b/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java | |||
| @@ -370,7 +370,7 @@ class MyQueryReasoner extends QueryReasoner { | |||
| 370 | 370 | ||
| 371 | relevantStore.importDataFromABoxOf(relevantSubset); | 371 | relevantStore.importDataFromABoxOf(relevantSubset); |
| 372 | 372 | ||
| 373 | int queryDependentMaxTermDepth = 1; // TODO make it dynamic | 373 | int queryDependentMaxTermDepth = 5; // TODO make it dynamic |
| 374 | int materialisationTag = relevantStore.materialiseSkolemly(relevantProgram, null, | 374 | int materialisationTag = relevantStore.materialiseSkolemly(relevantProgram, null, |
| 375 | queryDependentMaxTermDepth); | 375 | queryDependentMaxTermDepth); |
| 376 | queryRecord.addProcessingTime(Step.SKOLEM_UPPER_BOUND, t.duration()); | 376 | queryRecord.addProcessingTime(Step.SKOLEM_UPPER_BOUND, t.duration()); |
| @@ -386,6 +386,8 @@ class MyQueryReasoner extends QueryReasoner { | |||
| 386 | boolean isFullyProcessed = queryUpperStore(relevantStore, queryRecord, | 386 | boolean isFullyProcessed = queryUpperStore(relevantStore, queryRecord, |
| 387 | queryRecord.getExtendedQueryText(), | 387 | queryRecord.getExtendedQueryText(), |
| 388 | Step.SKOLEM_UPPER_BOUND); | 388 | Step.SKOLEM_UPPER_BOUND); |
| 389 | |||
| 390 | relevantStore.dispose(); | ||
| 389 | Utility.logInfo("Semi-Skolemised relevant upper store has been evaluated"); | 391 | Utility.logInfo("Semi-Skolemised relevant upper store has been evaluated"); |
| 390 | return isFullyProcessed; | 392 | return isFullyProcessed; |
| 391 | } | 393 | } |
diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxAnswerTuples.java b/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxAnswerTuples.java index 1e8181f..f823232 100644 --- a/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxAnswerTuples.java +++ b/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxAnswerTuples.java | |||
| @@ -9,6 +9,7 @@ import uk.ac.ox.cs.JRDFox.store.TupleIterator; | |||
| 9 | import uk.ac.ox.cs.pagoda.query.AnswerTuple; | 9 | import uk.ac.ox.cs.pagoda.query.AnswerTuple; |
| 10 | import uk.ac.ox.cs.pagoda.query.AnswerTuples; | 10 | import uk.ac.ox.cs.pagoda.query.AnswerTuples; |
| 11 | import uk.ac.ox.cs.pagoda.util.Utility; | 11 | import uk.ac.ox.cs.pagoda.util.Utility; |
| 12 | import uk.ac.ox.cs.pagoda.util.disposable.DisposedException; | ||
| 12 | 13 | ||
| 13 | public class RDFoxAnswerTuples extends AnswerTuples { | 14 | public class RDFoxAnswerTuples extends AnswerTuples { |
| 14 | 15 | ||
| @@ -35,11 +36,15 @@ public class RDFoxAnswerTuples extends AnswerTuples { | |||
| 35 | 36 | ||
| 36 | @Override | 37 | @Override |
| 37 | public boolean isValid() { | 38 | public boolean isValid() { |
| 39 | if(isDisposed()) throw new DisposedException(); | ||
| 40 | |||
| 38 | return multi != 0; | 41 | return multi != 0; |
| 39 | } | 42 | } |
| 40 | 43 | ||
| 41 | @Override | 44 | @Override |
| 42 | public int getArity() { | 45 | public int getArity() { |
| 46 | if(isDisposed()) throw new DisposedException(); | ||
| 47 | |||
| 43 | try { | 48 | try { |
| 44 | return m_iter.getArity(); | 49 | return m_iter.getArity(); |
| 45 | } catch (JRDFStoreException e) { | 50 | } catch (JRDFStoreException e) { |
| @@ -50,6 +55,8 @@ public class RDFoxAnswerTuples extends AnswerTuples { | |||
| 50 | 55 | ||
| 51 | @Override | 56 | @Override |
| 52 | public void moveNext() { | 57 | public void moveNext() { |
| 58 | if(isDisposed()) throw new DisposedException(); | ||
| 59 | |||
| 53 | try { | 60 | try { |
| 54 | multi = m_iter.getNext(); | 61 | multi = m_iter.getNext(); |
| 55 | } catch (JRDFStoreException e) { | 62 | } catch (JRDFStoreException e) { |
| @@ -65,11 +72,15 @@ public class RDFoxAnswerTuples extends AnswerTuples { | |||
| 65 | 72 | ||
| 66 | @Override | 73 | @Override |
| 67 | public AnswerTuple getTuple() { | 74 | public AnswerTuple getTuple() { |
| 75 | if(isDisposed()) throw new DisposedException(); | ||
| 76 | |||
| 68 | return new AnswerTuple(m_iter, m_answerVars.length); | 77 | return new AnswerTuple(m_iter, m_answerVars.length); |
| 69 | } | 78 | } |
| 70 | 79 | ||
| 71 | @Override | 80 | @Override |
| 72 | public void reset() { | 81 | public void reset() { |
| 82 | if(isDisposed()) throw new DisposedException(); | ||
| 83 | |||
| 73 | try { | 84 | try { |
| 74 | multi = m_iter.open(); | 85 | multi = m_iter.open(); |
| 75 | } catch (JRDFStoreException e) { | 86 | } catch (JRDFStoreException e) { |
| @@ -79,17 +90,23 @@ public class RDFoxAnswerTuples extends AnswerTuples { | |||
| 79 | 90 | ||
| 80 | @Override | 91 | @Override |
| 81 | public boolean contains(AnswerTuple t) { | 92 | public boolean contains(AnswerTuple t) { |
| 93 | if(isDisposed()) throw new DisposedException(); | ||
| 94 | |||
| 82 | Utility.logError("Unsupported operation in RDFoxAnswerTuples"); | 95 | Utility.logError("Unsupported operation in RDFoxAnswerTuples"); |
| 83 | return false; | 96 | return false; |
| 84 | } | 97 | } |
| 85 | 98 | ||
| 86 | @Override | 99 | @Override |
| 87 | public void remove() { | 100 | public void remove() { |
| 101 | if(isDisposed()) throw new DisposedException(); | ||
| 102 | |||
| 88 | Utility.logError("Unsupported operation in RDFoxAnswerTuples"); | 103 | Utility.logError("Unsupported operation in RDFoxAnswerTuples"); |
| 89 | } | 104 | } |
| 90 | 105 | ||
| 91 | @Override | 106 | @Override |
| 92 | public String[] getAnswerVariables() { | 107 | public String[] getAnswerVariables() { |
| 108 | if(isDisposed()) throw new DisposedException(); | ||
| 109 | |||
| 93 | return m_answerVars; | 110 | return m_answerVars; |
| 94 | } | 111 | } |
| 95 | 112 | ||
diff --git a/src/uk/ac/ox/cs/pagoda/rules/approximators/SkolemTermsManager.java b/src/uk/ac/ox/cs/pagoda/rules/approximators/SkolemTermsManager.java index ef004c4..44daf7a 100644 --- a/src/uk/ac/ox/cs/pagoda/rules/approximators/SkolemTermsManager.java +++ b/src/uk/ac/ox/cs/pagoda/rules/approximators/SkolemTermsManager.java | |||
| @@ -87,6 +87,13 @@ public class SkolemTermsManager { | |||
| 87 | return individualToDepth_map.keySet().size(); | 87 | return individualToDepth_map.keySet().size(); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | /** | ||
| 91 | * Just for reading the clause id from <tt>LimitedSkolemisationApproximator</tt>. | ||
| 92 | */ | ||
| 93 | int getClauseId(DLClause clause) { | ||
| 94 | return clauseToId_map.get(clause); | ||
| 95 | } | ||
| 96 | |||
| 90 | private int mapClauseToId(DLClause clause) { | 97 | private int mapClauseToId(DLClause clause) { |
| 91 | if(!clauseToId_map.containsKey(clause)) { | 98 | if(!clauseToId_map.containsKey(clause)) { |
| 92 | clauseToId_map.put(clause, termsCounter); | 99 | clauseToId_map.put(clause, termsCounter); |
diff --git a/src/uk/ac/ox/cs/pagoda/util/PagodaProperties.java b/src/uk/ac/ox/cs/pagoda/util/PagodaProperties.java index e07d54f..2c53063 100644 --- a/src/uk/ac/ox/cs/pagoda/util/PagodaProperties.java +++ b/src/uk/ac/ox/cs/pagoda/util/PagodaProperties.java | |||
| @@ -5,6 +5,8 @@ import org.apache.log4j.Logger; | |||
| 5 | import java.io.FileInputStream; | 5 | import java.io.FileInputStream; |
| 6 | import java.io.IOException; | 6 | import java.io.IOException; |
| 7 | import java.io.InputStream; | 7 | import java.io.InputStream; |
| 8 | import java.nio.file.Path; | ||
| 9 | import java.nio.file.Paths; | ||
| 8 | import java.util.Properties; | 10 | import java.util.Properties; |
| 9 | 11 | ||
| 10 | public class PagodaProperties { | 12 | public class PagodaProperties { |
| @@ -13,6 +15,7 @@ public class PagodaProperties { | |||
| 13 | public static final boolean DEFAULT_DEBUG = false; | 15 | public static final boolean DEFAULT_DEBUG = false; |
| 14 | private static final boolean DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND; | 16 | private static final boolean DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND; |
| 15 | private static final boolean DEFAULT_USE_SKOLEM_UPPER_BOUND; | 17 | private static final boolean DEFAULT_USE_SKOLEM_UPPER_BOUND; |
| 18 | private static final Path DEFAULT_STATISTICS_DIR; | ||
| 16 | 19 | ||
| 17 | public static boolean shellModeDefault = false; | 20 | public static boolean shellModeDefault = false; |
| 18 | private static boolean debug = DEFAULT_DEBUG; | 21 | private static boolean debug = DEFAULT_DEBUG; |
| @@ -20,6 +23,7 @@ public class PagodaProperties { | |||
| 20 | static { | 23 | static { |
| 21 | boolean defaultUseAlwaysSimpleUpperBound = false; | 24 | boolean defaultUseAlwaysSimpleUpperBound = false; |
| 22 | boolean defaultUseSkolemUpperBound = true; | 25 | boolean defaultUseSkolemUpperBound = true; |
| 26 | Path defaultStatisticsDir = null; | ||
| 23 | 27 | ||
| 24 | try(InputStream in = PagodaProperties.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) { | 28 | try(InputStream in = PagodaProperties.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) { |
| 25 | Properties config = new Properties(); | 29 | Properties config = new Properties(); |
| @@ -28,8 +32,12 @@ public class PagodaProperties { | |||
| 28 | Logger logger = Logger.getLogger("PagodaProperties"); | 32 | Logger logger = Logger.getLogger("PagodaProperties"); |
| 29 | if(config.containsKey("debug")) { | 33 | if(config.containsKey("debug")) { |
| 30 | debug = Boolean.parseBoolean(config.getProperty("debug")); | 34 | debug = Boolean.parseBoolean(config.getProperty("debug")); |
| 31 | // logger.info("Debugging mode is enabled (you can disable it from file \"pagoda.properties\")"); | ||
| 32 | logger.info("Debugging mode is enabled"); | 35 | logger.info("Debugging mode is enabled"); |
| 36 | |||
| 37 | if(config.containsKey("statisticsDir")) { | ||
| 38 | defaultStatisticsDir = Paths.get(config.getProperty("statisticsDir")); | ||
| 39 | logger.info("The directory where statistics are saved is: \"" + defaultStatisticsDir + "\""); | ||
| 40 | } | ||
| 33 | } | 41 | } |
| 34 | if(config.containsKey("useAlwaysSimpleUpperBound")) { | 42 | if(config.containsKey("useAlwaysSimpleUpperBound")) { |
| 35 | defaultUseAlwaysSimpleUpperBound = | 43 | defaultUseAlwaysSimpleUpperBound = |
| @@ -40,11 +48,13 @@ public class PagodaProperties { | |||
| 40 | defaultUseSkolemUpperBound = Boolean.parseBoolean(config.getProperty("useSkolemUpperBound")); | 48 | defaultUseSkolemUpperBound = Boolean.parseBoolean(config.getProperty("useSkolemUpperBound")); |
| 41 | logger.info("The Skolem upper bound is enabled"); | 49 | logger.info("The Skolem upper bound is enabled"); |
| 42 | } | 50 | } |
| 51 | |||
| 43 | } catch(IOException e) { | 52 | } catch(IOException e) { |
| 44 | e.printStackTrace(); | 53 | e.printStackTrace(); |
| 45 | } | 54 | } |
| 46 | DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND = defaultUseAlwaysSimpleUpperBound; | 55 | DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND = defaultUseAlwaysSimpleUpperBound; |
| 47 | DEFAULT_USE_SKOLEM_UPPER_BOUND = defaultUseSkolemUpperBound; | 56 | DEFAULT_USE_SKOLEM_UPPER_BOUND = defaultUseSkolemUpperBound; |
| 57 | DEFAULT_STATISTICS_DIR = defaultStatisticsDir; | ||
| 48 | } | 58 | } |
| 49 | 59 | ||
| 50 | String dataPath = null; | 60 | String dataPath = null; |
| @@ -56,6 +66,8 @@ public class PagodaProperties { | |||
| 56 | boolean shellMode = shellModeDefault; | 66 | boolean shellMode = shellModeDefault; |
| 57 | private boolean useAlwaysSimpleUpperBound = DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND; | 67 | private boolean useAlwaysSimpleUpperBound = DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND; |
| 58 | private boolean useSkolemUpperBound = DEFAULT_USE_SKOLEM_UPPER_BOUND; | 68 | private boolean useSkolemUpperBound = DEFAULT_USE_SKOLEM_UPPER_BOUND; |
| 69 | private Path statisticsDir = DEFAULT_STATISTICS_DIR; | ||
| 70 | |||
| 59 | public PagodaProperties(String path) { | 71 | public PagodaProperties(String path) { |
| 60 | java.util.Properties m_properties = new java.util.Properties(); | 72 | java.util.Properties m_properties = new java.util.Properties(); |
| 61 | InputStream inputStream = null; | 73 | InputStream inputStream = null; |
| @@ -92,6 +104,10 @@ public class PagodaProperties { | |||
| 92 | return DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND; | 104 | return DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND; |
| 93 | } | 105 | } |
| 94 | 106 | ||
| 107 | public static Path getDefaultStatisticsDir() { | ||
| 108 | return DEFAULT_STATISTICS_DIR; | ||
| 109 | } | ||
| 110 | |||
| 95 | public static boolean getDefaultUseSkolemUpperBound() { | 111 | public static boolean getDefaultUseSkolemUpperBound() { |
| 96 | return DEFAULT_USE_SKOLEM_UPPER_BOUND; | 112 | return DEFAULT_USE_SKOLEM_UPPER_BOUND; |
| 97 | } | 113 | } |
| @@ -167,4 +183,12 @@ public class PagodaProperties { | |||
| 167 | public void setUseSkolemUpperBound(boolean flag) { | 183 | public void setUseSkolemUpperBound(boolean flag) { |
| 168 | useSkolemUpperBound = flag; | 184 | useSkolemUpperBound = flag; |
| 169 | } | 185 | } |
| 186 | |||
| 187 | public Path getStatisticsDir() { | ||
| 188 | return statisticsDir; | ||
| 189 | } | ||
| 190 | |||
| 191 | public void setStatisticsDir(Path statisticsDir) { | ||
| 192 | this.statisticsDir = statisticsDir; | ||
| 193 | } | ||
| 170 | } | 194 | } |
diff --git a/src/uk/ac/ox/cs/pagoda/util/disposable/Disposable.java b/src/uk/ac/ox/cs/pagoda/util/disposable/Disposable.java index b208cc3..4015b66 100644 --- a/src/uk/ac/ox/cs/pagoda/util/disposable/Disposable.java +++ b/src/uk/ac/ox/cs/pagoda/util/disposable/Disposable.java | |||
| @@ -25,15 +25,6 @@ public abstract class Disposable { | |||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | private class AlreadyDisposedException extends RuntimeException { | 27 | private class AlreadyDisposedException extends RuntimeException { |
| 28 | |||
| 29 | public AlreadyDisposedException() { | ||
| 30 | super(); | ||
| 31 | } | ||
| 32 | |||
| 33 | public AlreadyDisposedException(String msg) { | ||
| 34 | super(msg); | ||
| 35 | } | ||
| 36 | } | 28 | } |
| 37 | 29 | ||
| 38 | |||
| 39 | } | 30 | } |
