/**
* 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.factories;
import org.whole.lang.bindings.IBindingManager;
import org.whole.lang.commons.factories.CommonsEntityAdapterFactory;
import org.whole.lang.matchers.Matcher;
import org.whole.lang.model.IEntity;
import org.whole.lang.model.InternalIEntity;
import org.whole.lang.reflect.EntityDescriptor;
import org.whole.lang.reflect.FeatureDescriptor;
import org.whole.lang.util.EntityUtils;
/**
* @author Riccardo Solmi
*/
public class GenericEntityFactory implements IEntityFactory {
protected IEntityRegistryProvider entityRegistryProvider;
public static final IEntityFactory instance = instance(RegistryConfigurations.DEFAULT);
public static IEntityFactory instance(IEntityRegistryProvider provider) {
return new GenericEntityFactory(provider);
}
protected GenericEntityFactory(IEntityRegistryProvider entityRegistryProvider) {
this.entityRegistryProvider = entityRegistryProvider;
}
public final IEntityRegistry getEntityRegistry(EntityDescriptor<?> ed) {
return entityRegistryProvider.getEntityRegistry(ed);
}
protected final <E extends IEntity> E get(EntityDescriptor<E> ed) {
return getEntityRegistry(ed).get(ed);
}
protected <E extends IEntity> E clone(E prototype) {
return EntityUtils.clone(prototype);
}
//TODO rename resolverClone
public <E extends IEntity> E clone(EntityDescriptor<E> ed, int initialSize) {
if (!EntityUtils.isComposite(ed))
throw new IllegalArgumentException("Expecting a composite entity");
IEntity[] values = new IEntity[initialSize];
for (int i=0; i<initialSize; i++)
values[i] = CommonsEntityAdapterFactory.createResolver(ed.getEntityDescriptor(i));
return create(ed, values);
}
@SuppressWarnings("unchecked")
public <E extends IEntity> E shallowClone(EntityDescriptor<E> ed) {
return (E) ((InternalIEntity) get(ed)).wShallowClone();
}
public <E extends IEntity> E shallowClone(EntityDescriptor<E> ed, IEntity... args) {
E entity = shallowClone(ed);
for (int i = 0; i < args.length; i++)
entity.wSet(i, args[i]);
return entity;
}
public IEntity cloneFeature(EntityDescriptor<?> ed, int index) {
IEntity prototype = get(ed);
if (index < prototype.wSize())
return clone(prototype.wGet(index));
if (EntityUtils.isComposite(prototype) && prototype.wSize() == 1)
return clone(prototype.wGet(0));
return CommonsEntityAdapterFactory.createResolver(ed.getEntityDescriptor(0));
}
public IEntity cloneFeature(EntityDescriptor<?> ed, FeatureDescriptor fd) {
return clone(get(ed).wGet(fd));
}
public boolean matchFeature(EntityDescriptor<?> ed, int index, IEntity value) {
return Matcher.match(value, get(ed).wGet(index));
}
public boolean matchFeature(EntityDescriptor<?> ed, FeatureDescriptor fd, IEntity value) {
return Matcher.match(value, get(ed).wGet(fd));
}
public <E extends IEntity> E create(EntityDescriptor<E> ed) {
return clone(get(ed));
}
public <E extends IEntity> E create(EntityDescriptor<E> ed, Object value) {
E entity = shallowClone(ed);
if (EntityUtils.isData(entity))
entity.wSetValue(value);
else if (EntityUtils.isData(ed.getEntityDescriptor(0)))
entity.wSet(0, create(ed.getEntityDescriptor(0), value));
else
throw new IllegalArgumentException("Expecting a data entity");
return entity;
}
public <E extends IEntity> E create(EntityDescriptor<E> ed, Object... values) {
IEntity[] args = new IEntity[values.length];
for (int i=0; i<values.length; i++)
if (ed.getEntityDescriptor(i).getEntityKind().isData())
args[i] = create(ed.getEntityDescriptor(i), values[i]);
else if (values[i] instanceof IEntity)
args[i] = (IEntity) values[i];
else
throw new IllegalArgumentException();
return create(ed, args);
}
public <E extends IEntity> E create(EntityDescriptor<E> ed, IEntity value) {
return create(ed, new IEntity[] { value });
}
public <E extends IEntity> E create(EntityDescriptor<E> ed, IEntity... values) {
E entity = values.length == ed.getEntityFeatureDescriptors().size() ? shallowClone(ed) : create(ed);
if (ed.getEntityKind().isComposite()) {
int length = values.length;
if (!ed.getCompositeKind().isOrdered())
length = 0; // unordered composites forward wSet by index to wAdd
for (int i=entity.wSize()-1; i>=length; i--)
entity.wRemove(i);
}
for (int i = 0; i < values.length; i++)
entity.wSet(i, values[i]); //FIXME check return value on AbstractUListEntity when implemented
return entity;
}
public <E extends IEntity> E create(EntityDescriptor<E> ed, IBindingManager bindings) {
E result = create(ed);
if (!EntityUtils.isSimple(result))
throw new IllegalArgumentException("Expecting a simple entity");
for (int i = 0; i < result.wSize(); i++) {
IEntity value = bindings.wGet(ed.getEntityFeatureDescriptor(i).getName());
if (value != null)
result.wSet(i, value);
}
return result;
}
public <E extends IEntity> IEntityBuilder<E> build(EntityDescriptor<E> ed) {
if (!EntityUtils.isSimple(ed))
throw new IllegalArgumentException("Expecting a simple entity");
return new EntityBuilder<E>(create(ed));
}
}