| 1 | package org.jtoolkit.essence.data; |
| 2 | |
| 3 | import org.jetbrains.annotations.NotNull; |
| 4 | import org.jetbrains.annotations.Nullable; |
| 5 | import org.jtoolkit.essence.app.ComponentBuilder; |
| 6 | import org.jtoolkit.essence.app.Container; |
| 7 | import org.jtoolkit.essence.app.pojo.DataValue; |
| 8 | import org.jtoolkit.essence.concurrency.NotThreadSafe; |
| 9 | import org.jtoolkit.essence.data.impl.StoreFactory; |
| 10 | import static org.jtoolkit.essence.utils.StringUtils.isSet; |
| 11 | import org.jtoolkit.essence.utils.Named; |
| 12 | |
| 13 | import java.util.Collection; |
| 14 | import java.util.LinkedHashMap; |
| 15 | import java.util.Map; |
| 16 | import java.util.Queue; |
| 17 | |
| 18 | /* |
| 19 | Copyright 2006 Peter Lawrey |
| 20 | |
| 21 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 22 | you may not use this file except in compliance with the License. |
| 23 | You may obtain a copy of the License at |
| 24 | |
| 25 | http://www.apache.org/licenses/LICENSE-2.0 |
| 26 | |
| 27 | Unless required by applicable law or agreed to in writing, software |
| 28 | distributed under the License is distributed on an "AS IS" BASIS, |
| 29 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 30 | See the License for the specific language governing permissions and |
| 31 | limitations under the License. |
| 32 | */ |
| 33 | |
| 34 | /** |
| 35 | * Build Store/Map/Queues from the Collections table in the container configuration. |
| 36 | * |
| 37 | * @author Peter Lawrey |
| 38 | */ |
| 39 | @NotThreadSafe |
| 40 | @SuppressWarnings("unchecked") |
| 41 | public class CollectionComponentBuilder implements ComponentBuilder { |
| 42 | private final String name; |
| 43 | private final Container container; |
| 44 | private final Map<String, CollectionData> collectionDataMap = new LinkedHashMap<String, CollectionData>(); |
| 45 | private final Map<String, Store> storeMap = new LinkedHashMap<String, Store>(); |
| 46 | private final StoreFactory storeFactory = new StoreFactory(); |
| 47 | |
| 48 | public CollectionComponentBuilder(@NotNull String name, @NotNull Container container) throws InstantiationException { |
| 49 | this.name = name; |
| 50 | this.container = container; |
| 51 | for (CollectionData cd : container.removeConfigAs("Collections", CollectionData.class)) |
| 52 | collectionDataMap.put(cd.collection, cd); |
| 53 | } |
| 54 | |
| 55 | @NotNull public String getName() { |
| 56 | return name; |
| 57 | } |
| 58 | |
| 59 | @Nullable |
| 60 | public <T> T resolveComponent(@NotNull String componentName, @Nullable Class<T> type) throws IllegalStateException, IllegalArgumentException { |
| 61 | CollectionData cd = collectionDataMap.get(componentName); |
| 62 | if (cd == null) return null; |
| 63 | Store store = storeMap.get(componentName); |
| 64 | if (store == null) storeMap.put(componentName, store = createStore(cd)); |
| 65 | if (type == null || type == Store.class || type == Event.Listenable.class) return (T) store; |
| 66 | if (type == Map.class) return (T) store.getMapView(); |
| 67 | if (type == Collection.class || type == Queue.class) return (T) store.getQueueView(); |
| 68 | throw new IllegalArgumentException(Container.COMPONENT + componentName + " cannot be cast to " + type); |
| 69 | } |
| 70 | |
| 71 | private Store createStore(CollectionData cd) throws IllegalStateException, IllegalArgumentException { |
| 72 | try { |
| 73 | Named.Source<String> options = container.getProperties(cd.collection); |
| 74 | Store store = storeFactory.acquire(container.getName(), cd.collection, cd.collectionType, |
| 75 | cd.storeType, cd.valueClass, cd.location, cd.readMode, cd.persistMode, options); |
| 76 | if (cd.storeType == Store.StoreType.MEMORY && isSet(cd.location)) { |
| 77 | Collection coll = store.getQueueView(); |
| 78 | for (Object obj : container.removeConfigAs(cd.location, cd.valueClass)) |
| 79 | coll.add(obj); |
| 80 | } |
| 81 | return store; |
| 82 | } catch (InstantiationException e) { |
| 83 | throw new IllegalStateException("Unable to create entries for " + cd.collection, e); |
| 84 | } catch (InterruptedException e) { |
| 85 | Thread.currentThread().interrupt(); |
| 86 | return throwUnableToLoad(cd, e); |
| 87 | } catch (Exception e) { |
| 88 | return throwUnableToLoad(cd, e); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | private static Store throwUnableToLoad(CollectionData cd, Exception e) { |
| 93 | throw new IllegalStateException("Unable to load " + cd.collection, e); |
| 94 | } |
| 95 | |
| 96 | static class CollectionData extends DataValue { |
| 97 | public final String collection; |
| 98 | public final Store.CollectionType collectionType; |
| 99 | public final Store.StoreType storeType; |
| 100 | public final Class valueClass; |
| 101 | public final String location; |
| 102 | public final Store.ReadMode readMode; |
| 103 | public final Store.PersistMode persistMode; |
| 104 | |
| 105 | @SuppressWarnings({"UnusedDeclaration"}) CollectionData(@NotNull String collection, Store.CollectionType collectionType, |
| 106 | @NotNull Store.StoreType storeType, @NotNull Class valueClass, |
| 107 | @NotNull String location, Store.ReadMode readMode, Store.PersistMode persistMode) { |
| 108 | this.collection = collection; |
| 109 | this.collectionType = collectionType; |
| 110 | this.storeType = storeType; |
| 111 | this.valueClass = valueClass; |
| 112 | this.location = location; |
| 113 | this.readMode = readMode; |
| 114 | this.persistMode = persistMode; |
| 115 | } |
| 116 | } |
| 117 | } |