+++ /dev/null
-package org.argeo.cms.jcr.internal;
-
-import static org.argeo.cms.osgi.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.argeo.api.cms.CmsLog;
-import org.argeo.cms.osgi.DataModelNamespace;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleWire;
-import org.osgi.framework.wiring.BundleWiring;
-
-class DataModels implements BundleListener {
- private final static CmsLog log = CmsLog.getLog(DataModels.class);
-
- private Map<String, DataModel> dataModels = new TreeMap<>();
-
- public DataModels(BundleContext bc) {
- for (Bundle bundle : bc.getBundles())
- processBundle(bundle, null);
- bc.addBundleListener(this);
- }
-
- public List<DataModel> getNonAbstractDataModels() {
- List<DataModel> res = new ArrayList<>();
- for (String name : dataModels.keySet()) {
- DataModel dataModel = dataModels.get(name);
- if (!dataModel.isAbstract())
- res.add(dataModel);
- }
- // TODO reorder?
- return res;
- }
-
- @Override
- public void bundleChanged(BundleEvent event) {
- if (event.getType() == Bundle.RESOLVED) {
- processBundle(event.getBundle(), null);
- } else if (event.getType() == Bundle.UNINSTALLED) {
- BundleWiring wiring = event.getBundle().adapt(BundleWiring.class);
- List<BundleCapability> providedDataModels = wiring.getCapabilities(CMS_DATA_MODEL_NAMESPACE);
- if (providedDataModels.size() == 0)
- return;
- for (BundleCapability bundleCapability : providedDataModels) {
- dataModels.remove(bundleCapability.getAttributes().get(DataModelNamespace.NAME));
- }
- }
-
- }
-
- protected void processBundle(Bundle bundle, List<Bundle> scannedBundles) {
- if (scannedBundles != null && scannedBundles.contains(bundle))
- throw new IllegalStateException("Cycle in CMS data model requirements for " + bundle);
- BundleWiring wiring = bundle.adapt(BundleWiring.class);
- if (wiring == null) {
- int bundleState = bundle.getState();
- if (bundleState != Bundle.INSTALLED && bundleState != Bundle.UNINSTALLED) {// ignore unresolved bundles
- log.warn("Bundle " + bundle.getSymbolicName() + " #" + bundle.getBundleId() + " ("
- + bundle.getLocation() + ") cannot be adapted to a wiring");
- } else {
- if (log.isTraceEnabled())
- log.warn("Bundle " + bundle.getSymbolicName() + " is not resolved.");
- }
- return;
- }
- List<BundleCapability> providedDataModels = wiring.getCapabilities(CMS_DATA_MODEL_NAMESPACE);
- if (providedDataModels.size() == 0)
- return;
- List<BundleWire> requiredDataModels = wiring.getRequiredWires(CMS_DATA_MODEL_NAMESPACE);
- // process requirements first
- for (BundleWire bundleWire : requiredDataModels) {
- List<Bundle> nextScannedBundles = new ArrayList<>();
- if (scannedBundles != null)
- nextScannedBundles.addAll(scannedBundles);
- nextScannedBundles.add(bundle);
- Bundle providerBundle = bundleWire.getProvider().getBundle();
- processBundle(providerBundle, nextScannedBundles);
- }
- for (BundleCapability bundleCapability : providedDataModels) {
- String name = (String) bundleCapability.getAttributes().get(DataModelNamespace.NAME);
- assert name != null;
- if (!dataModels.containsKey(name)) {
- DataModel dataModel = new DataModel(name, bundleCapability, requiredDataModels);
- dataModels.put(dataModel.getName(), dataModel);
- }
- }
- }
-
- /** Return a negative depth if dataModel is required by ref, 0 otherwise. */
- static int required(DataModel ref, DataModel dataModel, int depth) {
- for (DataModel dm : ref.getRequired()) {
- if (dm.equals(dataModel))// found here
- return depth - 1;
- int d = required(dm, dataModel, depth - 1);
- if (d != 0)// found deeper
- return d;
- }
- return 0;// not found
- }
-
- class DataModel {
- private final String name;
- private final boolean abstrct;
- // private final boolean standalone;
- private final String cnd;
- private final List<DataModel> required;
-
- private DataModel(String name, BundleCapability bundleCapability, List<BundleWire> requiredDataModels) {
- assert CMS_DATA_MODEL_NAMESPACE.equals(bundleCapability.getNamespace());
- this.name = name;
- Map<String, Object> attrs = bundleCapability.getAttributes();
- abstrct = KernelUtils.asBoolean((String) attrs.get(DataModelNamespace.ABSTRACT));
- // standalone = KernelUtils.asBoolean((String)
- // attrs.get(DataModelNamespace.CAPABILITY_STANDALONE_ATTRIBUTE));
- cnd = (String) attrs.get(DataModelNamespace.CND);
- List<DataModel> req = new ArrayList<>();
- for (BundleWire wire : requiredDataModels) {
- String requiredDataModelName = (String) wire.getCapability().getAttributes()
- .get(DataModelNamespace.NAME);
- assert requiredDataModelName != null;
- DataModel requiredDataModel = dataModels.get(requiredDataModelName);
- if (requiredDataModel == null)
- throw new IllegalStateException("No required data model " + requiredDataModelName);
- req.add(requiredDataModel);
- }
- required = Collections.unmodifiableList(req);
- }
-
- public String getName() {
- return name;
- }
-
- public boolean isAbstract() {
- return abstrct;
- }
-
- // public boolean isStandalone() {
- // return !isAbstract();
- // }
-
- public String getCnd() {
- return cnd;
- }
-
- public List<DataModel> getRequired() {
- return required;
- }
-
- // @Override
- // public int compareTo(DataModel o) {
- // if (equals(o))
- // return 0;
- // int res = required(this, o, 0);
- // if (res != 0)
- // return res;
- // // the other way round
- // res = required(o, this, 0);
- // if (res != 0)
- // return -res;
- // return 0;
- // }
-
- @Override
- public int hashCode() {
- return name.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof DataModel)
- return ((DataModel) obj).name.equals(name);
- return false;
- }
-
- @Override
- public String toString() {
- return "Data model " + name;
- }
-
- }
-
-}