You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2016/05/20 00:44:51 UTC
[14/30] isis git commit: ISIS-1407: removed SpecificationLoaderAware.
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
new file mode 100644
index 0000000..13fe785
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
@@ -0,0 +1,514 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.metamodel.services;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
+import org.apache.isis.applib.services.publish.PublishingService;
+import org.apache.isis.core.commons.components.ApplicationScopedComponent;
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.commons.lang.ObjectExtensions;
+import org.apache.isis.core.commons.util.ToString;
+import org.apache.isis.core.metamodel.exceptions.MetaModelException;
+import org.apache.isis.core.metamodel.spec.InjectorMethodEvaluator;
+import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
+import org.apache.isis.core.metamodel.specloader.ServiceInitializer;
+
+/**
+ * The repository of services, also able to inject into any object.
+ *
+ * <p>
+ * Implementation is (and must be) a thread-safe.
+ * </p>
+ *
+ */
+public class ServicesInjector implements ApplicationScopedComponent {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ServicesInjector.class);
+
+ //region > constructor, fields
+ /**
+ * This is mutable internally, but only ever exposed (in {@link #getRegisteredServices()}) as immutable.
+ */
+ private final List<Object> services = Lists.newArrayList();
+
+ /**
+ * If no key, not yet searched for type; otherwise the corresponding value is a {@link List} of all
+ * services that are assignable to the type. It's possible that this is an empty list.
+ */
+ private final Map<Class<?>, List<Object>> servicesAssignableToType = Maps.newHashMap();
+
+ private final Map<Class<?>, Object> serviceByConcreteType = Maps.newHashMap();
+
+ private final InjectorMethodEvaluator injectorMethodEvaluator;
+
+ public ServicesInjector(final List<Object> services) {
+ this(services, null);
+ }
+
+ /**
+ * For testing.
+ */
+ public ServicesInjector(final List<Object> services, final InjectorMethodEvaluator injectorMethodEvaluator) {
+ this.services.addAll(services);
+ this.injectorMethodEvaluator =
+ injectorMethodEvaluator != null
+ ? injectorMethodEvaluator
+ : new InjectorMethodEvaluatorDefault();
+
+ autowireServicesAndContainer();
+ }
+
+ //endregion
+
+ //region > replaceServices
+
+ /**
+ * Update an individual service.
+ *
+ * <p>
+ * There should already be a service {@link #getRegisteredServices() registered} of the specified type.
+ *
+ * @return <tt>true</tt> if a service of the specified type was found and updated, <tt>false</tt> otherwise.
+ * @param existingService
+ * @param replacementService
+ */
+ public <T> void replaceService(final T existingService, final T replacementService) {
+
+ if(!services.remove(existingService)) {
+ throw new IllegalArgumentException("Service to be replaced was not found (" + existingService + ")");
+ }
+
+ services.add(replacementService);
+
+ // invalidate
+ servicesAssignableToType.clear();
+ serviceByConcreteType.clear();
+
+ autowireServicesAndContainer();
+ }
+
+ public boolean isRegisteredService(final Class<?> cls) {
+ // lazily construct cache
+ if(serviceByConcreteType.isEmpty()) {
+ for (Object service : services) {
+ final Class<?> concreteType = service.getClass();
+ serviceByConcreteType.put(concreteType, service);
+ }
+ }
+ return serviceByConcreteType.containsKey(cls);
+ }
+
+ public <T> void addFallbackIfRequired(final Class<T> serviceClass, final T serviceInstance) {
+ if(!contains(services, serviceClass)) {
+ // add to beginning;
+ // (when first introduced, this feature has been used for the
+ // FixtureScriptsDefault so that appears it top of prototyping menu; not
+ // more flexible than this currently just because of YAGNI).
+ services.add(0, serviceInstance);
+ }
+ }
+
+ /**
+ * Validate domain service Ids are unique, and that the {@link PostConstruct} method, if present, must either
+ * take no arguments or take a {@link Map} object), and that the {@link PreDestroy} method, if present, must take
+ * no arguments.
+ *
+ * <p>
+ * TODO: there seems to be some duplication/overlap with {@link ServiceInitializer}.
+ */
+ public void validateServices() {
+ validate(getRegisteredServices());
+ }
+
+ private static void validate(List<Object> serviceList) {
+ for (Object service : serviceList) {
+ final Method[] methods = service.getClass().getMethods();
+ for (Method method : methods) {
+ validatePostConstructMethods(service, method);
+ validatePreDestroyMethods(service, method);
+ }
+ }
+ ListMultimap<String, Object> servicesById = ArrayListMultimap.create();
+ for (Object service : serviceList) {
+ String id = ServiceUtil.id(service);
+ servicesById.put(id, service);
+ }
+ for (Map.Entry<String, Collection<Object>> servicesForId : servicesById.asMap().entrySet()) {
+ String serviceId = servicesForId.getKey();
+ Collection<Object> services = servicesForId.getValue();
+ if(services.size() > 1) {
+ throw new IllegalStateException(
+ String.format("Service ids must be unique; serviceId '%s' is declared by domain services %s",
+ serviceId, classNamesFor(services)));
+ }
+ }
+ }
+
+ private static String classNamesFor(Collection<Object> services) {
+ StringBuilder buf = new StringBuilder();
+ for (Object service : services) {
+ if(buf.length() > 0) {
+ buf.append(", ");
+ }
+ buf.append(service.getClass().getName());
+ }
+ return buf.toString();
+ }
+
+ private static void validatePostConstructMethods(Object service, Method method) {
+ final PostConstruct postConstruct = method.getAnnotation(PostConstruct.class);
+ if(postConstruct == null) {
+ return;
+ }
+ final int numParams = method.getParameterTypes().length;
+ if(numParams == 0) {
+ return;
+ }
+ if(numParams == 1 && method.getParameterTypes()[0].isAssignableFrom(Map.class)) {
+ return;
+ }
+ throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PostConstruct method " + method.getName() + "; such methods must take either no argument or 1 argument of type Map<String,String>");
+ }
+
+ private static void validatePreDestroyMethods(Object service, Method method) {
+ final PreDestroy preDestroy = method.getAnnotation(PreDestroy.class);
+ if(preDestroy == null) {
+ return;
+ }
+ final int numParams = method.getParameterTypes().length;
+ if(numParams == 0) {
+ return;
+ }
+ throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PreDestroy method " + method.getName() + "; such methods must take no arguments");
+ }
+
+
+ static boolean contains(final List<Object> services, final Class<?> serviceClass) {
+ for (Object service : services) {
+ if(serviceClass.isAssignableFrom(service.getClass())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * All registered services, as an immutable {@link List}.
+ */
+ public List<Object> getRegisteredServices() {
+ return Collections.unmodifiableList(services);
+ }
+
+ private void addServices(final List<Object> services) {
+ for (final Object service : services) {
+ if (service instanceof List) {
+ final List<Object> serviceList = ObjectExtensions.asListT(service, Object.class);
+ addServices(serviceList);
+ } else {
+ addService(service);
+ }
+ }
+ }
+
+ private boolean addService(final Object service) {
+ return services.add(service);
+ }
+
+ //endregion
+
+ //region > injectServicesInto
+
+ /**
+ * Provided by the <tt>ServicesInjector</tt> when used by framework.
+ *
+ * <p>
+ * Called in multiple places from metamodel and facets.
+ */
+ public void injectServicesInto(final Object object) {
+ Assert.assertNotNull("no services", services);
+
+ injectServices(object, Collections.unmodifiableList(services));
+ }
+
+ /**
+ * As per {@link #injectServicesInto(Object)}, but for all objects in the
+ * list.
+ */
+ public void injectServicesInto(final List<Object> objects) {
+ for (final Object object : objects) {
+ injectServicesInto(object);
+ }
+ }
+
+ //endregion
+
+ //region > injectInto
+
+ /**
+ * That is, injecting this injector...
+ */
+ public void injectInto(final Object candidate) {
+ if (ServicesInjectorAware.class.isAssignableFrom(candidate.getClass())) {
+ final ServicesInjectorAware cast = ServicesInjectorAware.class.cast(candidate);
+ cast.setServicesInjector(this);
+ }
+ }
+
+ //endregion
+
+ //region > helpers
+
+ private void injectServices(final Object object, final List<Object> services) {
+
+ final Class<?> cls = object.getClass();
+
+ autowireViaFields(object, services, cls);
+ autowireViaPrefixedMethods(object, services, cls, "set");
+ autowireViaPrefixedMethods(object, services, cls, "inject");
+ }
+
+ private void autowireViaFields(final Object object, final List<Object> services, final Class<?> cls) {
+ final List<Field> fields = Arrays.asList(cls.getDeclaredFields());
+ final Iterable<Field> injectFields = Iterables.filter(fields, new Predicate<Field>() {
+ @Override
+ public boolean apply(final Field input) {
+ final Inject annotation = input.getAnnotation(javax.inject.Inject.class);
+ return annotation != null;
+ }
+ });
+
+ for (final Field field : injectFields) {
+ autowire(object, field, services);
+ }
+
+ // recurse up the object's class hierarchy
+ final Class<?> superclass = cls.getSuperclass();
+ if(superclass != null) {
+ autowireViaFields(object, services, superclass);
+ }
+ }
+
+ private void autowire(
+ final Object object,
+ final Field field,
+ final List<Object> services) {
+
+ final Class<?> type = field.getType();
+ // don't think that type can ever be null,
+ // but Javadoc for java.lang.reflect.Field doesn't say
+ if(type == null) {
+ return;
+ }
+
+ // inject into Collection<T> or List<T>
+ if(Collection.class.isAssignableFrom(type) || List.class.isAssignableFrom(type)) {
+ final Type genericType = field.getGenericType();
+ if(genericType instanceof ParameterizedType) {
+ final ParameterizedType listParameterizedType = (ParameterizedType) genericType;
+ final Class<?> listType = (Class<?>) listParameterizedType.getActualTypeArguments()[0];
+ final List<Object> listOfServices =
+ Collections.unmodifiableList(
+ Lists.newArrayList(
+ Iterables.filter(services, new Predicate<Object>() {
+ @Override
+ public boolean apply(final Object input) {
+ return input != null && listType.isAssignableFrom(input.getClass());
+ }
+ })));
+ invokeInjectorField(field, object, listOfServices);
+ }
+ }
+
+ for (final Object service : services) {
+ final Class<?> serviceClass = service.getClass();
+ if(type.isAssignableFrom(serviceClass)) {
+ invokeInjectorField(field, object, service);
+ return;
+ }
+ }
+ }
+
+ private void autowireViaPrefixedMethods(
+ final Object object,
+ final List<Object> services,
+ final Class<?> cls,
+ final String prefix) {
+ final List<Method> methods = Arrays.asList(cls.getMethods());
+ final Iterable<Method> prefixedMethods = Iterables.filter(methods, new Predicate<Method>(){
+ public boolean apply(final Method method) {
+ final String methodName = method.getName();
+ return methodName.startsWith(prefix);
+ }
+ });
+
+ for (final Method prefixedMethod : prefixedMethods) {
+ autowire(object, prefixedMethod, services);
+ }
+ }
+
+ private void autowire(
+ final Object object,
+ final Method prefixedMethod,
+ final List<Object> services) {
+ for (final Object service : services) {
+ final Class<?> serviceClass = service.getClass();
+ final boolean isInjectorMethod = injectorMethodEvaluator.isInjectorMethodFor(prefixedMethod, serviceClass);
+ if(isInjectorMethod) {
+ prefixedMethod.setAccessible(true);
+ invokeInjectorMethod(prefixedMethod, object, service);
+ return;
+ }
+ }
+ }
+
+ private static void invokeMethod(final Method method, final Object target, final Object[] parameters) {
+ try {
+ method.invoke(target, parameters);
+ } catch (final SecurityException | IllegalAccessException e) {
+ throw new MetaModelException(String.format("Cannot access the %s method in %s", method.getName(), target.getClass().getName()));
+ } catch (final IllegalArgumentException e1) {
+ throw new MetaModelException(e1);
+ } catch (final InvocationTargetException e) {
+ final Throwable targetException = e.getTargetException();
+ if (targetException instanceof RuntimeException) {
+ throw (RuntimeException) targetException;
+ } else {
+ throw new MetaModelException(targetException);
+ }
+ }
+ }
+
+ private static void invokeInjectorField(final Field field, final Object target, final Object parameter) {
+ try {
+ field.setAccessible(true);
+ field.set(target, parameter);
+ } catch (final IllegalArgumentException e) {
+ throw new MetaModelException(e);
+ } catch (final IllegalAccessException e) {
+ throw new MetaModelException(String.format("Cannot access the %s field in %s", field.getName(), target.getClass().getName()));
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("injected " + parameter + " into " + new ToString(target));
+ }
+ }
+
+ private static void invokeInjectorMethod(final Method method, final Object target, final Object parameter) {
+ final Object[] parameters = new Object[] { parameter };
+ invokeMethod(method, target, parameters);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("injected " + parameter + " into " + new ToString(target));
+ }
+ }
+
+ private void autowireServicesAndContainer() {
+ injectServicesInto(this.services);
+ }
+
+
+ //endregion
+
+ //region > lookupService, lookupServices
+
+ /**
+ * Returns the first registered domain service implementing the requested type.
+ *
+ * <p>
+ * Typically there will only ever be one domain service implementing a given type,
+ * (eg {@link PublishingService}), but for some services there can be more than one
+ * (eg {@link ExceptionRecognizer}).
+ *
+ * @see #lookupServices(Class)
+ */
+ @Programmatic
+ public <T> T lookupService(final Class<T> serviceClass) {
+ final List<T> services = lookupServices(serviceClass);
+ return !services.isEmpty() ? services.get(0) : null;
+ }
+
+ /**
+ * Returns all domain services implementing the requested type, in the order
+ * that they were registered in <tt>isis.properties</tt>.
+ *
+ * <p>
+ * Typically there will only ever be one domain service implementing a given type,
+ * (eg {@link PublishingService}), but for some services there can be more than one
+ * (eg {@link ExceptionRecognizer}).
+ *
+ * @see #lookupService(Class)
+ */
+ @SuppressWarnings("unchecked")
+ @Programmatic
+ public <T> List<T> lookupServices(final Class<T> serviceClass) {
+ locateAndCache(serviceClass);
+ return Collections.unmodifiableList((List<T>) servicesAssignableToType.get(serviceClass));
+ };
+
+ private void locateAndCache(final Class<?> serviceClass) {
+ if(servicesAssignableToType.containsKey(serviceClass)) {
+ return;
+ }
+
+ final List<Object> matchingServices = Lists.newArrayList();
+ addAssignableTo(serviceClass, services, matchingServices);
+
+ servicesAssignableToType.put(serviceClass, matchingServices);
+ }
+
+ private static void addAssignableTo(final Class<?> type, final List<Object> candidates, final List<Object> filteredServicesAndContainer) {
+ final Iterable<Object> filteredServices = Iterables.filter(candidates, ofType(type));
+ filteredServicesAndContainer.addAll(Lists.newArrayList(filteredServices));
+ }
+
+ private static final Predicate<Object> ofType(final Class<?> cls) {
+ return new Predicate<Object>() {
+ @Override
+ public boolean apply(final Object input) {
+ return cls.isAssignableFrom(input.getClass());
+ }
+ };
+ }
+
+ //endregion
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorAware.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorAware.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorAware.java
new file mode 100644
index 0000000..b7908f7
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorAware.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.core.metamodel.services;
+
+import org.apache.isis.applib.annotation.Programmatic;
+
+public interface ServicesInjectorAware {
+
+ @Programmatic
+ void setServicesInjector(ServicesInjector servicesInjector);
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
deleted file mode 100644
index 9eb9d36..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.isis.core.metamodel.services;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.isis.core.commons.ensure.Assert;
-import org.apache.isis.core.commons.lang.ObjectExtensions;
-import org.apache.isis.core.commons.util.ToString;
-import org.apache.isis.core.metamodel.exceptions.MetaModelException;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
-import org.apache.isis.core.metamodel.spec.InjectorMethodEvaluator;
-import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
-import org.apache.isis.core.metamodel.specloader.ServiceInitializer;
-
-/**
- * Must be a thread-safe.
- */
-public class ServicesInjectorDefault implements ServicesInjectorSpi {
-
- private static final Logger LOG = LoggerFactory.getLogger(ServicesInjectorDefault.class);
-
- /**
- * This is mutable internally, but only ever exposed (in {@link #getRegisteredServices()}) as immutable.
- */
- private final List<Object> services = Lists.newArrayList();
-
- /**
- * If no key, not yet searched for type; otherwise the corresponding value is a {@link List} of all
- * services that are assignable to the type. It's possible that this is an empty list.
- */
- private final Map<Class<?>, List<Object>> servicesAssignableToType = Maps.newHashMap();
-
- private final Map<Class<?>, Object> serviceByConcreteType = Maps.newHashMap();
-
- private final InjectorMethodEvaluator injectorMethodEvaluator;
-
- public ServicesInjectorDefault(final List<Object> services) {
- this(services, null);
- }
-
- /**
- * For testing.
- */
- public ServicesInjectorDefault(final List<Object> services, final InjectorMethodEvaluator injectorMethodEvaluator) {
- this.services.addAll(services);
- this.injectorMethodEvaluator = injectorMethodEvaluator != null ? injectorMethodEvaluator : new InjectorMethodEvaluatorDefault();
-
- autowireServicesAndContainer();
- }
-
- //region > replaceServices
-
- @Override
- public <T> void replaceService(final T existingService, final T replacementService) {
-
- if(!services.remove(existingService)) {
- throw new IllegalArgumentException("Service to be replaced was not found (" + existingService + ")");
- }
-
- services.add(replacementService);
-
- // invalidate
- servicesAssignableToType.clear();
- serviceByConcreteType.clear();
-
- autowireServicesAndContainer();
- }
-
- @Override
- public boolean isRegisteredService(final Class<?> cls) {
- // lazily construct cache
- if(serviceByConcreteType.isEmpty()) {
- for (Object service : services) {
- final Class<?> concreteType = service.getClass();
- serviceByConcreteType.put(concreteType, service);
- }
- }
- return serviceByConcreteType.containsKey(cls);
- }
-
- @Override
- public <T> void addFallbackIfRequired(final Class<T> serviceClass, final T serviceInstance) {
- if(!contains(services, serviceClass)) {
- // add to beginning;
- // (when first introduced, this feature has been used for the
- // FixtureScriptsDefault so that appears it top of prototyping menu; not
- // more flexible than this currently just because of YAGNI).
- services.add(0, serviceInstance);
- }
- }
-
- /**
- * Validate domain service Ids are unique, and that the {@link PostConstruct} method, if present, must either
- * take no arguments or take a {@link Map} object), and that the {@link PreDestroy} method, if present, must take
- * no arguments.
- *
- * <p>
- * TODO: there seems to be some duplication/overlap with {@link ServiceInitializer}.
- */
- @Override
- public void validateServices() {
- validate(getRegisteredServices());
- }
-
- private static void validate(List<Object> serviceList) {
- for (Object service : serviceList) {
- final Method[] methods = service.getClass().getMethods();
- for (Method method : methods) {
- validatePostConstructMethods(service, method);
- validatePreDestroyMethods(service, method);
- }
- }
- ListMultimap<String, Object> servicesById = ArrayListMultimap.create();
- for (Object service : serviceList) {
- String id = ServiceUtil.id(service);
- servicesById.put(id, service);
- }
- for (Map.Entry<String, Collection<Object>> servicesForId : servicesById.asMap().entrySet()) {
- String serviceId = servicesForId.getKey();
- Collection<Object> services = servicesForId.getValue();
- if(services.size() > 1) {
- throw new IllegalStateException(
- String.format("Service ids must be unique; serviceId '%s' is declared by domain services %s",
- serviceId, classNamesFor(services)));
- }
- }
- }
-
- private static String classNamesFor(Collection<Object> services) {
- StringBuilder buf = new StringBuilder();
- for (Object service : services) {
- if(buf.length() > 0) {
- buf.append(", ");
- }
- buf.append(service.getClass().getName());
- }
- return buf.toString();
- }
-
- private static void validatePostConstructMethods(Object service, Method method) {
- final PostConstruct postConstruct = method.getAnnotation(PostConstruct.class);
- if(postConstruct == null) {
- return;
- }
- final int numParams = method.getParameterTypes().length;
- if(numParams == 0) {
- return;
- }
- if(numParams == 1 && method.getParameterTypes()[0].isAssignableFrom(Map.class)) {
- return;
- }
- throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PostConstruct method " + method.getName() + "; such methods must take either no argument or 1 argument of type Map<String,String>");
- }
-
- private static void validatePreDestroyMethods(Object service, Method method) {
- final PreDestroy preDestroy = method.getAnnotation(PreDestroy.class);
- if(preDestroy == null) {
- return;
- }
- final int numParams = method.getParameterTypes().length;
- if(numParams == 0) {
- return;
- }
- throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PreDestroy method " + method.getName() + "; such methods must take no arguments");
- }
-
-
- static boolean contains(final List<Object> services, final Class<?> serviceClass) {
- for (Object service : services) {
- if(serviceClass.isAssignableFrom(service.getClass())) {
- return true;
- }
- }
- return false;
- }
-
-
- @Override
- public List<Object> getRegisteredServices() {
- return Collections.unmodifiableList(services);
- }
-
- private void addServices(final List<Object> services) {
- for (final Object service : services) {
- if (service instanceof List) {
- final List<Object> serviceList = ObjectExtensions.asListT(service, Object.class);
- addServices(serviceList);
- } else {
- addService(service);
- }
- }
- }
-
- private boolean addService(final Object service) {
- return services.add(service);
- }
-
- //endregion
-
- //region > injectServicesInto
-
- @Override
- public void injectServicesInto(final Object object) {
- Assert.assertNotNull("no services", services);
-
- injectServices(object, Collections.unmodifiableList(services));
- }
-
- @Override
- public void injectServicesInto(final List<Object> objects) {
- for (final Object object : objects) {
- injectServicesInto(object);
- }
- }
-
- //endregion
-
- //region > injectInto
-
- /**
- * That is, injecting this injector...
- */
- @Override
- public void injectInto(final Object candidate) {
- if (ServicesInjectorAware.class.isAssignableFrom(candidate.getClass())) {
- final ServicesInjectorAware cast = ServicesInjectorAware.class.cast(candidate);
- cast.setServicesInjector(this);
- }
- }
-
- //endregion
-
- //region > helpers
-
- private void injectServices(final Object object, final List<Object> services) {
-
- final Class<?> cls = object.getClass();
-
- autowireViaFields(object, services, cls);
- autowireViaPrefixedMethods(object, services, cls, "set");
- autowireViaPrefixedMethods(object, services, cls, "inject");
- }
-
- private void autowireViaFields(final Object object, final List<Object> services, final Class<?> cls) {
- final List<Field> fields = Arrays.asList(cls.getDeclaredFields());
- final Iterable<Field> injectFields = Iterables.filter(fields, new Predicate<Field>() {
- @Override
- public boolean apply(final Field input) {
- final Inject annotation = input.getAnnotation(javax.inject.Inject.class);
- return annotation != null;
- }
- });
-
- for (final Field field : injectFields) {
- autowire(object, field, services);
- }
-
- // recurse up the object's class hierarchy
- final Class<?> superclass = cls.getSuperclass();
- if(superclass != null) {
- autowireViaFields(object, services, superclass);
- }
- }
-
- private void autowire(
- final Object object,
- final Field field,
- final List<Object> services) {
-
- final Class<?> type = field.getType();
- // don't think that type can ever be null,
- // but Javadoc for java.lang.reflect.Field doesn't say
- if(type == null) {
- return;
- }
-
- // inject into Collection<T> or List<T>
- if(Collection.class.isAssignableFrom(type) || List.class.isAssignableFrom(type)) {
- final Type genericType = field.getGenericType();
- if(genericType instanceof ParameterizedType) {
- final ParameterizedType listParameterizedType = (ParameterizedType) genericType;
- final Class<?> listType = (Class<?>) listParameterizedType.getActualTypeArguments()[0];
- final List<Object> listOfServices =
- Collections.unmodifiableList(
- Lists.newArrayList(
- Iterables.filter(services, new Predicate<Object>() {
- @Override
- public boolean apply(final Object input) {
- return input != null && listType.isAssignableFrom(input.getClass());
- }
- })));
- invokeInjectorField(field, object, listOfServices);
- }
- }
-
- for (final Object service : services) {
- final Class<?> serviceClass = service.getClass();
- if(type.isAssignableFrom(serviceClass)) {
- invokeInjectorField(field, object, service);
- return;
- }
- }
- }
-
- private void autowireViaPrefixedMethods(
- final Object object,
- final List<Object> services,
- final Class<?> cls,
- final String prefix) {
- final List<Method> methods = Arrays.asList(cls.getMethods());
- final Iterable<Method> prefixedMethods = Iterables.filter(methods, new Predicate<Method>(){
- public boolean apply(final Method method) {
- final String methodName = method.getName();
- return methodName.startsWith(prefix);
- }
- });
-
- for (final Method prefixedMethod : prefixedMethods) {
- autowire(object, prefixedMethod, services);
- }
- }
-
- private void autowire(
- final Object object,
- final Method prefixedMethod,
- final List<Object> services) {
- for (final Object service : services) {
- final Class<?> serviceClass = service.getClass();
- final boolean isInjectorMethod = injectorMethodEvaluator.isInjectorMethodFor(prefixedMethod, serviceClass);
- if(isInjectorMethod) {
- prefixedMethod.setAccessible(true);
- invokeInjectorMethod(prefixedMethod, object, service);
- return;
- }
- }
- }
-
- private static void invokeMethod(final Method method, final Object target, final Object[] parameters) {
- try {
- method.invoke(target, parameters);
- } catch (final SecurityException | IllegalAccessException e) {
- throw new MetaModelException(String.format("Cannot access the %s method in %s", method.getName(), target.getClass().getName()));
- } catch (final IllegalArgumentException e1) {
- throw new MetaModelException(e1);
- } catch (final InvocationTargetException e) {
- final Throwable targetException = e.getTargetException();
- if (targetException instanceof RuntimeException) {
- throw (RuntimeException) targetException;
- } else {
- throw new MetaModelException(targetException);
- }
- }
- }
-
- private static void invokeInjectorField(final Field field, final Object target, final Object parameter) {
- try {
- field.setAccessible(true);
- field.set(target, parameter);
- } catch (final IllegalArgumentException e) {
- throw new MetaModelException(e);
- } catch (final IllegalAccessException e) {
- throw new MetaModelException(String.format("Cannot access the %s field in %s", field.getName(), target.getClass().getName()));
- }
- if (LOG.isDebugEnabled()) {
- LOG.debug("injected " + parameter + " into " + new ToString(target));
- }
- }
-
- private static void invokeInjectorMethod(final Method method, final Object target, final Object parameter) {
- final Object[] parameters = new Object[] { parameter };
- invokeMethod(method, target, parameters);
- if (LOG.isDebugEnabled()) {
- LOG.debug("injected " + parameter + " into " + new ToString(target));
- }
- }
-
- private void autowireServicesAndContainer() {
- injectServicesInto(this.services);
- }
-
-
- //endregion
-
- //region > lookupService, lookupServices
-
- @Override
- public <T> T lookupService(final Class<T> serviceClass) {
- final List<T> services = lookupServices(serviceClass);
- return !services.isEmpty() ? services.get(0) : null;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T> List<T> lookupServices(final Class<T> serviceClass) {
- locateAndCache(serviceClass);
- return Collections.unmodifiableList((List<T>) servicesAssignableToType.get(serviceClass));
- };
-
- private void locateAndCache(final Class<?> serviceClass) {
- if(servicesAssignableToType.containsKey(serviceClass)) {
- return;
- }
-
- final List<Object> matchingServices = Lists.newArrayList();
- addAssignableTo(serviceClass, services, matchingServices);
-
- servicesAssignableToType.put(serviceClass, matchingServices);
- }
-
- private static void addAssignableTo(final Class<?> type, final List<Object> candidates, final List<Object> filteredServicesAndContainer) {
- final Iterable<Object> filteredServices = Iterables.filter(candidates, ofType(type));
- filteredServicesAndContainer.addAll(Lists.newArrayList(filteredServices));
- }
-
- private static final Predicate<Object> ofType(final Class<?> cls) {
- return new Predicate<Object>() {
- @Override
- public boolean apply(final Object input) {
- return cls.isAssignableFrom(input.getClass());
- }
- };
- }
-
- //endregion
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
deleted file mode 100644
index ef8f7e6..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.isis.core.metamodel.services;
-
-import org.apache.isis.core.commons.components.ApplicationScopedComponent;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
-
-/**
- * The repository of services, also able to inject into any object.
- *
- * <p>
- * Can be considered a mutable SPI to the {@link org.apache.isis.core.metamodel.runtimecontext.ServicesInjector} immutable API.
- */
-public interface ServicesInjectorSpi extends ApplicationScopedComponent, ServicesInjector {
-
- /**
- * Update an individual service.
- *
- * <p>
- * There should already be a service {@link #getRegisteredServices() registered} of the specified type.
- *
- * @return <tt>true</tt> if a service of the specified type was found and updated, <tt>false</tt> otherwise.
- * @param originalService
- * @param replacementService
- */
- <T> void replaceService(T originalService, T replacementService);
-
- boolean isRegisteredService(Class<?> cls);
-
- <T> void addFallbackIfRequired(Class<T> serviceClass, T serviceInstance);
-
- void validateServices();
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
index fd8f0c9..077a518 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
@@ -42,6 +42,7 @@ import org.apache.isis.applib.annotation.Where;
import org.apache.isis.applib.fixturescripts.FixtureScript;
import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
import org.apache.isis.applib.services.appfeat.ApplicationMemberType;
+import org.apache.isis.applib.services.registry.ServiceRegistry2;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
import org.apache.isis.core.metamodel.facets.SingleIntValueFacet;
import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
@@ -50,23 +51,19 @@ import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemove
import org.apache.isis.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
import org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet;
import org.apache.isis.core.metamodel.facets.properties.update.modify.PropertySetterFacet;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoaderAware;
import org.apache.isis.core.metamodel.spec.feature.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.core.metamodel.specloader.specimpl.ContributeeMember;
@DomainService(
nature = NatureOfService.DOMAIN,
repositoryFor = ApplicationFeature.class
)
-public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRepository, SpecificationLoaderAware,
- ServicesInjectorAware {
+public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRepository {
//region > caches
SortedMap<ApplicationFeatureId, ApplicationFeature> packageFeatures = Maps.newTreeMap();
@@ -86,7 +83,7 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
}
private Collection<ObjectSpecification> primeMetaModel() {
- final List<Object> services = servicesInjector.getRegisteredServices();
+ final List<Object> services = serviceRegistry.getRegisteredServices();
for (final Object service : services) {
specificationLoader.loadSpecification(service.getClass());
}
@@ -321,7 +318,7 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
* </p>
*/
private boolean isSuperClassOfService(final ObjectSpecification spec) {
- final List<Object> registeredServices = servicesInjector.getRegisteredServices();
+ final List<Object> registeredServices = serviceRegistry.getRegisteredServices();
final Class<?> specClass = spec.getCorrespondingClass();
@@ -512,23 +509,15 @@ public class ApplicationFeatureRepositoryDefault implements ApplicationFeatureRe
//endregion
//region > services (injected)
- @Inject
- DomainObjectContainer container;
-
- private SpecificationLoader specificationLoader;
- @Programmatic
- @Override
- public void setSpecificationLoader(final SpecificationLoader specificationLoader) {
- this.specificationLoader = specificationLoader;
- }
+ @Inject
+ ServiceRegistry2 serviceRegistry;
- private ServicesInjector servicesInjector;
+ @Inject
+ DomainObjectContainer container;
- @Override
- public void setServicesInjector(final ServicesInjector servicesInjector) {
- this.servicesInjector = servicesInjector;
- }
+ @Inject
+ SpecificationLoader specificationLoader;
@Inject
ApplicationFeatureFactory applicationFeatureFactory;
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java
index aee46d9..adb18a1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java
@@ -24,6 +24,7 @@ import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
+import javax.inject.Inject;
import com.google.common.base.Predicate;
@@ -65,13 +66,10 @@ import org.apache.isis.core.metamodel.services.container.query.QueryFindByPatter
import org.apache.isis.core.metamodel.services.container.query.QueryFindByTitle;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoaderAware;
@DomainService(nature = NatureOfService.DOMAIN)
public class DomainObjectContainerDefault
- implements DomainObjectContainer,
- PersistenceSessionServiceAware, SpecificationLoaderAware,
- AdapterManagerAware, ExceptionRecognizer {
+ implements DomainObjectContainer, PersistenceSessionServiceAware, AdapterManagerAware, ExceptionRecognizer {
//region > titleOf
@@ -109,7 +107,7 @@ public class DomainObjectContainerDefault
@SuppressWarnings("unchecked")
@Override
public <T> T newViewModelInstance(Class<T> ofClass, String memento) {
- final ObjectSpecification spec = getSpecificationLoader().loadSpecification(ofClass);
+ final ObjectSpecification spec = specificationLoader.loadSpecification(ofClass);
if (!spec.containsFacet(ViewModelFacet.class)) {
throw new IsisException("Type must be a ViewModel: " + ofClass);
}
@@ -652,20 +650,9 @@ public class DomainObjectContainerDefault
//region > framework dependencies
private PersistenceSessionService persistenceSessionService;
- private SpecificationLoader specificationLoader;
private AdapterManager adapterManager;
- protected SpecificationLoader getSpecificationLoader() {
- return specificationLoader;
- }
-
- @Programmatic
- @Override
- public void setSpecificationLoader(final SpecificationLoader specificationLoader) {
- this.specificationLoader = specificationLoader;
- }
-
protected AdapterManager getAdapterManager() {
return adapterManager;
@@ -693,31 +680,34 @@ public class DomainObjectContainerDefault
//region > service dependencies
- @javax.inject.Inject
+ @Inject
+ SpecificationLoader specificationLoader;
+
+ @Inject
org.apache.isis.applib.services.config.ConfigurationService configurationService;
- @javax.inject.Inject
+ @Inject
FactoryService factoryService;
- @javax.inject.Inject
+ @Inject
MessageService messageService;
- @javax.inject.Inject
+ @Inject
RepositoryService repositoryService;
- @javax.inject.Inject
+ @Inject
ServiceRegistry serviceRegistry;
- @javax.inject.Inject
+ @Inject
TransactionService transactionService;
- @javax.inject.Inject
+ @Inject
TitleService titleService;
- @javax.inject.Inject
+ @Inject
UserService userService;
- @javax.inject.Inject
+ @Inject
WrapperFactory wrapperFactory;
//endregion
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/factory/FactoryServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/factory/FactoryServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/factory/FactoryServiceDefault.java
index ebdda4f..a72d43e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/factory/FactoryServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/factory/FactoryServiceDefault.java
@@ -36,21 +36,18 @@ import org.apache.isis.core.metamodel.runtimecontext.PersistenceSessionService;
import org.apache.isis.core.metamodel.runtimecontext.PersistenceSessionServiceAware;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoaderAware;
@DomainService(
nature = NatureOfService.DOMAIN
)
-public class FactoryServiceDefault
- implements FactoryService,
- PersistenceSessionServiceAware, SpecificationLoaderAware {
+public class FactoryServiceDefault implements FactoryService, PersistenceSessionServiceAware {
@Programmatic
@Override
@SuppressWarnings("unchecked")
public <T> T instantiate(final Class<T> domainClass) {
- final ObjectSpecification spec = specificationLookup.loadSpecification(domainClass);
+ final ObjectSpecification spec = specificationLoader.loadSpecification(domainClass);
final ObjectAdapter adapter = doCreateTransientInstance(spec);
return (T) adapter.getObject();
}
@@ -67,7 +64,7 @@ public class FactoryServiceDefault
@Programmatic
@Override
public <T> T mixin(final Class<T> mixinClass, final Object mixedIn) {
- final ObjectSpecification objectSpec = specificationLookup.loadSpecification(mixinClass);
+ final ObjectSpecification objectSpec = specificationLoader.loadSpecification(mixinClass);
final MixinFacet mixinFacet = objectSpec.getFacet(MixinFacet.class);
if(mixinFacet == null) {
throw new NonRecoverableException("Class '" + mixinClass.getName() + " is not a mixin");
@@ -94,6 +91,9 @@ public class FactoryServiceDefault
}
@Inject
+ SpecificationLoader specificationLoader;
+
+ @Inject
ServiceRegistry serviceRegistry;
private PersistenceSessionService persistenceSessionService;
@@ -103,9 +103,5 @@ public class FactoryServiceDefault
this.persistenceSessionService = persistenceSessionService;
}
- private SpecificationLoader specificationLookup;
- @Override
- public void setSpecificationLoader(final SpecificationLoader specificationLookup) {
- this.specificationLookup = specificationLookup;
- }
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
index 7904ea9..8ffb99a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
@@ -104,17 +104,15 @@ import org.apache.isis.core.metamodel.facets.properties.propertylayout.NamedFace
import org.apache.isis.core.metamodel.facets.properties.propertylayout.RenderedAdjustedFacetForPropertyXml;
import org.apache.isis.core.metamodel.facets.properties.propertylayout.TypicalLengthFacetForPropertyXml;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoaderAware;
import org.apache.isis.core.metamodel.spec.feature.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-public abstract class GridSystemServiceAbstract<G extends Grid>
- implements GridSystemService<G>, SpecificationLoaderAware {
+public abstract class GridSystemServiceAbstract<G extends Grid> implements GridSystemService<G> {
private static final Logger LOG = LoggerFactory.getLogger(GridSystemServiceAbstract.class);
@@ -203,7 +201,7 @@ public abstract class GridSystemServiceAbstract<G extends Grid>
final Class<?> domainClass) {
- final ObjectSpecification objectSpec = specificationLookup.loadSpecification(domainClass);
+ final ObjectSpecification objectSpec = specificationLoader.loadSpecification(domainClass);
final Map<String, OneToOneAssociation> oneToOneAssociationById =
ObjectMember.Util.mapById(getOneToOneAssociations(objectSpec));
@@ -398,7 +396,7 @@ public abstract class GridSystemServiceAbstract<G extends Grid>
public void complete(final G grid, final Class<?> domainClass) {
normalize(grid, domainClass);
- final ObjectSpecification objectSpec = specificationLookup.loadSpecification(domainClass);
+ final ObjectSpecification objectSpec = specificationLoader.loadSpecification(domainClass);
grid.visit(new Grid.VisitorAdapter() {
@@ -680,11 +678,8 @@ public abstract class GridSystemServiceAbstract<G extends Grid>
// //////////////////////////////////////
- protected SpecificationLoader specificationLookup;
-
- public void setSpecificationLoader(final SpecificationLoader specificationLookup) {
- this.specificationLookup = specificationLookup;
- }
+ @Inject
+ protected SpecificationLoader specificationLoader;
@Inject
protected TranslationService translationService;
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
index 1d51fff..133cad6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBS3.java
@@ -85,7 +85,7 @@ public class GridSystemServiceBS3 extends GridSystemServiceAbstract<BS3Grid> {
public Grid defaultGrid(final Class<?> domainClass) {
final BS3Grid bs3Grid = new BS3Grid();
- final ObjectSpecification objectSpec = specificationLookup.loadSpecification(domainClass);
+ final ObjectSpecification objectSpec = specificationLoader.loadSpecification(domainClass);
bs3Grid.setDomainClass(domainClass);
final BS3Row headerRow = new BS3Row();
@@ -167,7 +167,7 @@ public class GridSystemServiceBS3 extends GridSystemServiceAbstract<BS3Grid> {
final Class<?> domainClass) {
- final ObjectSpecification objectSpec = specificationLookup.loadSpecification(domainClass);
+ final ObjectSpecification objectSpec = specificationLoader.loadSpecification(domainClass);
final Map<String, OneToOneAssociation> oneToOneAssociationById =
ObjectMember.Util.mapById(getOneToOneAssociations(objectSpec));
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/LayoutServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/LayoutServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/LayoutServiceDefault.java
index 89dd2c9..c7ba107 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/LayoutServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/LayoutServiceDefault.java
@@ -46,13 +46,12 @@ import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoaderAware;
import org.apache.isis.objectstore.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
@DomainService(
nature = NatureOfService.DOMAIN
)
-public class LayoutServiceDefault implements LayoutService, SpecificationLoaderAware {
+public class LayoutServiceDefault implements LayoutService {
private static final Logger LOG = LoggerFactory.getLogger(LayoutServiceDefault.class);
@@ -69,7 +68,7 @@ public class LayoutServiceDefault implements LayoutService, SpecificationLoaderA
protected Grid toGrid(final Class<?> domainClass, final Style style) {
if (style == Style.CURRENT) {
- final ObjectSpecification objectSpec = specificationLookup.loadSpecification(domainClass);
+ final ObjectSpecification objectSpec = specificationLoader.loadSpecification(domainClass);
final GridFacet facet = objectSpec.getFacet(GridFacet.class);
return facet != null? facet.getGrid(): null;
}
@@ -95,7 +94,7 @@ public class LayoutServiceDefault implements LayoutService, SpecificationLoaderA
@Programmatic
public byte[] toZip(final Style style) {
- final Collection<ObjectSpecification> allSpecs = specificationLookup.allSpecifications();
+ final Collection<ObjectSpecification> allSpecs = specificationLoader.allSpecifications();
final Collection<ObjectSpecification> domainObjectSpecs = Collections2
.filter(allSpecs, new Predicate<ObjectSpecification>(){
@Override
@@ -138,18 +137,10 @@ public class LayoutServiceDefault implements LayoutService, SpecificationLoaderA
}
- ////////////////////////////////////////////////////////
- //region > injected dependencies
-
- private SpecificationLoader specificationLookup;
-
- @Override
- public void setSpecificationLoader(final SpecificationLoader specificationLookup) {
- this.specificationLookup = specificationLookup;
- }
-
+ @Inject
+ SpecificationLoader specificationLoader;
@Inject
JaxbService jaxbService;
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
index 060fd07..6c1a23e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
@@ -40,18 +40,17 @@ import org.apache.isis.applib.services.metamodel.MetaModelService2;
import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
import org.apache.isis.core.metamodel.spec.ObjectSpecId;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoaderAware;
import org.apache.isis.core.metamodel.spec.feature.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
@DomainService(
nature = NatureOfService.DOMAIN
)
-public class MetaModelServiceDefault implements MetaModelService2, SpecificationLoaderAware {
+public class MetaModelServiceDefault implements MetaModelService2 {
@SuppressWarnings("unused")
private final static Logger LOG = LoggerFactory.getLogger(MetaModelServiceDefault.class);
@@ -198,14 +197,11 @@ public class MetaModelServiceDefault implements MetaModelService2, Specification
return sortOf(domainType);
}
- // //////////////////////////////////////
- private SpecificationLoader specificationLookup;
- @Override
- public void setSpecificationLoader(final SpecificationLoader specificationLookup) {
- this.specificationLookup = specificationLookup;
- }
+
+ @Inject
+ SpecificationLoader specificationLookup;
@Inject
GridService gridService;
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
index 2f5dc95..50511f8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
@@ -19,19 +19,20 @@
package org.apache.isis.core.metamodel.services.registry;
+import java.util.List;
+
import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.NatureOfService;
import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.registry.ServiceRegistry;
+import org.apache.isis.applib.services.registry.ServiceRegistry2;
import org.apache.isis.applib.services.wrapper.WrapperFactory;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.metamodel.services.ServicesInjectorAware;
@DomainService(
nature = NatureOfService.DOMAIN
)
-public class ServiceRegistryDefault
- implements ServiceRegistry, ServicesInjectorAware {
+public class ServiceRegistryDefault implements ServiceRegistry2, ServicesInjectorAware {
@Programmatic
@@ -53,6 +54,11 @@ public class ServiceRegistryDefault
return servicesInjector.lookupServices(service);
}
+ @Programmatic
+ @Override
+ public List<Object> getRegisteredServices() {
+ return servicesInjector.getRegisteredServices();
+ }
private Object unwrapped(Object domainObject) {
return wrapperFactory != null ? wrapperFactory.unwrap(domainObject) : domainObject;
@@ -66,7 +72,7 @@ public class ServiceRegistryDefault
private ServicesInjector servicesInjector;
@Override
public void setServicesInjector(final ServicesInjector servicesInjector) {
-
this.servicesInjector = servicesInjector;
}
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
index 15dc64b..2bde668 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
@@ -21,6 +21,7 @@ package org.apache.isis.core.metamodel.services.swagger;
import java.util.Map;
import javax.annotation.PostConstruct;
+import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,12 +32,11 @@ import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.services.swagger.SwaggerService;
import org.apache.isis.core.metamodel.services.swagger.internal.SwaggerSpecGenerator;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoaderAware;
@DomainService(
nature = NatureOfService.DOMAIN
)
-public class SwaggerServiceDefault implements SwaggerService, SpecificationLoaderAware {
+public class SwaggerServiceDefault implements SwaggerService {
@SuppressWarnings("unused")
private final static Logger LOG = LoggerFactory.getLogger(SwaggerServiceDefault.class);
@@ -70,14 +70,8 @@ public class SwaggerServiceDefault implements SwaggerService, SpecificationLoade
return swaggerSpec;
}
- //region > injected dependencies
- private SpecificationLoader specificationLoader;
- @Override
- public void setSpecificationLoader(final SpecificationLoader specificationLookup) {
- this.specificationLoader = specificationLookup;
- }
-
- //endregion
+ @Inject
+ SpecificationLoader specificationLoader;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecificationDependencies.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecificationDependencies.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecificationDependencies.java
index 40275f3..bc2211f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecificationDependencies.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecificationDependencies.java
@@ -17,7 +17,7 @@
package org.apache.isis.core.metamodel.spec;
import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.core.metamodel.specloader.facetprocessor.FacetProcessor;
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberDependencies.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberDependencies.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberDependencies.java
index 47d4223..178cf50 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberDependencies.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberDependencies.java
@@ -17,7 +17,7 @@
package org.apache.isis.core.metamodel.spec.feature;
import org.apache.isis.core.metamodel.runtimecontext.PersistenceSessionService;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
public class ObjectMemberDependencies {
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
index f16375a..a92cf0a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
@@ -32,9 +32,9 @@ import org.slf4j.LoggerFactory;
import org.apache.isis.applib.AppManifest;
import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.core.commons.components.ApplicationScopedComponent;
import org.apache.isis.core.commons.config.IsisConfiguration;
-import org.apache.isis.core.commons.config.IsisConfigurationDefault;
import org.apache.isis.core.commons.ensure.Assert;
import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.commons.lang.ClassUtil;
@@ -46,13 +46,11 @@ import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFac
import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
-import org.apache.isis.core.metamodel.runtimecontext.ConfigurationServiceInternal;
import org.apache.isis.core.metamodel.runtimecontext.PersistenceSessionService;
import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
import org.apache.isis.core.metamodel.runtimecontext.noruntime.RuntimeContextNoRuntime;
-import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.metamodel.services.ServicesInjectorAware;
import org.apache.isis.core.metamodel.spec.FreeStandingList;
import org.apache.isis.core.metamodel.spec.ObjectSpecId;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
@@ -89,6 +87,7 @@ import static org.hamcrest.Matchers.notNullValue;
* conjunction with some <tt>PersistenceMechanism</tt>s that do class
* enhancement.
* </ul>
+ * </p>
*
* <p>
* In addition, the {@link RuntimeContext} can optionally be injected, but will
@@ -101,7 +100,14 @@ import static org.hamcrest.Matchers.notNullValue;
* framework (that is, when there <i>is</i> a runtime), then the framework
* injects an implementation of {@link RuntimeContext} that acts like a bridge
* to its <tt>IsisContext</tt>.
- */
+ * </p>
+ *
+ * <p>
+ * Implementing class is added to {@link ServicesInjector} as an (internal) domain service; all public methods
+ * must be annotated using {@link Programmatic}.
+ * </p>
+ *
+*/
public class SpecificationLoader implements ApplicationScopedComponent {
private final static Logger LOG = LoggerFactory.getLogger(SpecificationLoader.class);
@@ -113,7 +119,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
private final ProgrammingModel programmingModel;
private final FacetProcessor facetProcessor;
- private final ServicesInjectorSpi servicesInjector;
+ private final ServicesInjector servicesInjector;
private final MetaModelValidator metaModelValidator;
private final SpecificationCacheDefault cache = new SpecificationCacheDefault();
@@ -125,7 +131,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
final ProgrammingModel programmingModel,
final MetaModelValidator metaModelValidator,
final List<LayoutMetadataReader> layoutMetadataReaders,
- final ServicesInjectorSpi servicesInjector) {
+ final ServicesInjector servicesInjector) {
ensureThatArg(deploymentCategory, is(notNullValue()));
ensureThatArg(configuration, is(notNullValue()));
@@ -140,8 +146,8 @@ public class SpecificationLoader implements ApplicationScopedComponent {
this.programmingModel = programmingModel;
-
this.metaModelValidator = metaModelValidator;
+
this.facetProcessor = new FacetProcessor(configuration, programmingModel);
this.layoutMetadataReaders = layoutMetadataReaders;
}
@@ -170,9 +176,10 @@ public class SpecificationLoader implements ApplicationScopedComponent {
/**
* Initializes and wires up, and primes the cache based on any service
- * classes (provided by the {@link ServicesInjectorSpi}).
+ * classes (provided by the {@link ServicesInjector}).
* @param runtimeContext
*/
+ @Programmatic
public void init(final RuntimeContext runtimeContext) {
this.runtimeContext = runtimeContext;
@@ -182,13 +189,9 @@ public class SpecificationLoader implements ApplicationScopedComponent {
// default subcomponents
if (runtimeContext == null) {
- servicesInjector.addFallbackIfRequired(
- ConfigurationServiceInternal.class, new IsisConfigurationDefault(null));
this.runtimeContext = new RuntimeContextNoRuntime(servicesInjector, this);
}
- injectInto(metaModelValidator);
-
// wire subcomponents into each other
this.runtimeContext.injectInto(facetProcessor);
for (final LayoutMetadataReader layoutMetadataReader : layoutMetadataReaders) {
@@ -198,7 +201,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
// initialize subcomponents
programmingModel.init();
facetProcessor.init();
- metaModelValidator.init();
+ metaModelValidator.init(this);
loadSpecificationsForServices();
loadSpecificationsForMixins();
@@ -240,6 +243,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
cache.setCacheBySpecId(specById);
}
+ @Programmatic
public boolean isInitialized() {
return initialized;
}
@@ -248,6 +252,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
/**
* Set using {@link #init(RuntimeContext)}.
*/
+ @Programmatic
public RuntimeContext getRuntimeContext() {
return runtimeContext;
}
@@ -256,6 +261,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
//region > shutdown
+ @Programmatic
public void shutdown() {
LOG.info("shutting down " + this);
@@ -268,6 +274,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
//region > invalidateCache
+ @Programmatic
public void invalidateCache(final Class<?> cls) {
if(!cache.isInitialized()) {
@@ -305,6 +312,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
private ValidationFailures validationFailures;
+ @Programmatic
public void validateAndAssert() {
ValidationFailures validationFailures = validate();
validationFailures.assertNone();
@@ -312,6 +320,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
cacheBySpecId();
}
+ @Programmatic
public ValidationFailures validate() {
if(validationFailures == null) {
validationFailures = new ValidationFailures();
@@ -333,6 +342,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
* the configured {@link org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor}
* has filtered out the class.
*/
+ @Programmatic
public ObjectSpecification loadSpecification(final String className) {
ensureThatArg(className, is(notNullValue()), "specification class name must be specified");
@@ -351,6 +361,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
/**
* @see #loadSpecification(String)
*/
+ @Programmatic
public ObjectSpecification loadSpecification(final Class<?> type) {
final ObjectSpecification spec = internalLoadSpecification(type);
if(spec == null) {
@@ -410,6 +421,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
* Loads the specifications of the specified types except the one specified
* (to prevent an infinite loop).
*/
+ @Programmatic
public boolean loadSpecifications(final List<Class<?>> typesToLoad, final Class<?> typeToIgnore) {
boolean anyLoadedAsNull = false;
for (final Class<?> typeToLoad : typesToLoad) {
@@ -425,6 +437,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
/**
* Loads the specifications of the specified types.
*/
+ @Programmatic
public boolean loadSpecifications(final List<Class<?>> typesToLoad) {
return loadSpecifications(typesToLoad, null);
}
@@ -504,6 +517,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
/**
* Return all the loaded specifications.
*/
+ @Programmatic
public Collection<ObjectSpecification> allSpecifications() {
return cache.allSpecifications();
}
@@ -512,6 +526,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
//region > getServiceClasses, isServiceClass
+ @Programmatic
public List<Class<?>> allServiceClasses() {
List<Class<?>> serviceClasses = Lists
.transform(this.servicesInjector.getRegisteredServices(), new Function<Object, Class<?>>(){
@@ -523,6 +538,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
return Collections.unmodifiableList(Lists.newArrayList(serviceClasses));
}
+ @Programmatic
public boolean isServiceClass(Class<?> cls) {
return this.servicesInjector.isRegisteredService(cls);
}
@@ -533,6 +549,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
/**
* Whether this class has been loaded.
*/
+ @Programmatic
public boolean loaded(final Class<?> cls) {
return loaded(cls.getName());
}
@@ -540,6 +557,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
/**
* @see #loaded(Class).
*/
+ @Programmatic
public boolean loaded(final String fullyQualifiedClassName) {
return cache.get(fullyQualifiedClassName) != null;
}
@@ -547,6 +565,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
//endregion
//region > lookupBySpecId
+ @Programmatic
public ObjectSpecification lookupBySpecId(ObjectSpecId objectSpecId) {
final ObjectSpecification objectSpecification = cache.getByObjectType(objectSpecId);
if(objectSpecification == null) {
@@ -563,16 +582,9 @@ public class SpecificationLoader implements ApplicationScopedComponent {
* Injects self into candidate if required, and instructs its subcomponents
* to do so also.
*/
+ @Programmatic
public void injectInto(final Object candidate) {
final Class<?> candidateClass = candidate.getClass();
- if (SpecificationLoaderAware.class.isAssignableFrom(candidateClass)) {
- final SpecificationLoaderAware cast = SpecificationLoaderAware.class.cast(candidate);
- cast.setSpecificationLoader(this);
- }
- if (SpecificationLoaderAware.class.isAssignableFrom(candidateClass)) {
- final SpecificationLoaderAware cast = SpecificationLoaderAware.class.cast(candidate);
- cast.setSpecificationLoader(this);
- }
if (ServicesInjectorAware.class.isAssignableFrom(candidateClass)) {
final ServicesInjectorAware cast = ServicesInjectorAware.class.cast(candidate);
cast.setServicesInjector(this.servicesInjector);
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderAware.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderAware.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderAware.java
deleted file mode 100644
index 8f60a85..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderAware.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.isis.core.metamodel.specloader;
-
-import org.apache.isis.applib.annotation.Programmatic;
-
-public interface SpecificationLoaderAware {
-
- @Programmatic
- public void setSpecificationLoader(final SpecificationLoader specificationLookup);
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderInstaller.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderInstaller.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderInstaller.java
index cd6a86c..60a4f08 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderInstaller.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderInstaller.java
@@ -20,21 +20,22 @@
package org.apache.isis.core.metamodel.specloader;
import java.util.Collection;
+
import org.apache.isis.core.commons.components.Installer;
import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
-import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
/**
* Installs a {@link SpecificationLoader} during system start up.
*/
public interface SpecificationLoaderInstaller extends Installer {
- static String TYPE = "reflector";
+ String TYPE = "reflector";
SpecificationLoader createReflector(
final DeploymentCategory deploymentCategory,
final Collection<MetaModelRefiner> metaModelRefiners,
- final ServicesInjectorSpi servicesInjector);
+ final ServicesInjector servicesInjector);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/6e3495f4/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
index 3306a6e..bb77b40 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
@@ -55,7 +55,7 @@ import org.apache.isis.core.metamodel.interactions.InteractionUtils;
import org.apache.isis.core.metamodel.interactions.UsabilityContext;
import org.apache.isis.core.metamodel.interactions.VisibilityContext;
import org.apache.isis.core.metamodel.runtimecontext.PersistenceSessionService;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
import org.apache.isis.core.metamodel.services.command.CommandDtoServiceInternal;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;