1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
package com.c2kernel.persistency;
import com.c2kernel.entity.C2KLocalObject;
import com.c2kernel.persistency.outcome.Outcome;
import com.c2kernel.persistency.outcome.Viewpoint;
import com.c2kernel.process.auth.Authenticator;
import com.c2kernel.utils.Logger;
/** Interface for persistency managers of entities. It allows different kernel objects to be stored in different backend. For instance,
* Properties may be stored in LDAP, while Events, Outcomes and Viewpoints could be stored in a relational database. There are old generic
* query methods, but these are deprecated. The kernel does no analytical querying of the ClusterStorages, only simple gets and puts.
*
* Each first-level path under the Item is defined as a Cluster. Different Clusters may be stored in different places.
* Each ClusterStorage must support {@link #get(Integer, String)} and {@link #getClusterContents(Integer, String)} for clusters they return
* {@link #READ} and {@link #READWRITE} from queryClusterSupport
* and {@link #put(Integer, C2KLocalObject)} and {@link #delete(Integer, String)} for clusters they return {@link #WRITE} and {@link #READWRITE}
* from {@link #getClusterContents(Integer, String)}.
* Operations that have notbeen declared as not supported should throw a ClusterStorageException.
* If a cluster does not exist, get should return null, and delete should return with no action.
*/
public abstract class ClusterStorage {
/**
* Constant to return from {@link #queryClusterSupport(String)} for Cluster types this storage does not support.
*/
public static final short NONE = 0;
/**
* Constant to return from {@link #queryClusterSupport(String)} for Cluster types this storage can read from a database but not write.
* An example would be pre-existing data in a database that is mapped to Items in some way.
*/
public static final short READ = 1;
/**
* Constant to return from {@link #queryClusterSupport(String)} for Cluster types this storage can write to a database but not read.
* An example would be a realtime database export of data, which is transformed in an unrecoverable way for use in other systems.
*/
public static final short WRITE = 2;
/**
* Constant to return from {@link #queryClusterSupport(String)} for data stores that CRISTAL may use for both reading and writing for the given Cluster type.
*/
public static final short READWRITE = 3;
// Cluster types
/**
* The defined path of the root of the CRISTAL Kernel object cluster tree. A zero-length string.
*/
public static final String ROOT = "";
/**
* The root of the Property object cluster. All Property paths start with this. Defined as "Property". Properties are
* stored underneath according to their name e.g. "Property/Name"
*/
public static final String PROPERTY = "Property";
/**
* The root of the Collection object cluster. All Collection paths start with this. Defined as "Collection". Collections
* are stored underneath by name e.g. "Collection/Composition"
*/
public static final String COLLECTION = "Collection";
/**
* The cluster which holds the Item workflow. Defined as "LifeCycle". Holds the workflow inside, which is named "workflow",
* hence "LifeCycle/workflow".
* @see com.c2kernel.lifecycle.instance.Workflow
*/
public static final String LIFECYCLE = "LifeCycle";
/**
* This cluster holds all outcomes of this Item. The path to each outcome is "Outcome/<i>Schema Name</i>/<i>Schema Version</i>/<i>Event ID</i>"
*/
public static final String OUTCOME = "Outcome";
/**
* This is the cluster that contains all event for this Item. This cluster may be instantiated in a client as a History, which is a
* RemoteMap. Events are stored with their ID: "/AuditTrail/<i>Event ID</i>"
*/
public static final String HISTORY = "AuditTrail";
/**
* This cluster contains all viewpoints. Its name is defined as "ViewPoint". The paths of viewpoint objects stored here follow this pattern:
* "ViewPoint/<i>Schema Name</i>/<i>Viewpoint Name</i>"
*/
public static final String VIEWPOINT = "ViewPoint";
/**
* Agents store their persistent jobs in this cluster that have been pushed to them by activities configured to do so. The name is defined as "Job"
* and each new job received is assigned an integer ID one more than the highest already present.
*/
public static final String JOB = "Job";
/**
* An array of all currently supported cluster types, for iterative purposes.
*/
public static final String[] allClusterTypes = { PROPERTY, COLLECTION, LIFECYCLE, OUTCOME, HISTORY, VIEWPOINT, JOB };
// connection maintenance
public abstract void open(Authenticator auth)
throws ClusterStorageException;
public abstract void close()
throws ClusterStorageException;
// introspection
public abstract short queryClusterSupport(String clusterType);
public abstract String getName();
// for addressing queries
public abstract String getId();
/** Quickly gets the first string of the slashed path */
public static String getClusterType(String path) {
try {
if (path == null || path.length() == 0) return ClusterStorage.ROOT;
int start = path.charAt(0) == '/' ? 1 : 0;
int end = path.indexOf('/', start + 1);
if (end == -1) end = path.length();
return path.substring(start, end);
} catch (Exception ex) {
Logger.error(ex);
return ClusterStorage.ROOT;
}
}
public static String getPath(C2KLocalObject obj) {
String root = obj.getClusterType();
if (root == null) return null; // no storage allowed
if (obj instanceof Outcome) {
Outcome oc = (Outcome)obj;
return root+"/"+oc.getSchemaType()+"/"+oc.getSchemaVersion()+"/"+oc.getName();
}
else if (obj instanceof Viewpoint) {
Viewpoint vp = (Viewpoint)obj;
return root+"/"+vp.getSchemaName()+"/"+vp.getName();
}
else
return root+"/"+obj.getName();
}
/* object manipulation */
// retrieve object by path
public abstract C2KLocalObject get(Integer sysKey, String path)
throws ClusterStorageException;
// store object by path
public abstract void put(Integer sysKey, C2KLocalObject obj)
throws ClusterStorageException;
// delete cluster
public abstract void delete(Integer sysKey, String path)
throws ClusterStorageException;
// db specific queries
@Deprecated
public Object query(Object query)
throws ClusterStorageException {
throw new ClusterStorageException("Query not supported on this storage");
}
@Deprecated
public String queryToXML(String query, boolean genericFormat)
throws ClusterStorageException {
throw new ClusterStorageException("Query not supported on this storage");
}
// directory listing
public abstract String[] getClusterContents(Integer sysKey, String path)
throws ClusterStorageException;
}
|