/**
* 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.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.whole.lang.commons.parsers.CommonsDataTypePersistenceParser;
import org.whole.lang.model.DynamicEnumType;
import org.whole.lang.model.EnumType;
import org.whole.lang.model.EnumValue;
import org.whole.lang.model.EnumValueImpl;
import org.whole.lang.model.IEntity;
import org.whole.lang.resources.IResourceRegistryListener;
/**
* @author Riccardo Solmi
*/
public class EntityDescriptorEnum extends EnumType<EntityDescriptor<?>> implements IResourceRegistryListener<ILanguageKit> {
private static final long serialVersionUID = 1L;
transient private ILanguageKit languageKit;
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
languageKit = ReflectionFactory.getLanguageKit(in.readUTF(), true, null);
in.defaultReadObject();
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.writeUTF(languageKit.getURI());
out.defaultWriteObject();
}
public EntityDescriptorEnum() {
initEntityDescriptors();
initForeignTypeRelations();
}
protected void initEntityDescriptors() {
}
protected void initForeignTypeRelations() {
}
public void updateTypeRelations() {
}
public void updateForeignTypeRelations() {
updateForeignTypeRelations(null, true);
}
public void notifyAdded(ILanguageKit resource) {
updateForeignTypeRelations(resource, true);
}
public void notifyRemoved(ILanguageKit resource) {
updateForeignTypeRelations(resource, false);
//FIXME initForeignTypeRelations();
}
public void notifyChanged(ILanguageKit oldResource, ILanguageKit newResource) {
notifyRemoved(oldResource);
notifyAdded(newResource);
}
protected void updateForeignTypeRelations(ILanguageKit foreignLanguageKit, boolean enable) {
if (foreignLanguageKit != null && foreignLanguageKit.equals(getLanguageKit()))
return;
for (Map.Entry<EntityDescriptor<?>, Set<String>> entry : directForeignSupertypes.entrySet())
if (!isAllTypes(entry.getValue()))
for (String foreignEdUri : entry.getValue()) {
EntityDescriptor<?> foreignEd = CommonsDataTypePersistenceParser.getEntityDescriptor(foreignEdUri, false, null);
if (foreignEd != null && (foreignLanguageKit == null || foreignEd.getLanguageKit().equals(foreignLanguageKit)))
foreignEd.getEntityDescriptorEnum().setAssignableFromForeignType(enable,
entry.getKey().getURI(), foreignEd.getOrdinal());
}
for (Map.Entry<EntityDescriptor<?>, Set<String>> entry : directForeignSubtypes.entrySet())
if (!isAllTypes(entry.getValue()))
for (String foreignEdUri : entry.getValue()) {
EntityDescriptor<?> foreignEd = CommonsDataTypePersistenceParser.getEntityDescriptor(foreignEdUri, false, null);
if (foreignEd != null && (foreignLanguageKit == null || foreignEd.getLanguageKit().equals(foreignLanguageKit)))
foreignEd.getEntityDescriptorEnum().setAssignableToForeignType(enable,
entry.getKey().getURI(), foreignEd.getOrdinal());
}
}
public final boolean equals(Object o) {
if (!(o instanceof EntityDescriptorEnum))
return false;
return getLanguageKit().equals(((EntityDescriptorEnum) o).getLanguageKit());
}
public ILanguageKit getLanguageKit() {
return languageKit;
}
public void setLanguageKit(ILanguageKit languageKit) {
this.languageKit = languageKit;
updateTypeRelations();
updateForeignTypeRelations();
ReflectionFactory.getLanguageKitRegistry().addResourceRegistryListener(this);
}
public static final Set<String> ALL_TYPES = Collections.emptySet();
public static boolean isAllTypes(Set<?> types) {
return types != null && types.isEmpty();
}
protected Map<EntityDescriptor<?>, Set<String>> directForeignSupertypes = new HashMap<EntityDescriptor<?>, Set<String>>();
protected Map<EntityDescriptor<?>, Set<String>> directForeignSubtypes = new HashMap<EntityDescriptor<?>, Set<String>>();
public boolean declaredForeignSupertypesUpto(EntityDescriptor<?> ed, EntityDescriptor<?> optTargetEd, Set<EntityDescriptor<?>> supertypes) {
if (supertypes.add(ed)) {
Set<String> foreignSupertypes = directForeignSupertypes.get(ed);
if (foreignSupertypes == null)
return false;
else if (isAllTypes(foreignSupertypes)) {
supertypes.clear();
return true;
} else if (optTargetEd != null && foreignSupertypes.contains(optTargetEd.getURI()))
return true;
else
for (String foreignEdUri : foreignSupertypes) {
EntityDescriptor<?> foreignEd = CommonsDataTypePersistenceParser.getEntityDescriptor(foreignEdUri, false, null);
if (foreignEd != null && foreignEd.declaredSupertypesUpto(optTargetEd, supertypes))
return true;
}
}
return false;
}
public boolean declaredForeignSubtypesUpto(EntityDescriptor<?> ed, EntityDescriptor<?> optTargetEd, Set<EntityDescriptor<?>> subtypes) {
if (subtypes.add(ed)) {
Set<String> foreignSubtypes = directForeignSubtypes.get(ed);
if (foreignSubtypes == null)
return false;
else if (isAllTypes(foreignSubtypes)) {
subtypes.clear();
return true;
} else if (optTargetEd != null && foreignSubtypes.contains(optTargetEd.getURI()))
return true;
else
for (String foreignEdUri : foreignSubtypes) {
EntityDescriptor<?> foreignEd = CommonsDataTypePersistenceParser.getEntityDescriptor(foreignEdUri, false, null);
if (foreignEd != null && foreignEd.declaredSubtypesUpto(optTargetEd, subtypes))
return true;
}
}
return false;
}
public void setAssignableToAll(boolean enable, int... edOrdinals) {
for (int edOrdinal : edOrdinals)
if (enable)
directForeignSupertypes.put(valueOf(edOrdinal), ALL_TYPES);
else
directForeignSupertypes.remove(valueOf(edOrdinal));
}
public void setAssignableToForeignType(boolean enable, String foreignEdUri, int... edOrdinals) {
for (int edOrdinal : edOrdinals) {
EntityDescriptor<?> ed = valueOf(edOrdinal);
Set<String> subtypes = directForeignSupertypes.get(ed);
if (isAllTypes(subtypes))
return;
else if (subtypes == null && enable)
directForeignSupertypes.put(ed, subtypes = new HashSet<String>());
if (enable)
subtypes.add(foreignEdUri);
else if (subtypes != null) {
subtypes.remove(foreignEdUri);
if (subtypes.isEmpty())//otherwise isAllTypes(subtypes) true
directForeignSupertypes.remove(ed);
}
}
}
public void setAssignableFromAll(boolean enable, int... edOrdinals) {
for (int edOrdinal : edOrdinals)
if (enable)
directForeignSubtypes.put(valueOf(edOrdinal), ALL_TYPES);
else
directForeignSubtypes.remove(valueOf(edOrdinal));
}
public void setAssignableFromForeignType(boolean enable, String foreignEdUri, int... edOrdinals) {
for (int edOrdinal : edOrdinals) {
EntityDescriptor<?> ed = valueOf(edOrdinal);
Set<String> supertypes = directForeignSubtypes.get(ed);
if (isAllTypes(supertypes))
return;
else if (supertypes == null && enable)
directForeignSubtypes.put(ed, supertypes = new HashSet<String>());
if (enable)
supertypes.add(foreignEdUri);
else if (supertypes != null) {
supertypes.remove(foreignEdUri);
if (supertypes.isEmpty())//otherwise isAllTypes(supertypes) true
directForeignSubtypes.remove(ed);
}
}
}
public void setAliasOf(boolean enable, String foreignEdUri, int edOrdinal) {
setAssignableToForeignType(enable, foreignEdUri, edOrdinal);
setAssignableFromForeignType(enable, foreignEdUri, edOrdinal);
}
public Set<EntityDescriptor<?>> getExtendedLanguageConcreteSubtypesOf(EntityDescriptor<?> foreignEd) {
return getExtendedLanguageConcreteSubtypesOf(foreignEd, new HashSet<EntityDescriptor<?>>());
}
protected Set<EntityDescriptor<?>> getExtendedLanguageConcreteSubtypesOf(EntityDescriptor<?> foreignEd, Set<EntityDescriptor<?>> values) {
for (EntityDescriptor<?> value : this)
if (!value.isAbstract() && foreignEd.isExtendedLanguageSupertypeOf(value))
values.add(value);
return values;
}
protected <E extends IEntity> EntityDescriptor<E> putSimpleEntity(int ordinal,
String name, Class<E> type, boolean isAbstract) {
return putSimpleEntity(ordinal, name, name, type, isAbstract);
}
protected <E extends IEntity> EntityDescriptor<E> putSimpleEntity(int ordinal,
String name, String implName, Class<E> type, boolean isAbstract) {
assert (valueOf(name) == null);
EntityDescriptor<E> ed = new SimpleEntityDescriptor<E>(ordinal, name, implName, type, isAbstract);
putEnumValue(ed);
return ed;
}
protected <E extends IEntity> EntityDescriptor<E> putSimpleEntity(int ordinal,
String name, Class<E> type, boolean isAbstract, int... assignableEdOrdinals) {
return putSimpleEntity(ordinal, name, name, type, isAbstract, assignableEdOrdinals);
}
protected <E extends IEntity> EntityDescriptor<E> putSimpleEntity(int ordinal,
String name, String implName, Class<E> type, boolean isAbstract, int... assignableEdOrdinals) {
EntityDescriptor<E> ed = putSimpleEntity(ordinal, name, implName, type, isAbstract);
ed.setLanguageSubtypes(true, assignableEdOrdinals);
return ed;
}
protected <E extends IEntity> EntityDescriptor<E> putCompositeEntity(
int ordinal, String name, Class<E> type,
boolean isRelationship, int elementEdOrdinal,
boolean isOrdered, boolean isUnique) {
return putCompositeEntity(
ordinal, name, name, type, isRelationship, elementEdOrdinal, isOrdered, isUnique);
}
protected <E extends IEntity> EntityDescriptor<E> putCompositeEntity(
int ordinal, String name, String implName, Class<E> type,
boolean isRelationship, int elementEdOrdinal,
boolean isOrdered, boolean isUnique) {
return putCompositeEntity(ordinal, name, implName, type,
isRelationship, elementEdOrdinal,
isOrdered, isUnique, false, false, false);
}
protected <E extends IEntity> EntityDescriptor<E> putCompositeEntity(
int ordinal, String name, Class<E> type,
boolean isRelationship, int elementEdOrdinal,
boolean isOrdered, boolean isUnique, boolean isReference,
boolean isDerived, boolean isShared) {
return putCompositeEntity(ordinal, name, name, type,
isRelationship, elementEdOrdinal, isOrdered, isUnique,
isReference, isDerived, isShared);
}
protected <E extends IEntity> EntityDescriptor<E> putCompositeEntity(
int ordinal, String name, String implName, Class<E> type,
boolean isRelationship, int elementEdOrdinal,
boolean isOrdered, boolean isUnique, boolean isReference,
boolean isDerived, boolean isShared) {
assert (valueOf(name) == null);
EntityDescriptor<E> ed = new CompositeEntityDescriptor<E>(ordinal, name, implName, type,
isRelationship, isOrdered, isUnique,
elementEdOrdinal, true, isReference, isDerived, isShared);
putEnumValue(ed);
return ed;
}
protected <E extends IEntity> EntityDescriptor<E> putMapEntity(int ordinal,
String name, Class<E> type, boolean isRelationship,
int keyEdOrdinal, int valueEdOrdinal) {
return putMapEntity(ordinal, name, name, type,
isRelationship, keyEdOrdinal, valueEdOrdinal);
}
protected <E extends IEntity> EntityDescriptor<E> putMapEntity(int ordinal,
String name, String implName, Class<E> type, boolean isRelationship,
int keyEdOrdinal, int valueEdOrdinal) {
assert (valueOf(name) == null);
EntityDescriptor<E> ed = new MapEntityDescriptor<E>(ordinal, name, implName, type,
isRelationship, keyEdOrdinal, valueEdOrdinal);
putEnumValue(ed);
return ed;
}
protected <E extends IEntity> EntityDescriptor<E> putDataEntity(int ordinal,
String name, Class<E> type, boolean isRelationship, Class<?> dataType) {
return putDataEntity(ordinal, name, name, type, isRelationship, dataType);
}
protected <E extends IEntity> EntityDescriptor<E> putDataEntity(int ordinal,
String name, String implName, Class<E> type, boolean isRelationship, Class<?> dataType) {
assert (valueOf(name) == null);
EntityDescriptor<E> ed = new DataEntityDescriptor<E>(ordinal, name, implName, type, isRelationship, dataType);
putEnumValue(ed);
return ed;
}
public EntityDescriptor<? extends IEntity> addSimpleEntity(String name, String implName, boolean isAbstract) {
return putSimpleEntity(size(), name, implName, IEntity.class, isAbstract);
}
public EntityDescriptor<? extends IEntity> addCompositeEntity(String name, String implName, boolean isRelationship,
boolean isOrdered, boolean isUnique) {
return putCompositeEntity(size(), name, implName, IEntity.class, isRelationship, 0, isOrdered, isUnique, false, false, false);
}
public EntityDescriptor<? extends IEntity> addDataEntity(String name, String implName, boolean isRelationship, Class<?> dataType) {
return putDataEntity(size(), name, implName, IEntity.class, isRelationship, dataType);
}
public EntityDescriptor<? extends IEntity> addEnumEntity(String name, String implName, final String... enumValues) {
return putDataEntity(size(), name, implName, IEntity.class, false, EnumValue.class).withDataEnumType(new DynamicEnumType(name) {
private static final long serialVersionUID = 1L;
{
int i=0;
for (String value : enumValues)
putEnumValue(new EnumValueImpl(i++, value));
}
});
}
}