package org.orienteer.core.module;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.index.OIndex;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OClass.INDEX_TYPE;
import com.orientechnologies.orient.core.metadata.schema.OProperty;
import com.orientechnologies.orient.core.metadata.schema.OSchema;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.metadata.security.OIdentity;
import com.orientechnologies.orient.core.metadata.security.ORole;
import com.orientechnologies.orient.core.metadata.security.OSecurityShared;
import com.orientechnologies.orient.core.metadata.security.OUser;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.query.OSQLSynchQuery;
import org.orienteer.core.CustomAttribute;
import org.orienteer.core.OrienteerWebApplication;
import org.orienteer.core.util.CommonUtils;
import org.orienteer.core.util.OSchemaHelper;
import ru.ydn.wicket.wicketorientdb.utils.DBClosure;
import javax.inject.Singleton;
import java.util.List;
import java.util.Set;
/**
* {@link IOrienteerModule} for "perspectives" feature of Orienteer
*/
@Singleton
public class PerspectivesModule extends AbstractOrienteerModule
{
public static final String NAME = "perspectives";
public static final String OCLASS_PERSPECTIVE="OPerspective";
public static final String OCLASS_ITEM = "OPerspectiveItem";
public static final String DEFAULT_PERSPECTIVE = "Default";
public PerspectivesModule()
{
super(NAME, 5);
}
@Override
public ODocument onInstall(OrienteerWebApplication app, ODatabaseDocument db) {
OSchemaHelper.bind(db)
.oClass(OCLASS_PERSPECTIVE)
.oProperty("name", OType.EMBEDDEDMAP).assignVisualization("localization")
.markAsDocumentName()
.linkedType(OType.STRING)
.oIndex(OCLASS_PERSPECTIVE + ".name_by_value", INDEX_TYPE.UNIQUE, "name by value")
.oProperty("icon", OType.STRING)
.oProperty("homeUrl", OType.STRING)
.oProperty("menu", OType.LINKLIST).assignVisualization("table")
.oProperty("footer", OType.STRING).assignVisualization("textarea")
.switchDisplayable(true, "name", "homeUrl")
.orderProperties("name", "icon", "homeUrl", "footer", "menu")
.oClass(OCLASS_ITEM)
.oProperty("name", OType.EMBEDDEDMAP).assignVisualization("localization").markAsDocumentName()
.oProperty("icon", OType.STRING)
.oProperty("url", OType.STRING)
.oProperty("perspective", OType.LINK).markAsLinkToParent()
.oProperty("perspectiveItem", OType.LINK).markAsLinkToParent()
.oProperty("subItems", OType.LINKLIST).assignVisualization("table")
.switchDisplayable(true, "name", "icon", "url")
.orderProperties("name", "perspective", "icon", "url")
.setupRelationship(OCLASS_PERSPECTIVE, "menu", OCLASS_ITEM, "perspective")
.oClass(OIdentity.CLASS_NAME)
.oProperty("perspective", OType.LINK).linkedClass(OCLASS_PERSPECTIVE)
.setupRelationship(OCLASS_ITEM, "subItems", OCLASS_ITEM, "perspectiveItem")
.oProperty("perspectiveItem", OType.LINK).linkedClass(OCLASS_ITEM)
.oClass(OIdentity.CLASS_NAME);
return null;
}
@Override
public void onUpdate(OrienteerWebApplication app, ODatabaseDocument db,
int oldVersion, int newVersion) {
int toVersion = oldVersion+1;
switch (toVersion) {
case 2:
convertNameProperty(app, db, OCLASS_PERSPECTIVE);
convertNameProperty(app, db, OCLASS_ITEM);
break;
case 3:
onInstall(app, db);
break;
case 4:
OIndex<?> index = db.getMetadata().getIndexManager().getIndex(OCLASS_PERSPECTIVE + ".name");
if(index!=null) index.delete();
onInstall(app, db);
case 5:
OSchemaHelper.bind(db)
.oClass(OIdentity.CLASS_NAME)
.oProperty("perspective", OType.LINK).linkedClass(OCLASS_PERSPECTIVE);
default:
break;
}
if(toVersion<newVersion) onUpdate(app, db, toVersion, newVersion);
}
private void convertNameProperty(OrienteerWebApplication app, ODatabaseDocument db, String className) {
boolean wasInTransacton = db.getTransaction().isActive();
db.commit();
for(ODocument doc : db.browseClass(className)) {
Object value = doc.field("name");
if(value instanceof String) {
doc.field("temp", doc.field("name"));
doc.field("name", (String) null);
doc.save();
}
}
OClass oClass = db.getMetadata().getSchema().getClass(className);
oClass.dropProperty("name");
OProperty nameProperty = oClass.createProperty("name", OType.EMBEDDEDMAP);
CustomAttribute.VISUALIZATION_TYPE.setValue(nameProperty, "localization");
for(ODocument doc : db.browseClass(className)) {
if(doc.containsField("temp")) {
doc.field("name", CommonUtils.toMap("en", doc.field("temp")));
doc.removeField("temp");
doc.save();
}
}
if(wasInTransacton) db.begin();
}
private ODocument runtimeRepairDefaultPerspective()
{
return new DBClosure<ODocument>() {
@Override
protected ODocument execute(ODatabaseDocument db) {
ODocument perspective = new ODocument(OCLASS_PERSPECTIVE);
perspective.field("name", CommonUtils.toMap("en", DEFAULT_PERSPECTIVE));
perspective.field("homeUrl", "/classes");
perspective.save();
ODocument item = new ODocument(OCLASS_ITEM);
item.field("name", CommonUtils.toMap("en", "Users"));
item.field("icon", "users");
item.field("url", "/browse/OUser");
item.field("perspective", perspective);
item.save();
item = new ODocument(OCLASS_ITEM);
item.field("name", CommonUtils.toMap("en", "Roles"));
item.field("icon", "users");
item.field("url", "/browse/ORole");
item.field("perspective", perspective);
item.save();
item = new ODocument(OCLASS_ITEM);
item.field("name", CommonUtils.toMap("en", "Schema"));
item.field("icon", "cubes");
item.field("url", "/schema");
item.field("perspective", perspective);
item.save();
item = new ODocument(OCLASS_ITEM);
item.field("name", CommonUtils.toMap("en", "Localization"));
item.field("icon", "language");
item.field("url", "/browse/OLocalization");
item.field("perspective", perspective);
item.save();
item = new ODocument(OCLASS_ITEM);
item.field("name", CommonUtils.toMap("en", "Perspectives"));
item.field("icon", "desktop");
item.field("url", "/browse/OPerspective");
item.field("perspective", perspective);
item.save();
return perspective;
}
}.execute();
}
public ODocument getPerspectiveByName(ODatabaseDocument db, String name)
{
List<ODocument> perspectives = db.query(new OSQLSynchQuery<ODocument>("select from "+OCLASS_PERSPECTIVE+" where name CONTAINSVALUE ?"), name);
if(perspectives!=null && !perspectives.isEmpty())
{
return perspectives.get(0);
}
else
{
return null;
}
}
public ODocument getDefaultPerspective(ODatabaseDocument db, OUser user)
{
if(user!=null)
{
Object perspectiveObj = user.getDocument().field("perspective");
if(perspectiveObj!=null && perspectiveObj instanceof OIdentifiable)
return (ODocument)((OIdentifiable)perspectiveObj).getRecord();
Set<ORole> roles = user.getRoles();
ODocument perspective = null;
for (ORole oRole : roles)
{
perspective = getPerspectiveForORole(oRole);
if(perspective!=null) return perspective;
}
}
ODocument perspective = getPerspectiveByName(db, DEFAULT_PERSPECTIVE);
if(perspective==null)
{
perspective = runtimeRepairDefaultPerspective();
}
return perspective;
}
private ODocument getPerspectiveForORole(ORole role)
{
if(role==null) return null;
Object perspectiveObj = role.getDocument().field("perspective");
if(perspectiveObj!=null && perspectiveObj instanceof OIdentifiable)
return (ODocument)((OIdentifiable)perspectiveObj).getRecord();
else
{
ORole parentRole = role.getParentRole();
if(parentRole!=null && !parentRole.equals(role))
{
return getPerspectiveForORole(parentRole);
}
else
{
return null;
}
}
}
@Override
public void onInitialize(OrienteerWebApplication app, ODatabaseDocument db) {
OSchema schema = db.getMetadata().getSchema();
if(schema.getClass(OCLASS_PERSPECTIVE)==null || schema.getClass(OCLASS_ITEM)==null)
{
//Repair
onInstall(app, db);
}
}
}