Skip to content

Commit

Permalink
Add check of properties conflicts
Browse files Browse the repository at this point in the history
Plus few utilities methods
  • Loading branch information
PhantomYdn committed Apr 2, 2015
1 parent fe1b771 commit d4dd342
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 25 deletions.
Expand Up @@ -500,14 +500,15 @@ void setSuperClassesInternal(List<? extends OClass> classes) {
cls = (OClassImpl) superClass;
newSuperClasses.add(cls);
}
checkParametersConflict(newSuperClasses);
List<OClassImpl> toAddList = new ArrayList<OClassImpl>(newSuperClasses);
toAddList.removeAll(superClasses);
List<OClassImpl> toRemoveList = new ArrayList<OClassImpl>(superClasses);
toRemoveList.removeAll(newSuperClasses);

for(OClassImpl addTo: toAddList)
{
addTo.addBaseClasses(this);
addTo.addBaseClass(this);
}
for(OClassImpl toRemove: toRemoveList)
{
Expand Down Expand Up @@ -557,11 +558,13 @@ void addSuperClassInternal(final OClass superClass) {
cls = (OClassImpl) ((OClassAbstractDelegate) superClass).delegate;
else
cls = (OClassImpl) superClass;

if (cls != null)
cls.addBaseClasses(this);

superClasses.add(cls);
if (cls != null)
{
cls.checkParametersConflict(this);
cls.addBaseClass(this);
superClasses.add(cls);
}
} finally {
releaseSchemaWriteLock();
}
Expand Down Expand Up @@ -724,24 +727,24 @@ public Map<String, OProperty> propertiesMap() {
acquireSchemaReadLock();
try {
final Map<String, OProperty> props = new HashMap<String, OProperty>(20);
propertiesMap(props);
propertiesMap(props, true);
return props;
} finally {
releaseSchemaReadLock();
}
}

public void propertiesMap(Map<String, OProperty> propertiesMap)
private void propertiesMap(Map<String, OProperty> propertiesMap, boolean keepCase)
{
for (OProperty p : properties.values()) {
final String propName = p.getName();

String propName = p.getName();
if(!keepCase) propName = propName.toLowerCase();
if (!propertiesMap.containsKey(propName))
propertiesMap.put(propName, p);
}
for(OClassImpl superClass: superClasses)
{
superClass.propertiesMap(propertiesMap);
superClass.propertiesMap(propertiesMap, keepCase);
}
}

Expand Down Expand Up @@ -2327,11 +2330,9 @@ private void addClusterIdToIndexes(int iId) {
* @param iBaseClass
* The base class to add.
*/
private OClass addBaseClasses(final OClassImpl iBaseClass) {
if(checkRecursion(iBaseClass))
{
throw new OSchemaException("Can't add base class, because of recursion");
}
private OClass addBaseClass(final OClassImpl iBaseClass) {
checkRecursion(iBaseClass);
checkParametersConflict(iBaseClass);

if (subclasses == null)
subclasses = new ArrayList<OClass>();
Expand All @@ -2344,11 +2345,52 @@ private OClass addBaseClasses(final OClassImpl iBaseClass) {
return this;
}

private boolean checkRecursion(OClass baseClass)
private void checkParametersConflict(OClass baseClass)
{
Collection<OProperty> baseClassProperties = baseClass.properties();
for(OProperty property:baseClassProperties)
{
OProperty thisProperty = getProperty(property.getName());
if(thisProperty!=null && thisProperty.getType().equals(property.getType()))
{
throw new OSchemaException("Can't add base class '"+baseClass.getName()+"', because of paramaters conflict: "+thisProperty+" vs "+property);
}
}
}

private void checkParametersConflict(List<OClassImpl> classes)
{
Map<String, OProperty> commulative = new HashMap<String, OProperty>();
Map<String, OProperty> properties = new HashMap<String, OProperty>();;
for(OClassImpl superClass:classes)
{
superClass.propertiesMap(properties, false);
for(Map.Entry<String, OProperty> entry: properties.entrySet())
{
if(commulative.containsKey(entry.getKey()))
{
String property = entry.getKey();
OProperty existingProperty = commulative.get(property);
if(!existingProperty.getType().equals(entry.getValue().getType()))
{
throw new OSchemaException("Properties conflict detected: ["+existingProperty+"] vs ["+entry.getValue()+"]");
}
}
}

commulative.putAll(properties);
properties.clear();
}
}

private void checkRecursion(OClass baseClass)
{
Set<String> browsed = new HashSet<String>();
browsed.add(baseClass.getName());
return checkRecursion(browsed);
if(checkRecursion(browsed))
{
throw new OSchemaException("Can't add base class '"+baseClass.getName()+"', because of recursion");
}
}

private boolean checkRecursion(Set<String> browsedClasses)
Expand Down
Expand Up @@ -132,6 +132,11 @@ public OClass createAbstractClass(String iClassName) {
public OClass createAbstractClass(String iClassName, OClass iSuperClass) {
throw new UnsupportedOperationException();
}

@Override
public OClass createAbstractClass(String iClassName, OClass... superClasses) {
throw new UnsupportedOperationException();
}

@Override
public void dropClass(String iClassName) {
Expand Down
Expand Up @@ -54,6 +54,8 @@ public interface OSchema {
public OClass createAbstractClass(final String iClassName);

public OClass createAbstractClass(final String iClassName, final OClass iSuperClass);

public OClass createAbstractClass(final String iClassName, final OClass... superClasses);

public void dropClass(final String iClassName);

Expand Down
Expand Up @@ -152,6 +152,12 @@ public OClass createAbstractClass(final String iClassName, final OClass iSuperCl
setCurrentDatabaseInThreadLocal();
return delegate.createAbstractClass(iClassName, iSuperClass);
}

@Override
public OClass createAbstractClass(String iClassName, OClass... superClasses) {
setCurrentDatabaseInThreadLocal();
return delegate.createAbstractClass(iClassName, superClasses);
}

public void dropClass(final String iClassName) {
setCurrentDatabaseInThreadLocal();
Expand Down
Expand Up @@ -379,6 +379,11 @@ public OClass createAbstractClass(final String className, final OClass superClas
return createClass(className, superClass, -1);
}

@Override
public OClass createAbstractClass(String iClassName, OClass... superClasses) {
return createClass(iClassName, new int[]{-1}, superClasses);
}

@Override
public OClass createClass(final String className, final OClass superClass, int[] clusterIds) {
return createClass(className, clusterIds, superClass);
Expand Down
Expand Up @@ -37,20 +37,20 @@ public void testClassCreation()

OClass aClass = oSchema.createAbstractClass("javaA");
OClass bClass = oSchema.createAbstractClass("javaB");
aClass.createProperty("property", OType.INTEGER);
bClass.createProperty("property", OType.DOUBLE);
aClass.createProperty("propertyInt", OType.INTEGER);
bClass.createProperty("propertyDouble", OType.DOUBLE);
OClass cClass = oSchema.createClass("javaC", aClass,bClass);
testClassClreationBranch(aClass, bClass, cClass);
testClassCreationBranch(aClass, bClass, cClass);
oSchema.reload();
testClassClreationBranch(aClass, bClass, cClass);
testClassCreationBranch(aClass, bClass, cClass);
oSchema = db.getMetadata().getImmutableSchemaSnapshot();
aClass = oSchema.getClass("javaA");
bClass = oSchema.getClass("javaB");
cClass = oSchema.getClass("javaC");
testClassClreationBranch(aClass, bClass, cClass);
testClassCreationBranch(aClass, bClass, cClass);
}

private void testClassClreationBranch(OClass aClass, OClass bClass, OClass cClass)
private void testClassCreationBranch(OClass aClass, OClass bClass, OClass cClass)
{
assertNotNull(aClass.getSuperClasses());
assertEquals(aClass.getSuperClasses().size(), 0);
Expand All @@ -67,10 +67,15 @@ private void testClassClreationBranch(OClass aClass, OClass bClass, OClass cClas
assertTrue(aClass.isSuperClassOf(cClass));
assertTrue(bClass.isSuperClassOf(cClass));

OProperty property = cClass.getProperty("property");
OProperty property = cClass.getProperty("propertyInt");
assertEquals(OType.INTEGER, property.getType());
property = cClass.propertiesMap().get("property");
property = cClass.propertiesMap().get("propertyInt");
assertEquals(OType.INTEGER, property.getType());

property = cClass.getProperty("propertyDouble");
assertEquals(OType.DOUBLE, property.getType());
property = cClass.propertiesMap().get("propertyDouble");
assertEquals(OType.DOUBLE, property.getType());
}

@Test
Expand Down Expand Up @@ -128,4 +133,27 @@ public void testPreventionOfCycles()

aClass.setSuperClasses(Arrays.asList(cClass));
}

@Test
public void testParametersImpactGoodScenario()
{
final OSchema oSchema = db.getMetadata().getSchema();
OClass aClass = oSchema.createAbstractClass("impactGoodA");
aClass.createProperty("property", OType.STRING);
OClass bClass = oSchema.createAbstractClass("impactGoodB");
bClass.createProperty("property", OType.STRING);
OClass cClass = oSchema.createAbstractClass("impactGoodC", aClass, bClass);
assertTrue(cClass.existsProperty("property"));
}

@Test(expectedExceptions={OSchemaException.class}, expectedExceptionsMessageRegExp=".*conflict.*")
public void testParametersImpactBadScenario()
{
final OSchema oSchema = db.getMetadata().getSchema();
OClass aClass = oSchema.createAbstractClass("impactBadA");
aClass.createProperty("property", OType.STRING);
OClass bClass = oSchema.createAbstractClass("impactBadB");
bClass.createProperty("property", OType.INTEGER);
oSchema.createAbstractClass("impactBadC", aClass, bClass);
}
}
Expand Up @@ -120,6 +120,11 @@ public OClass createAbstractClass(String iClassName) {
public OClass createAbstractClass(String iClassName, OClass iSuperClass) {
return underlying.createAbstractClass(iClassName, iSuperClass);
}

@Override
public OClass createAbstractClass(String iClassName, OClass... superClasses) {
return underlying.createAbstractClass(iClassName, superClasses);
}

@Override
public void dropClass(String iClassName) {
Expand Down

0 comments on commit d4dd342

Please sign in to comment.