/************************************************************************
* Copyright (c) 2014-2015 IoT-Solutions e.U.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
************************************************************************/
package iot.jcypher.domain;
import iot.jcypher.database.IDBAccess;
import iot.jcypher.graph.GrNode;
import iot.jcypher.graph.GrProperty;
import iot.jcypher.query.JcQuery;
import iot.jcypher.query.JcQueryResult;
import iot.jcypher.query.api.IClause;
import iot.jcypher.query.factories.clause.MATCH;
import iot.jcypher.query.factories.clause.RETURN;
import iot.jcypher.query.factories.clause.START;
import iot.jcypher.query.result.JcError;
import iot.jcypher.query.result.JcResultException;
import iot.jcypher.query.values.JcNode;
import iot.jcypher.util.Util;
import java.util.ArrayList;
import java.util.List;
/**
* Provides general informations about domains.
*
*/
public class DomainInformation {
private static final String DomainInfoNodeLabel = "DomainInfo";
private static final String DomainInfoNameProperty = "name";
private static final String DomainInfoLabel2ClassProperty = "label2ClassMap";
private IDBAccess dbAccess;
private String domainName;
private Long infoNodeId;
private IDomainAccess domainAccess;
private DomainInformation(IDBAccess dbAccess, String domainName) {
super();
this.dbAccess = dbAccess;
this.domainName = domainName;
}
/**
* answer the names of available domains.
* @param dbAccess
* @return a list of names of available domains
* in the graph database accessed through dbAccess.
*/
public static List<String> availableDomains(IDBAccess dbAccess) {
List<GrNode> resultList = loadAllDomainInfoNodes(dbAccess);
List<String> domains = new ArrayList<String>();
for (GrNode rNode : resultList) {
domains.add(rNode.getProperty(DomainInfoNameProperty).getValue().toString());
}
return domains;
}
/**
* create a DomainInformation object for a domain with name 'domainName'
* stored in a graphdatabase accessed via 'dbAccess'
* @param dbAccess
* @param domainName
* @return a DomainInformation object
*/
public static DomainInformation forDomain(IDBAccess dbAccess, String domainName) {
return new DomainInformation(dbAccess, domainName);
}
/**
* answer a list of DomainObjectTypes stored in the domain graph
* @return a list of DomainObjectTypes
*/
public List<DomainObjectType> getDomainObjectTypes() {
List<DomainObjectType> resultList = new ArrayList<DomainObjectType>();
GrNode infoNode = loadDomainInfoNode();
GrProperty prop = infoNode.getProperty(DomainInfoLabel2ClassProperty);
if (prop != null) {
@SuppressWarnings("unchecked")
List<String> val = (List<String>) prop.getValue();
for (String str : val) {
String[] c2l = str.split("=");
resultList.add(new DomainObjectType(c2l[1], c2l[0]));
}
}
return resultList;
}
/**
* answer a list of names of DomainObjectTypes stored in the domain graph
* @return a list of DomainObjectTypes
*/
public List<String> getDomainObjectTypeNames() {
List<DomainObjectType> types = getDomainObjectTypes();
List<String> typeNames = new ArrayList<String>(types.size());
for (DomainObjectType typ : types) {
typeNames.add(typ.getTypeName());
}
return typeNames;
}
/**
* answer the raw types (Java classes) of the list of DomainObjectTypes.
* <br/>Note: this may raise a ClassNotFoundException
* @param types list of DomainObjectTypes
* @return list of raw types (Java classes)
*/
public List<Class<?>> getRawTypes(List<DomainObjectType> types) {
List<Class<?>> resultList = new ArrayList<Class<?>>();
for (DomainObjectType type : types) {
resultList.add(type.getType());
}
return resultList;
}
/**
* answer a domain access object (IDomainAccess) to access (store, retrieve domain objects) this domain
* @return a domain access object (IDomainAccess)
*/
public IDomainAccess getDomainAccess() {
if (this.domainAccess == null) {
this.domainAccess = DomainAccessFactory.createDomainAccess(dbAccess, domainName);
}
return this.domainAccess;
}
/**
* answer a domain access object (IGenericDomainAccess) to access (store, retrieve domain objects) this domain.
* The returned domain access object works with a generic domain model.
* @return a domain access object (IDomainAccess)
*/
public IGenericDomainAccess getGenericDomainAccess() {
return getDomainAccess().getGenericDomainAccess();
}
private GrNode loadDomainInfoNode() {
GrNode infoNode = null;
if (this.infoNodeId == null) {
List<GrNode> resultList = loadAllDomainInfoNodes(dbAccess);
for (GrNode rNode : resultList) {
if (domainName.equals(rNode.getProperty(DomainInfoNameProperty).getValue().toString())) {
infoNode = rNode;
infoNodeId = new Long(rNode.getId());
}
}
} else {
JcNode n = new JcNode("n");
JcQuery query = new JcQuery();
query.setClauses(new IClause[] {
START.node(n).byId(infoNodeId.longValue()),
RETURN.value(n)
});
JcQueryResult result = dbAccess.execute(query);
List<JcError> errors = Util.collectErrors(result);
if (errors.size() > 0) {
throw new JcResultException(errors);
}
List<GrNode> resultList = result.resultOf(n);
// there must be exactly one node
infoNode = resultList.get(0);
}
return infoNode;
}
private static List<GrNode> loadAllDomainInfoNodes (IDBAccess dbAccess) {
JcNode n = new JcNode("n");
JcQuery query = new JcQuery();
query.setClauses(new IClause[] {
MATCH.node(n).label(DomainInfoNodeLabel),
RETURN.value(n)
});
JcQueryResult result = dbAccess.execute(query);
List<JcError> errors = Util.collectErrors(result);
if (errors.size() > 0) {
throw new JcResultException(errors);
}
return result.resultOf(n);
}
/*******************************************/
public class DomainObjectType {
private String typeName;
private String nodeLabel;
private Class<?> type;
private DomainObjectType(String typeName, String nodeLabel) {
super();
this.typeName = typeName;
this.nodeLabel = nodeLabel;
}
/**
* Answer the fully qualified name of the java type.
* @return the fully qualified name of the java type.
*/
public String getTypeName() {
return typeName;
}
/**
* Answer label of nodes to which domain objects of that type are mapped.
* @return a node label
*/
public String getNodeLabel() {
return nodeLabel;
}
/**
* Answer the java type (Class).
* Note: this may raise a ClassNotFoundException
* @return the java type
*/
public Class<?> getType() {
if (this.type == null) {
try {
this.type = Class.forName(this.typeName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
return type;
}
@Override
public String toString() {
return "DomainObjectType [typeName=" + typeName + "]";
}
}
}