001 package de.deepamehta.core.impl; 002 003 import de.deepamehta.core.TopicType; 004 import de.deepamehta.core.AssociationType; 005 import de.deepamehta.core.model.AssociationTypeModel; 006 import de.deepamehta.core.model.TopicTypeModel; 007 008 009 import java.util.HashMap; 010 import java.util.Map; 011 import java.util.logging.Logger; 012 013 014 015 /** 016 * A memory-cache for type definitions: topic types and association types. 017 * <p> 018 * Types are accessed by the {@link get} methods. They are lazy-loaded from the DB. 019 * <p> 020 * This class is internally used by the {@link EmbeddedService}. The plugin developer accesses topic types via the 021 * {@link de.deepamehta.core.service.DeepaMehtaService#getTopicType} core service call. 022 */ 023 class TypeCache { 024 025 // ---------------------------------------------------------------------------------------------- Instance Variables 026 027 private Map<String, TopicType> topicTypes = new HashMap(); // key: topic type URI 028 private Map<String, AssociationType> assocTypes = new HashMap(); // key: assoc type URI 029 030 private EmbeddedService dms; 031 032 private EndlessRecursionDetection endlessRecursionDetection = new EndlessRecursionDetection(); 033 034 private Logger logger = Logger.getLogger(getClass().getName()); 035 036 // ---------------------------------------------------------------------------------------------------- Constructors 037 038 TypeCache(EmbeddedService dms) { 039 this.dms = dms; 040 } 041 042 // ----------------------------------------------------------------------------------------- Package Private Methods 043 044 TopicType getTopicType(String topicTypeUri) { 045 TopicType topicType = topicTypes.get(topicTypeUri); 046 if (topicType == null) { 047 topicType = loadTopicType(topicTypeUri); 048 putTopicType(topicType); 049 } 050 return topicType; 051 } 052 053 AssociationType getAssociationType(String assocTypeUri) { 054 AssociationType assocType = assocTypes.get(assocTypeUri); 055 if (assocType == null) { 056 assocType = loadAssociationType(assocTypeUri); 057 putAssociationType(assocType); 058 } 059 return assocType; 060 } 061 062 // --- 063 064 void putTopicType(TopicType topicType) { 065 topicTypes.put(topicType.getUri(), topicType); 066 } 067 068 void putAssociationType(AssociationType assocType) { 069 assocTypes.put(assocType.getUri(), assocType); 070 } 071 072 // --- 073 074 void removeTopicType(String topicTypeUri) { 075 logger.info("### Removing topic type \"" + topicTypeUri + "\" from type cache"); 076 if (topicTypes.remove(topicTypeUri) == null) { 077 throw new RuntimeException("Topic type \"" + topicTypeUri + "\" not found in type cache"); 078 } 079 dms.typeStorage.removeFromTypeCache(topicTypeUri); 080 } 081 082 void removeAssociationType(String assocTypeUri) { 083 logger.info("### Removing association type \"" + assocTypeUri + "\" from type cache"); 084 if (assocTypes.remove(assocTypeUri) == null) { 085 throw new RuntimeException("Association type \"" + assocTypeUri + "\" not found in type cache"); 086 } 087 dms.typeStorage.removeFromTypeCache(assocTypeUri); 088 } 089 090 // ------------------------------------------------------------------------------------------------- Private Methods 091 092 private TopicType loadTopicType(String topicTypeUri) { 093 try { 094 logger.info("Loading topic type \"" + topicTypeUri + "\""); 095 endlessRecursionDetection.check(topicTypeUri); 096 // 097 TopicTypeModel model = dms.typeStorage.getTopicType(topicTypeUri); 098 return new AttachedTopicType(model, dms); 099 } finally { 100 endlessRecursionDetection.reset(topicTypeUri); 101 } 102 } 103 104 private AssociationType loadAssociationType(String assocTypeUri) { 105 try { 106 logger.info("Loading association type \"" + assocTypeUri + "\""); 107 endlessRecursionDetection.check(assocTypeUri); 108 // 109 AssociationTypeModel model = dms.typeStorage.getAssociationType(assocTypeUri); 110 return new AttachedAssociationType(model, dms); 111 } finally { 112 endlessRecursionDetection.reset(assocTypeUri); 113 } 114 } 115 116 // --- 117 118 private class EndlessRecursionDetection { 119 120 private Map<String, Boolean> loadInProgress = new HashMap(); 121 122 private void check(String typeUri) { 123 if (loadInProgress.get(typeUri) != null) { 124 throw new RuntimeException("Endless recursion detected while loading type \"" + typeUri + "\""); 125 } 126 loadInProgress.put(typeUri, true); 127 } 128 129 private void reset(String typeUri) { 130 loadInProgress.remove(typeUri); 131 } 132 } 133 }