/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.reflect;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import org.whole.lang.bindings.IBindingManager;
import org.whole.lang.builders.IBuilderFactory;
import org.whole.lang.codebase.ClasspathPersistenceProvider;
import org.whole.lang.codebase.DataTypePersistenceKit;
import org.whole.lang.codebase.IPersistenceKit;
import org.whole.lang.codebase.IPersistenceProvider;
import org.whole.lang.codebase.ObjectPersistenceKit;
import org.whole.lang.codebase.PrettyPrintPersistenceKit;
import org.whole.lang.contexts.EntityContext;
import org.whole.lang.contexts.IEntityContext;
import org.whole.lang.events.IChangeEventHandler;
import org.whole.lang.iterators.IEntityIterator;
import org.whole.lang.iterators.IteratorFactory;
import org.whole.lang.lifecycle.IHistoryManager;
import org.whole.lang.lifecycle.ITransaction;
import org.whole.lang.model.IEntity;
import org.whole.lang.model.IFragmentModel;
import org.whole.lang.model.InternalIEntity;
import org.whole.lang.model.NullFragmentModel;
import org.whole.lang.operations.MetaModelMapperOperation;
import org.whole.lang.resources.IResourceRegistry;
import org.whole.lang.resources.LanguageKitResourceFactory;
import org.whole.lang.resources.ResourceRegistry;
import org.whole.lang.templates.ITemplateFactory;
import org.whole.lang.templates.ResourceTemplateFactory;
import org.whole.lang.util.EntityUtils;
import org.whole.lang.util.ResourceUtils;
import org.whole.lang.visitors.IVisitorFactory;
/**
* @author Riccardo Solmi
*/
public class ReflectionFactory {
private static ClassLoader platformClassLoader;
private static IResourceRegistry<ILanguageKit> languageKitRegistry;
static {
languageKitRegistry = ResourceRegistry.getRegistry(ILanguageKit.class.getName());
languageKitRegistry.getResourceFactoryRegistry().setDefaultResourceFactory(
new LanguageKitResourceFactory(languageKitRegistry.getResourceFactoryRegistry()));
}
private static SortedSet<IEditorKit> editorKitsSet = new TreeSet<IEditorKit>();
private static Map<String, IEditorKit> editorKitsMap = new TreeMap<String, IEditorKit>();
private static IPersistenceKit defaultPersistenceKit;
private static Map<String, IPersistenceKit> editorIdPersistenceKitMap = new HashMap<String, IPersistenceKit>();
private static Map<IPersistenceKit, List<String>> persistenceKitEditorIdMap = new HashMap<IPersistenceKit, List<String>>();
private static Map<String, IPersistenceKit> persistenceKitsMap = new TreeMap<String, IPersistenceKit>();
private static SortedSet<IPersistenceKit> persistenceKits = new TreeSet<IPersistenceKit>();
private static final ReflectionFactory instance = new ReflectionFactory();
protected ReflectionFactory() {
//workaround for Android compatibility
//was addPersistenceKit("org.whole.lang.XmlBeansEditor", BeansPersistenceKit.instance());
try {
Class<?> clazz = Class.forName("org.whole.lang.codebase.BeansPersistenceKit", true, getClass().getClassLoader());
Method method = clazz.getMethod("instance", new Class[0]);
addPersistenceKit("org.whole.lang.XmlBeansEditor", (IPersistenceKit) method.invoke(null, new Object[0]));
} catch (Exception e) {
}
addPersistenceKit("org.whole.lang.ObjectEditor", ObjectPersistenceKit.instance());
addPersistenceKit("org.whole.lang.DataTypeEditor", DataTypePersistenceKit.instance());
persistenceKitsMap.put(PrettyPrintPersistenceKit.instance().getId(), PrettyPrintPersistenceKit.instance());
}
public static void deploy(String deployerClassName) {
deploy(ReflectionFactory.<IDeployer> instantiateClass(deployerClassName));
}
public static void deploy(Class<? extends IDeployer> deployerClass) {
deploy(instantiateClass(deployerClass));
}
public static void deploy(IDeployer deployer) {
deployer.deploy(ReflectionFactory.instance);
}
public static void undeploy(String deployerClassName) {
undeploy(ReflectionFactory.<IDeployer> instantiateClass(deployerClassName));
}
public static void undeploy(Class<? extends IDeployer> deployerClass) {
undeploy(instantiateClass(deployerClass));
}
public static void undeploy(IDeployer deployer) {
deployer.undeploy(ReflectionFactory.instance);
}
private static WholePlatformDeployer wholePlatformDeployer = null;
public static synchronized void deployWholePlatform() {
if (wholePlatformDeployer == null) {
WholePlatformDeployer newWholePlatformDeployer = new WholePlatformDeployer();
deploy(newWholePlatformDeployer);
wholePlatformDeployer = newWholePlatformDeployer;
}
}
public static synchronized void undeployWholePlatform() {
if (wholePlatformDeployer != null) {
undeploy(wholePlatformDeployer);
wholePlatformDeployer = null;
}
}
private static synchronized void resetWholePlatformDeployer() {
wholePlatformDeployer = null;
}
public static class WholePlatformDeployer extends AbstractSafeSuiteDeployer {
public int getDeployLevel() {
return IDeployer.LEVEL_LANGUAGE;
}
public WholePlatformDeployer() {
super(
"org.whole.lang.commons.reflect.CommonsLanguageDeployer",
"org.whole.langs.core.CoreLanguagesDeployer",
"org.whole.langs.legacy.LegacyLanguagesDeployer",
"org.whole.langs.db.DBLanguagesDeployer",
"org.whole.langs.core.CoreDynamicLanguagesDeployer",
"org.whole.langs.legacy.LegacyDynamicLanguagesDeployer",
"org.whole.langs.core.op.WorkflowsInterpreterDeployer",
"org.whole.langs.core.op.CoreOperationsDeployer",
"org.whole.langs.legacy.op.LegacyOperationsDeployer",
"org.whole.langs.core.CoreMetaModelsDeployer",
"org.whole.langs.legacy.LegacyMetaModelsDeployer",
"org.whole.langs.db.op.DBContributionsDeployer",
"org.whole.langs.core.op.CoreContributionsDeployer"
);
}
}
public static final String CLASS_LOADER_VAR = "classLoader";
public static ClassLoader getClassLoader(IBindingManager bm) {
return bm.wIsSet(CLASS_LOADER_VAR) ? (ClassLoader) bm.wGetValue(CLASS_LOADER_VAR) : getPlatformClassLoader();
}
public static ClassLoader setClassLoader(IBindingManager bm, ClassLoader cl) {
ClassLoader oldCL = getClassLoader(bm);
bm.wDefValue(CLASS_LOADER_VAR, cl);
return oldCL;
}
public static ClassLoader getPlatformClassLoader() {
if (platformClassLoader == null)
platformClassLoader = ReflectionFactory.instance.getClass().getClassLoader();
return platformClassLoader;
}
public static void setUserClassLoader(ClassLoader classLoader) {
try {
Class<?> rfClass = Class.forName(ReflectionFactory.instance.getClass().getName(), true, classLoader);
if (rfClass != ReflectionFactory.instance.getClass())
throw new IllegalArgumentException("Inconsistent class loaders hierarchy");
platformClassLoader = classLoader;
} catch (ClassNotFoundException e) {
platformClassLoader = new OrderedClassLoader(getPlatformClassLoader(), classLoader);
}
}
public static class OrderedClassLoader extends ClassLoader {
private ClassLoader userClassLoader;
public OrderedClassLoader(ClassLoader platformClassLoader, ClassLoader userClassLoader) {
super(platformClassLoader);
setUserClassLoader(userClassLoader);
}
public void setUserClassLoader(ClassLoader userClassLoader) {
this.userClassLoader = userClassLoader;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
return super.findClass(name);
} catch (ClassNotFoundException e) {
return userClassLoader.loadClass(name);
}
}
}
@SuppressWarnings("unchecked")
public static <T> T instantiateClass(String className) {
try {
return instantiateClass((Class<T>) Class.forName(className, true, getPlatformClassLoader()));
} catch (ClassNotFoundException e) {
throw new DeployerException(e);
}
}
public static <T> T instantiateClass(Class<T> clazz) {
try {
return clazz.newInstance();
} catch (Exception e) {
throw new DeployerException(e);
}
}
public synchronized void addLanguageKit(ILanguageKit languageKit) {
if (!languageKitRegistry.addResource(languageKit, false))
resetWholePlatformDeployer();
updatePersistenceAndEditorKits(languageKit);
}
public static void updatePersistenceAndEditorKits(ILanguageKit languageKit) {
InternalILanguageKit internalILanguageKit = (InternalILanguageKit) languageKit;
for (IPersistenceKit persistenceKit : getPersistenceKits())
if (persistenceKit.canApply(languageKit))
internalILanguageKit.addPersistenceKit(persistenceKit);
else
internalILanguageKit.removePersistenceKit(persistenceKit);
for (IEditorKit editorKit : getEditorKits())
if (editorKit.canApply(languageKit))
internalILanguageKit.addEditorKit(editorKit);
else
internalILanguageKit.removeEditorKit(editorKit);
}
public synchronized void removeLanguageKit(String languageURI) {
if (languageKitRegistry.removeResource(languageURI))
resetWholePlatformDeployer();
}
public static IResourceRegistry<ILanguageKit> getLanguageKitRegistry() {
return languageKitRegistry;
}
public static Collection<ILanguageKit> getLanguageKits(boolean includeHidden) {
return languageKitRegistry.getResources(includeHidden);
}
public static SortedSet<ILanguageKit> getLanguageKits(boolean includeHidden, Comparator<? super ILanguageKit> comparator) {
return languageKitRegistry.getResources(includeHidden, comparator);
}
public static IEntityIterator<IEntity> languageKitsIterator() {
return IteratorFactory.javaCollectionIterator(getLanguageKits(false, ResourceUtils.SIMPLE_COMPARATOR));
}
public static IEntityIterator<IEntity> entityDescriptorIterator(ILanguageKit languageKit) {
if (languageKit == null)
return IteratorFactory.emptyIterator();
else
return IteratorFactory.javaCollectionIterator(languageKit.getEntityDescriptorEnum());
}
public static EntityDescriptor<?> firstEntityDescriptor(ILanguageKit languageKit, String optName, boolean excludeAbstract) {
EntityDescriptorEnum edEnum = languageKit.getEntityDescriptorEnum();
EntityDescriptor<?> ed = null;
if (optName != null && optName.length() > 0)
ed = edEnum.valueOf(optName);
if (ed == null || (ed.isAbstract() && excludeAbstract)) {
if (excludeAbstract) {
Iterator<EntityDescriptor<?>> iterator = edEnum.values().iterator();
EntityDescriptor<?> nextED;
while (ed == null && iterator.hasNext())
if (!(nextED = iterator.next()).isAbstract())
ed = nextED;
} else
ed = edEnum.valueOf(0);
}
return ed;
}
@Deprecated
public static boolean hasLanguageKit(String languageURI) {
return hasLanguageKit(languageURI, true, null);
}
public static boolean hasLanguageKit(String languageURI, boolean loadOnDemand, String contextURI) {
return languageKitRegistry.containsResource(languageURI, loadOnDemand, contextURI) ||
languageRequestHandler.containsLanguage(languageURI);
}
@Deprecated
public static ILanguageKit getLanguageKit(String languageURI) {
return getLanguageKit(languageURI, true, null);
}
public static ILanguageKit getLanguageKit(String languageURI, boolean loadOnDemand, String contextURI) {
ILanguageKit languageKit = languageKitRegistry.getResource(languageURI, loadOnDemand, contextURI);
if (languageKit == null)
try {
if (languageRequestHandler.deployLanguage(languageURI))
languageKit = languageKitRegistry.getResource(languageURI, false, contextURI);
} catch (Exception e) {
throw new IllegalArgumentException("The Language: "+languageURI+" is not deployed.", e);
}
if (languageKit == null)
throw new IllegalArgumentException("The Language: "+languageURI+" is not deployed.");
return languageKit;
}
public static ILanguageKit safeGetLanguageKit(String languageURI, boolean loadOnDemand, String contextURI) {
return languageURI != null && hasLanguageKit(languageURI, loadOnDemand, contextURI) ?
getLanguageKit(languageURI, loadOnDemand, contextURI) : null;
}
public static ILanguageKit getLanguageKit(IEntity entity) {
return entity.wGetEntityDescriptor().getLanguageKit();
}
public static IEditorKit getEditorKit(IEntity entity) {
if (entity.wIsAdapter() && EntityUtils.hasParent(entity))
return entity.wGetParent().wGetEditorKit();
else
return entity.wGetEditorKit();
}
private static ILanguageRequestHandler languageRequestHandler = NullLanguageRequestHandler.instance;
public static ILanguageRequestHandler getLanguageRequestHandler() {
return languageRequestHandler;
}
public static void addLanguageRequestHandler(ILanguageRequestHandler handler) {
if (languageRequestHandler.getPriority() < handler.getPriority()) {
handler.addLanguageRequestHandler(languageRequestHandler);
languageRequestHandler = handler;
} else if (languageRequestHandler != handler)
languageRequestHandler.addLanguageRequestHandler(handler);
}
public static void removeLanguageRequestHandler(ILanguageRequestHandler handler) {
if (handler != languageRequestHandler)
languageRequestHandler.removeLanguageRequestHandler(handler);
else
languageRequestHandler = languageRequestHandler.removeLanguageRequestHandler(handler);
}
public void addReactionsHandler(String languageURI, IChangeEventHandler reactionsHandler) {
ILanguageKit languageKit = getLanguageKit(languageURI, false, null);
languageKit.addReactionsHandler(reactionsHandler);
}
public void addOperationFactory(String languageURI, String operationId, IVisitorFactory visitorFactory) {
ILanguageKit languageKit = getLanguageKit(languageURI, false, null);
languageKit.addVisitorFactory(operationId, visitorFactory);
}
public void addOperationFactory(String languageURI, String operationId, IBuilderFactory builderFactory) {
ILanguageKit languageKit = getLanguageKit(languageURI, false, null);
languageKit.addBuilderFactory(operationId, builderFactory);
}
public void addEditorKit(String editorId) {
IEditorKit editorKit = instantiateClass(editorId);
addEditorKit(editorKit);
}
public void addEditorKit(IEditorKit editorKit) {
if (editorKitsMap.containsKey(editorKit.getId()))
removeEditorKit(editorKit.getId());
editorKitsMap.put(editorKit.getId(), editorKit);
editorKitsSet.add(editorKit);
// update language kits
for (ILanguageKit languageKit : getLanguageKits(true))
if (editorKit.canApply(languageKit))
((InternalILanguageKit) languageKit).addEditorKit(editorKit);
}
public synchronized void removeEditorKit(String id) {
IEditorKit old = editorKitsMap.remove(id);
if (old != null) {
// fileExtensionEditorKitMap.remove(old.getFileExtension());
editorKitsSet.remove(old);
// update language kits
for (ILanguageKit languageKit : getLanguageKits(true))
if (old.canApply(languageKit))
((InternalILanguageKit) languageKit).removeEditorKit(old);
}
}
public static Collection<IEditorKit> getEditorKits() {
return Collections.unmodifiableCollection(editorKitsSet);
}
public static Collection<IEditorKit> getEditorKits(String languageURI) {
return getLanguageKit(languageURI).getEditorKits();
}
public static boolean hasEditorKit(String editorId) {
return editorKitsMap.containsKey(editorId);
}
public static IEditorKit getEditorKit(String editorId) {
IEditorKit editorKit = editorKitsMap.get(editorId);
if (editorKit == null)
throw new IllegalArgumentException("The Notation requested is not deployed: "+editorId);
return editorKit;
}
public static void addPersistenceKit(IPersistenceKit persistenceKit) {
if (persistenceKits.contains(persistenceKit))
persistenceKitEditorIdMap.put(persistenceKit, removePersistenceKit(persistenceKit));
if (persistenceKits.add(persistenceKit)) {
persistenceKitsMap.put(persistenceKit.getId(), persistenceKit);
// update language kits
for (ILanguageKit languageKit : getLanguageKits(true))
if (persistenceKit.canApply(languageKit))
((InternalILanguageKit) languageKit).addPersistenceKit(persistenceKit);
}
}
public static List<String> removePersistenceKit(IPersistenceKit persistenceKit) {
List<String> editorIds = null;
if (persistenceKits.remove(persistenceKit)) {
persistenceKitsMap.remove(persistenceKit.getId());
editorIds = persistenceKitEditorIdMap.remove(persistenceKit);
if (editorIds != null)
for (String editorId : editorIds)
editorIdPersistenceKitMap.remove(editorId);
// update language kits
for (ILanguageKit languageKit : getLanguageKits(true))
if (persistenceKit.canApply(languageKit))
((InternalILanguageKit) languageKit).removePersistenceKit(persistenceKit);
}
return editorIds;
}
public static SortedSet<IPersistenceKit> getPersistenceKits() {
return Collections.unmodifiableSortedSet(persistenceKits);
}
public void addPersistenceKit(String editorId, IPersistenceKit persistenceKit) {
addPersistenceKit(persistenceKit);
editorIdPersistenceKitMap.put(editorId, persistenceKit);
List<String> editorIds = persistenceKitEditorIdMap.get(persistenceKit);
if (editorIds == null)
persistenceKitEditorIdMap.put(persistenceKit, editorIds = new ArrayList<String>());
editorIds.add(editorId);
}
public static boolean hasPersistenceKit(String persistenceKitId) {
return persistenceKitsMap.containsKey(persistenceKitId);
}
public static IPersistenceKit getPersistenceKit(String persistenceKitId) {
IPersistenceKit persistenceKit = persistenceKitsMap.get(persistenceKitId);
if (persistenceKit == null)
throw new IllegalArgumentException("The Persistence requested is not deployed: "+persistenceKitId);
return persistenceKit;
}
public static List<String> getEditorIdsFromPersistenceKit(IPersistenceKit persistenceKit) {
return persistenceKitEditorIdMap.get(persistenceKit);
}
public static String getEditorIdFromPersistenceKit(IPersistenceKit persistenceKit) {
List<String> editorIds = getEditorIdsFromPersistenceKit(persistenceKit);
return editorIds.get(editorIds.size()-1);
}
public static boolean hasAssociatedPersistenceKit(String editorId) {
return editorIdPersistenceKitMap.containsKey(editorId);
}
public static IPersistenceKit getPersistenceKitFromEditorId(String editorId) {
IPersistenceKit kit = (IPersistenceKit) editorIdPersistenceKitMap.get(editorId);
if (kit == null)
return getDefaultPersistenceKit();
else
return kit;
}
public static IPersistenceKit getDefaultPersistenceKit() {
if (defaultPersistenceKit == null)
defaultPersistenceKit = ObjectPersistenceKit.instance();//BeansPersistenceKit.instance();//
return defaultPersistenceKit;
}
public static void setDefaultPersistenceKit(IPersistenceKit persistenceKit) {
defaultPersistenceKit = persistenceKit;
}
public static <E extends IEntity> E makeRootEntity(E entity) {
return makeRootEntity(entity, NullFragmentModel.instance);
}
public static <E extends IEntity> E makeRootEntity(E entity, IFragmentModel parentFragmentModel) {
IFragmentModel fragmentModel = getLanguageKit(entity).createFragmentModel();
if (parentFragmentModel != NullFragmentModel.instance)
fragmentModel.setCompoundModel(parentFragmentModel.getCompoundModel());
((InternalIEntity) entity).wSetModel(fragmentModel);
return entity;
}
public static IEntityContext newModelContext(IEntity entity) {
return new EntityContext(entity);
}
public void setMetaModelTemplate(String languageURI, String templateName, String resourceClasspath) {
setMetaModelTemplate(languageURI, templateName, new ClasspathPersistenceProvider(resourceClasspath));
}
public void setMetaModelTemplate(String languageURI, String templateName, IPersistenceProvider pp) {
ITemplateFactory<?> templateFactory = new ResourceTemplateFactory<IEntity>(pp);
setMetaModelTemplate(languageURI, templateFactory);
if (templateName != null)
getLanguageKit("http://lang.whole.org/Models", false, null).getTemplateManager().put(templateName, templateFactory);
}
public void setMetaModelTemplate(String languageURI, ITemplateFactory<?> metaModelTemplate) {
getLanguageKit(languageURI).setMetaModelTemplate(metaModelTemplate);
}
public void unsetMetaModelTemplate(String languageURI) {
setMetaModelTemplate(languageURI, (ITemplateFactory<?>) null);
}
public void setMetaModelTemplate(String languageURI, String metaModelTemplateClassName) {
setMetaModelTemplate(languageURI, ReflectionFactory.<ITemplateFactory<?>> instantiateClass(metaModelTemplateClassName));
}
public static IEntity getMetaModel(String languageURI) {
return getLanguageKit(languageURI).getMetaModel();
}
public static IEntity getMetaModel(IEntity entity) {
return getLanguageKit(entity).getMetaModel();
}
public static IEntity getMetaEntity(IEntity entity) {
return MetaModelMapperOperation.getMetaEntity(entity);
}
public static IHistoryManager getHistoryManager(IEntity entity) {
return entity.wGetModel().getCompoundModel().getHistoryManager();
}
public static ITransaction getTransaction(IEntity entity) {
return entity.wGetModel().getCompoundModel().getHistoryManager();
}
}