/** * 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.util.BitSet; import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import org.whole.lang.commons.parsers.CommonsDataTypePersistenceParser; import org.whole.lang.model.EnumType; import org.whole.lang.model.EnumValue; import org.whole.lang.model.EnumValueImpl; import org.whole.lang.model.IEntity; /** * @author Riccardo Solmi */ @SuppressWarnings("serial") public abstract class AbstractEntityDescriptor<E extends IEntity> extends EnumValueImpl implements EntityDescriptor<E> { private Class<E> entityType; private boolean isAbstract; private boolean isRelationship; protected AbstractEntityDescriptor() {} //Reserved to standard serialization protected AbstractEntityDescriptor(int ordinal, String name, String implName, Class<E> type, boolean isAbstract, boolean isRelationship) { super(ordinal, name, implName); this.entityType = type; this.isAbstract = isAbstract; this.isRelationship = isRelationship; } protected AbstractEntityDescriptor(int ordinal, String name, String implName, Class<E> type, EnumSet<EntityModifiers> modifiers) { this(ordinal, name, implName, type, modifiers != null && modifiers.contains(EntityModifiers.ABSTRACT), modifiers != null && modifiers.contains(EntityModifiers.RELATIONSHIP)); } public ILanguageKit getLanguageKit() { return getEntityDescriptorEnum().getLanguageKit(); } public String getURI() { return CommonsDataTypePersistenceParser.unparseEntityDescriptor(this); } public EntityDescriptorEnum getEntityDescriptorEnum() { return getEnumType(EntityDescriptorEnum.class); } public FeatureDescriptorEnum getFeatureDescriptorEnum() { return getLanguageKit().getFeatureDescriptorEnum(); } public Class<E> getEntityType() { return entityType; } public CompositeKinds getCompositeKind() { return CompositeKinds.NOT_A_COMPOSITE; } public DataKinds getDataKind() { return DataKinds.NOT_A_DATA; } public Class<?> getDataType() { return null; } public EnumType<? extends EnumValue> getDataEnumType() { return null; } public EntityDescriptor<E> withDataEnumType(EnumType<?> enumType) { throw new IllegalStateException("withDataEnumType is defined only for enum data entities"); } public boolean isAbstract() { return isAbstract; } public boolean isRelationship() { return isRelationship; } public boolean isToManyRelationship() { return false; } public List<FeatureDescriptor> getEntityFeatureDescriptors() { return Collections.<FeatureDescriptor>emptyList(); } public FeatureDescriptor getEntityFeatureDescriptor(FeatureDescriptor fd) { return getEntityFeatureDescriptor(indexOf(fd)); } public FeatureDescriptor getEntityFeatureDescriptor(int index) { throw new IllegalArgumentException("No such feature"); } public boolean has(FeatureDescriptor fd) { return indexOf(fd) != -1; } public int indexOf(FeatureDescriptor fd) { return -1; } public FeatureDescriptor getDirectFeatureDescriptor(FeatureDescriptor oppositeFd) { for (FeatureDescriptor efd : getEntityFeatureDescriptors()) { FeatureDescriptor fd = efd.getOppositeFeatureDescriptor(); if (fd != null && fd.equals(oppositeFd)) return efd; } return null; } public EntityDescriptor<?> getEntityDescriptor(int index) { return getEntityFeatureDescriptor(index).getEntityDescriptor(); } public EntityDescriptor<?> getEntityDescriptor(FeatureDescriptor fd) { return getEntityDescriptor(indexOf(fd)); } public boolean isSubtypeOfAny() { HashSet<EntityDescriptor<?>> supertypes = new HashSet<EntityDescriptor<?>>(); return declaredSupertypesUpto(null, supertypes) && EntityDescriptorEnum.isAllTypes(supertypes); } public boolean isSupertypeOfAny() { HashSet<EntityDescriptor<?>> subtypes = new HashSet<EntityDescriptor<?>>(); return declaredSubtypesUpto(null, subtypes) && EntityDescriptorEnum.isAllTypes(subtypes); } public boolean isLanguageSubtypeOf(EntityDescriptor<?> ed) { return getLanguageKit().equals(ed.getLanguageKit()) ? languageSupertypes().get(ed.getOrdinal()) : false; } public boolean isLanguageSupertypeOf(EntityDescriptor<?> ed) { return equals(ed); } public boolean isPlatformSupertypeOf(EntityDescriptor<?> ed) { return declaredSubtypesUpto(ed, new HashSet<EntityDescriptor<?>>()) || ed.declaredSupertypesUpto(this, new HashSet<EntityDescriptor<?>>()); } public boolean isExtendedLanguageSupertypeOf(EntityDescriptor<?> ed) { return getLanguageKit().equals(ed.getLanguageKit()) ? isLanguageSupertypeOf(ed) : isPlatformSupertypeOf(ed); } public void setLanguageSubtypes(boolean enable, int... edOrdinals) { throw new UnsupportedOperationException(); } private BitSet languageSupertypes; protected BitSet languageSupertypes() { if (languageSupertypes == null) { languageSupertypes = new BitSet(); languageSupertypes.set(getOrdinal()); EntityDescriptorEnum edEnum = getEntityDescriptorEnum(); for (EntityDescriptor<?> superEd : edEnum) if (superEd.isLanguageSupertypeOf(this)) languageSupertypes.set(superEd.getOrdinal()); } return languageSupertypes; } private BitSet languageSubtypes; protected BitSet languageSubtypes() { if (languageSubtypes == null) { languageSubtypes = new BitSet(); languageSubtypes.set(getOrdinal()); } return languageSubtypes; } public Iterable<EntityDescriptor<?>> languageSupertypesIterable() { return new Iterable<EntityDescriptor<?>>() { public Iterator<EntityDescriptor<?>> iterator() { return new Iterator<EntityDescriptor<?>>() { private int fromIndex; public boolean hasNext() { return fromIndex >= 0 && languageSupertypes().nextSetBit(fromIndex) >= 0; } public EntityDescriptor<?> next() { if (fromIndex < 0) throw new NoSuchElementException(); fromIndex = languageSupertypes().nextSetBit(fromIndex); return getEntityDescriptorEnum().valueOf(fromIndex++); } public void remove() { throw new UnsupportedOperationException(); } }; } }; } public Iterable<EntityDescriptor<?>> languageSubtypesIterable() { return new Iterable<EntityDescriptor<?>>() { public Iterator<EntityDescriptor<?>> iterator() { return new Iterator<EntityDescriptor<?>>() { private int fromIndex; public boolean hasNext() { return fromIndex >= 0 && languageSubtypes().nextSetBit(fromIndex) >= 0; } public EntityDescriptor<?> next() { if (fromIndex < 0) throw new NoSuchElementException(); fromIndex = languageSubtypes().nextSetBit(fromIndex); return getEntityDescriptorEnum().valueOf(fromIndex++); } public void remove() { throw new UnsupportedOperationException(); } }; } }; } public /*final*/ Set<EntityDescriptor<?>> getLanguageConcreteSubtypes() { return getLanguageConcreteSubtypes(new HashSet<EntityDescriptor<?>>()); } public Set<EntityDescriptor<?>> getLanguageConcreteSubtypes(Set<EntityDescriptor<?>> set) { set.add(this); return set; } public boolean declaredSupertypesUpto(EntityDescriptor<?> optTargetEd, Set<EntityDescriptor<?>> supertypes) { if (optTargetEd != null && isLanguageSubtypeOf(optTargetEd)) return true; EntityDescriptorEnum edEnum = getEntityDescriptorEnum(); for (int i=languageSupertypes().nextSetBit(0); i>=0; i=languageSupertypes().nextSetBit(i+1)) if (edEnum.declaredForeignSupertypesUpto(edEnum.valueOf(i), optTargetEd, supertypes)) return true; return false; } public boolean declaredSubtypesUpto(EntityDescriptor<?> optTargetEd, Set<EntityDescriptor<?>> subtypes) { return (optTargetEd != null && isLanguageSupertypeOf(optTargetEd)) || getEntityDescriptorEnum().declaredForeignSubtypesUpto(this, optTargetEd, subtypes); } public boolean isPolymorphic() { return false; } public EntityDescriptor<E> withFeature(FeatureDescriptor fd, int edOrdinal) { return withFeature(fd, edOrdinal, null, false, false, false, false, false); } public EntityDescriptor<E> withFeature(FeatureDescriptor fd, int edOrdinal, boolean isOptional, boolean isId, boolean isReference, boolean isDerived, boolean isShared) { return withFeature(fd, edOrdinal, null, isOptional, isId, isReference, isDerived, isShared); } public EntityDescriptor<E> withFeature(FeatureDescriptor fd, int edOrdinal, FeatureDescriptor oppositeFd, boolean isOptional, boolean isId, boolean isReference, boolean isDerived, boolean isShared) { throw new UnsupportedOperationException(); } public String toString() { return (getLanguageKit() != null ? getLanguageKit().getURI()+"#" : "")+getName(); } }