blob: 9e3bf2d48fda1b783ba4eabc11bf2131d1aaa89c [file] [log] [blame]
/*
* 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.polygene.runtime;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Stream;
import org.apache.polygene.api.PolygeneAPI;
import org.apache.polygene.api.association.AbstractAssociation;
import org.apache.polygene.api.association.Association;
import org.apache.polygene.api.association.AssociationDescriptor;
import org.apache.polygene.api.association.AssociationStateHolder;
import org.apache.polygene.api.association.AssociationWrapper;
import org.apache.polygene.api.association.ManyAssociation;
import org.apache.polygene.api.association.ManyAssociationWrapper;
import org.apache.polygene.api.association.NamedAssociation;
import org.apache.polygene.api.association.NamedAssociationWrapper;
import org.apache.polygene.api.composite.Composite;
import org.apache.polygene.api.composite.CompositeDescriptor;
import org.apache.polygene.api.composite.CompositeInstance;
import org.apache.polygene.api.composite.ModelDescriptor;
import org.apache.polygene.api.composite.TransientComposite;
import org.apache.polygene.api.composite.TransientDescriptor;
import org.apache.polygene.api.entity.EntityComposite;
import org.apache.polygene.api.entity.EntityDescriptor;
import org.apache.polygene.api.entity.EntityReference;
import org.apache.polygene.api.property.Property;
import org.apache.polygene.api.property.PropertyDescriptor;
import org.apache.polygene.api.property.PropertyWrapper;
import org.apache.polygene.api.property.StateHolder;
import org.apache.polygene.api.service.ServiceComposite;
import org.apache.polygene.api.service.ServiceDescriptor;
import org.apache.polygene.api.service.ServiceReference;
import org.apache.polygene.api.structure.ModuleDescriptor;
import org.apache.polygene.api.unitofwork.UnitOfWork;
import org.apache.polygene.api.value.ValueComposite;
import org.apache.polygene.api.value.ValueDescriptor;
import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
import org.apache.polygene.bootstrap.ApplicationModelFactory;
import org.apache.polygene.bootstrap.PolygeneRuntime;
import org.apache.polygene.runtime.association.AbstractAssociationInstance;
import org.apache.polygene.runtime.bootstrap.ApplicationAssemblyFactoryImpl;
import org.apache.polygene.runtime.bootstrap.ApplicationModelFactoryImpl;
import org.apache.polygene.runtime.composite.ProxyReferenceInvocationHandler;
import org.apache.polygene.runtime.composite.TransientInstance;
import org.apache.polygene.runtime.entity.EntityInstance;
import org.apache.polygene.runtime.property.PropertyInstance;
import org.apache.polygene.runtime.service.ImportedServiceReferenceInstance;
import org.apache.polygene.runtime.service.ServiceReferenceInstance;
import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
import org.apache.polygene.runtime.value.ValueInstance;
import org.apache.polygene.spi.PolygeneSPI;
import org.apache.polygene.spi.entity.EntityState;
import static java.lang.reflect.Proxy.getInvocationHandler;
import static org.apache.polygene.api.composite.CompositeInstance.compositeInstanceOf;
/**
* Incarnation of Polygene.
*/
public final class PolygeneRuntimeImpl
implements PolygeneSPI, PolygeneRuntime
{
private final ApplicationAssemblyFactory applicationAssemblyFactory;
private final ApplicationModelFactory applicationModelFactory;
public PolygeneRuntimeImpl()
{
applicationAssemblyFactory = new ApplicationAssemblyFactoryImpl();
applicationModelFactory = new ApplicationModelFactoryImpl();
}
@Override
public ApplicationAssemblyFactory applicationAssemblyFactory()
{
return applicationAssemblyFactory;
}
@Override
public ApplicationModelFactory applicationModelFactory()
{
return applicationModelFactory;
}
@Override
public PolygeneAPI api()
{
return this;
}
@Override
public PolygeneSPI spi()
{
return this;
}
// API
@Override
@SuppressWarnings( "unchecked" )
public <T> T dereference( T composite )
{
InvocationHandler handler = getInvocationHandler( composite );
if( handler instanceof ProxyReferenceInvocationHandler )
{
return (T) ( (ProxyReferenceInvocationHandler) handler ).proxy();
}
if( handler instanceof CompositeInstance )
{
return composite;
}
return null;
}
@Override
public ModuleDescriptor moduleOf( Object compositeOrServiceReferenceOrUow )
{
if( compositeOrServiceReferenceOrUow instanceof Composite )
{
return compositeInstanceOf( (Composite) compositeOrServiceReferenceOrUow ).module();
}
// else if( compositeOrServiceReferenceOrUow instanceof ServiceComposite )
// {
// ServiceComposite composite = (ServiceComposite) compositeOrServiceReferenceOrUow;
// InvocationHandler handler = getInvocationHandler( composite );
// if( handler instanceof ServiceInstance )
// {
// return ( (ServiceInstance) handler ).module();
// }
// return ( (ServiceReferenceInstance.ServiceInvocationHandler) handler ).module();
// }
else if( compositeOrServiceReferenceOrUow instanceof UnitOfWork )
{
ModuleUnitOfWork unitOfWork = (ModuleUnitOfWork) compositeOrServiceReferenceOrUow;
return unitOfWork.module();
}
else if( compositeOrServiceReferenceOrUow instanceof ServiceReferenceInstance )
{
ServiceReferenceInstance<?> reference = (ServiceReferenceInstance<?>) compositeOrServiceReferenceOrUow;
return reference.module();
}
else if( compositeOrServiceReferenceOrUow instanceof ImportedServiceReferenceInstance )
{
ImportedServiceReferenceInstance<?> importedServiceReference
= (ImportedServiceReferenceInstance<?>) compositeOrServiceReferenceOrUow;
return importedServiceReference.module();
}
throw new IllegalArgumentException( "Wrong type. Must be one of "
+ Arrays.asList( TransientComposite.class, ValueComposite.class,
EntityComposite.class,
ServiceComposite.class, ServiceReference.class,
UnitOfWork.class ) );
}
@Override
public ModelDescriptor modelDescriptorFor( Object compositeOrServiceReference )
{
if( compositeOrServiceReference instanceof Composite )
{
return compositeInstanceOf( (Composite) compositeOrServiceReference ).descriptor();
}
// else if( compositeOrServiceReference instanceof ServiceComposite )
// {
// ServiceComposite composite = (ServiceComposite) compositeOrServiceReference;
// InvocationHandler handler = getInvocationHandler( composite );
// if( handler instanceof ServiceInstance )
// {
// return ( (ServiceInstance) handler ).descriptor();
// }
// return ( (ServiceReferenceInstance.ServiceInvocationHandler) handler ).descriptor();
// }
else if( compositeOrServiceReference instanceof ServiceReferenceInstance )
{
ServiceReferenceInstance<?> reference = (ServiceReferenceInstance<?>) compositeOrServiceReference;
return reference.serviceDescriptor();
}
else if( compositeOrServiceReference instanceof ImportedServiceReferenceInstance )
{
ImportedServiceReferenceInstance<?> importedServiceReference
= (ImportedServiceReferenceInstance<?>) compositeOrServiceReference;
return importedServiceReference.serviceDescriptor();
}
throw new IllegalArgumentException( "Wrong type. Must be one of "
+ Arrays.asList( TransientComposite.class, ValueComposite.class, EntityComposite.class,
ServiceComposite.class, ServiceReference.class,
ImportedServiceReferenceInstance.class ) );
}
@Override
public CompositeDescriptor compositeDescriptorFor( Object compositeOrServiceReference )
{
return (CompositeDescriptor) modelDescriptorFor( compositeOrServiceReference );
}
// Descriptors
@Override
public TransientDescriptor transientDescriptorFor( Object transsient )
{
if( transsient instanceof TransientComposite )
{
TransientInstance transientInstance = (TransientInstance) compositeInstanceOf( (Composite) transsient );
return (TransientDescriptor) transientInstance.descriptor();
}
throw new IllegalArgumentException( "Wrong type. Must be subtype of " + TransientComposite.class );
}
@Override
public StateHolder stateOf( TransientComposite composite )
{
return compositeInstanceOf( composite ).state();
}
@Override
public EntityDescriptor entityDescriptorFor( Object entity )
{
if( entity instanceof EntityComposite )
{
EntityInstance entityInstance = (EntityInstance) getInvocationHandler( entity );
return entityInstance.entityModel();
}
throw new IllegalArgumentException( "Wrong type. Must be subtype of " + EntityComposite.class );
}
@Override
public AssociationStateHolder stateOf( EntityComposite composite )
{
return ( (EntityInstance) compositeInstanceOf( composite ) ).state();
}
@Override
public ValueDescriptor valueDescriptorFor( Object value )
{
if( value instanceof ValueComposite )
{
ValueInstance valueInstance = (ValueInstance) compositeInstanceOf( (Composite) value );
return valueInstance.descriptor();
}
throw new IllegalArgumentException( "Wrong type. {" + value + "} must be subtype of " + ValueComposite.class );
}
@Override
public AssociationStateHolder stateOf( ValueComposite composite )
{
return ( (ValueInstance) compositeInstanceOf( composite ) ).state();
}
@Override
public ServiceDescriptor serviceDescriptorFor( Object service )
{
if( service instanceof ServiceReferenceInstance )
{
ServiceReferenceInstance<?> ref = (ServiceReferenceInstance<?>) service;
return ref.serviceDescriptor();
}
if( service instanceof ServiceComposite )
{
ServiceComposite composite = (ServiceComposite) service;
return (ServiceDescriptor) compositeInstanceOf( composite ).descriptor();
}
throw new IllegalArgumentException( "Wrong type. Must be subtype of "
+ ServiceComposite.class + " or " + ServiceReference.class );
}
@Override
public PropertyDescriptor propertyDescriptorFor( Property<?> property )
{
while( property instanceof PropertyWrapper )
{
property = ( (PropertyWrapper) property ).next();
}
return (PropertyDescriptor) ( (PropertyInstance<?>) property ).propertyInfo();
}
@Override
public AssociationDescriptor associationDescriptorFor( AbstractAssociation association )
{
while( association instanceof AssociationWrapper )
{
association = ( (AssociationWrapper) association ).next();
}
while( association instanceof ManyAssociationWrapper )
{
association = ( (ManyAssociationWrapper) association ).next();
}
while( association instanceof NamedAssociationWrapper )
{
association = ( (NamedAssociationWrapper) association ).next();
}
return (AssociationDescriptor) ( (AbstractAssociationInstance) association ).associationInfo();
}
@Override
public boolean isComposite( Object object )
{
return isCompositeType( object );
}
public static boolean isCompositeType( Object object )
{
return Proxy.isProxyClass( object.getClass() )
&& Proxy.getInvocationHandler( object ) instanceof CompositeInstance;
}
// SPI
@Override
public EntityState entityStateOf( EntityComposite composite )
{
return ( (EntityInstance) compositeInstanceOf( composite ) ).entityState();
}
@Override
public EntityReference entityReferenceOf( Association<?> assoc )
{
return assoc.reference();
}
@Override
public Stream<EntityReference> entityReferencesOf( ManyAssociation<?> assoc )
{
return assoc.references();
}
@Override
public Stream<Map.Entry<String, EntityReference>> entityReferencesOf( NamedAssociation<?> assoc )
{
return assoc.references();
}
}