-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathusage.html
More file actions
456 lines (384 loc) · 25 KB
/
Copy pathusage.html
File metadata and controls
456 lines (384 loc) · 25 KB
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.7.1 at 2017-03-16
| Rendered using Apache Maven Fluido Skin 1.5
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="Date-Revision-yyyymmdd" content="20170316" />
<meta http-equiv="Content-Language" content="en" />
<title>RDFBeans – RDFBeans Usage Guide</title>
<link rel="stylesheet" href="./css/apache-maven-fluido-1.5.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script type="text/javascript" src="./js/apache-maven-fluido-1.5.min.js"></script>
</head>
<body class="topBarDisabled">
<div class="container-fluid">
<div id="banner">
<div class="pull-left">
<div id="bannerLeft">
<h2>RDFBeans</h2>
</div>
</div>
<div class="pull-right"> </div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 2017-03-16
<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 2.2-SNAPSHOT
</li>
</ul>
</div>
<div class="row-fluid">
<div id="leftColumn" class="span2">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">RDFBeans</li>
<li>
<a href="index.html" title="Overview">
<span class="none"></span>
Overview</a>
</li>
<li class="active">
<a href="#"><span class="none"></span>Usage</a>
</li>
<li>
<a href="rdfbean.html" title="RDFBean format">
<span class="none"></span>
RDFBean format</a>
</li>
<li>
<a href="apidocs/index.html" title="JavaDocs">
<span class="none"></span>
JavaDocs</a>
</li>
<li>
<a href="http://github.com/cyberborean/rdfbeans" class="externalLink" title="GitHub project">
<span class="none"></span>
GitHub project</a>
</li>
<li class="nav-header">Project Documentation</li>
<li>
<a href="project-info.html" title="Project Information">
<span class="icon-chevron-right"></span>
Project Information</a>
</li>
<li>
<a href="project-reports.html" title="Project Reports">
<span class="icon-chevron-right"></span>
Project Reports</a>
</li>
</ul>
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
</a>
</div>
</div>
</div>
<div id="bodyColumn" class="span10" >
<h1>RDFBeans Usage Guide</h1>
<ul>
<li><a href="#Make_sure_that_your_Java_classes_or_interfaces_are_RDFBeans-compliant">Make sure that your Java classes or interfaces are RDFBeans-compliant</a></li>
<li><a href="#Add_required_RDFBeans_annotations">Add required RDFBeans annotations</a></li>
<li><a href="#Prepare_your_RDF_storage">Prepare your RDF storage</a></li>
<li><a href="#Go_with_RDFBeans">Go with RDFBeans</a></li>
<li><a href="#Adding_instances">Adding instances</a></li>
<li><a href="#Updating_instances">Updating instances</a></li>
<li><a href="#Retrieving_instances">Retrieving instances</a></li>
<li><a href="#Resolving_RDFBean_identifiers">Resolving RDFBean identifiers</a></li>
<li><a href="#Deleting_RDFBeans">Deleting RDFBeans</a></li>
<li><a href="#Cascade_databinding">Cascade databinding</a></li>
<li><a href="#Transactions">Transactions</a></li>
<li><a href="#Querying_the_model">Querying the model</a></li></ul>
<div class="section">
<h2><a name="Getting_started"></a>Getting started</h2>
<p>Persisting Java objects with RDF in your application requires few easy steps:</p>
<div class="section">
<h3><a name="Make_sure_that_your_Java_classes_or_interfaces_are_RDFBeans-compliant"></a>Make sure that your Java classes or interfaces are RDFBeans-compliant</h3>
<p>This basically means that every class or interface you intend to use within RDFBeans framework must obey general <a class="externalLink" href="http://en.wikipedia.org/wiki/JavaBean">JavaBeans conventions</a>: that is, the classes must have a public no-argument constructor and classes and interfaces must declare conventionally named getter and setter methods for the fields you plan to map to RDF properties. Serializability of the classes is not required.</p></div>
<div class="section">
<h3><a name="Add_required_RDFBeans_annotations"></a>Add required RDFBeans annotations</h3>
<p><i>RDFBean type declaration</i> (<tt>@RDFBean</tt>) declares that the class or interface is an RDFBean mapped to specified RDF type:</p>
<div class="source">
<div class="source"><pre class="prettyprint">@RDFBean("http://xmlns.com/foaf/0.1/Person")
public class Person
{ ...
</pre></div></div>
<p><i>Property declarations</i> (<tt>@RDF</tt>) are applied to the getter methods of the data properties to declare their RDF counterparts:</p>
<div class="source">
<div class="source"><pre class="prettyprint">@RDF("http://xmlns.com/foaf/0.1/name")
public String getName()
{ ...
</pre></div></div>
<p><i>Identifier property declaration</i> (<tt>@RDFSubject</tt>) is applied to a single getter method to mark that it returns an unique String value identifying an RDFBean instance.</p>
<p>Identifiers in RDF are URIs, so this method must either return a valid absolute URI, or a namespace prefix should be declared to construct the URI from the prefix value and the String, returned by the method:</p>
<div class="source">
<div class="source"><pre class="prettyprint">@RDFSubject
public String getUri()
{ ... // -- must return absolute URI
</pre></div></div>
<p>or</p>
<div class="source">
<div class="source"><pre class="prettyprint">@RDFSubject(prefix="http://some.uri.prefix/")
public String getId()
{ ... // -- returns an arbitrary string
</pre></div></div>
<p>For complete specification of RDFBeans annotation conventions and examples, please refer to <a href="rdfbean.html">RDFBeans classes and interfaces format specification</a>.</p></div>
<div class="section">
<h3><a name="Prepare_your_RDF_storage"></a>Prepare your RDF storage</h3>
<p>Set up and configure an <a class="externalLink" href="http://semanticweb.org/wiki/RDF2Go">RDF2Go</a>-supported RDF framework (Sesame or Jena) as a back-end to store RDF representations of your RDFBeans classes.</p></div>
<div class="section">
<h3><a name="Go_with_RDFBeans"></a>Go with RDFBeans</h3>
<p>Add, retrieve, modify and delete your RDFBean objects using <tt>RDFBeanManager</tt> class and RDF2Go <a class="externalLink" href="http://mavenrepo.fzi.de/semweb4j.org/site/rdf2go.api/apidocs/org/ontoware/rdf2go/model/Model.html">Model</a> implementation, as it’s shown below on this page.</p></div></div>
<div class="section">
<h2><a name="Classes_or_interfaces"></a>Classes or interfaces?</h2>
<p>Before you start, you need to decide which of two databinding techniques supported by RDFBeans framework to be used.</p>
<p>The first method is based on use of RDFBean classes and it is much more like a traditional JavaBeans persistence technique. Here you declare a RDFBean class with no-argument constructor, instantiate it and manipulate with properties data. At any time, you can dump (marshal) the object state to the RDF model and retrieve it from there.</p>
<p>The second method is based purely on the RDFBean interfaces. In this case, the special proxy objects are created dynamically to access the RDF data directly through RDFBean methods. Setting of a RDFBean property causes immediate update of the RDF model and the getter methods return actual values, retrieved from the model, so you don’t have to bother about state synchronization between your object model and RDF resources.</p>
<p>It is completely up to you which one method you should use in your application. Moreover, it is perfectly ok to use both methods at the same time and on the same RDF model.</p></div>
<div class="section">
<h2><a name="RDFBeanManager"></a>RDFBeanManager</h2>
<p>RDFBeans databinding functions are accessible as methods of a single <tt>RDFBeanManager</tt> class. An <tt>RDFBeanManager</tt> instance is created with a RDF2Go <a class="externalLink" href="http://mavenrepo.fzi.de/semweb4j.org/site/rdf2go.api/apidocs/org/ontoware/rdf2go/model/Model.html">Model</a> which provides an abstraction layer to access an underlying physical RDF storage. Currently, <a class="externalLink" href="http://semanticweb.org/wiki/RDF2Go">RDF2Go</a> project provides implementations of Model interface (adapters) for Sesame 2.x and Jena frameworks.</p>
<p>A Model instance is passed as an argument to the <tt>RDFBeanManager</tt> constructor. The Model implementations may require the model to be opened (initialized) before and closed after use. The following example illustrates how to setup RDFBeans databinding with a model adapter determined automatically via RDF2Go ModelFactory mechanism:</p>
<div class="source">
<div class="source"><pre class="prettyprint">import org.cyberborean.rdfbeans.RDFBeanManager;
import org.ontoware.rdf2go.ModelFactory;
import org.ontoware.rdf2go.RDF2Go;
import org.ontoware.rdf2go.model.Model;
...
ModelFactory modelFactory = RDF2Go.getModelFactory();
Model model = modelFactory.createModel();
model.open();
RDFBeanManager manager = new RDFBeanManager(model);
...
model.close();
</pre></div></div>
<p>An example with hardcoded Sesame 2.x NativeStore model implementation:</p>
<div class="source">
<div class="source"><pre class="prettyprint">import org.cyberborean.rdfbeans.RDFBeanManager;
import org.ontoware.rdf2go.model.Model;
import org.openrdf.rdf2go.RepositoryModel;
import org.openrdf.repository.Repository;
import org.openrdf.repository.sail.SailRepository;
import org.openrdf.sail.nativerdf.NativeStore;
...
Repository repository = new SailRepository(new NativeStore(new File("~/.sesame/test")));
repository.initialize();
Model model = new RepositoryModel(repository);
model.open();
RDFBeanManager manager = new RDFBeanManager(model);
...
model.close();
</pre></div></div>
<p>For detailed information on RDF2Go configuration for specific triple store adapters, please refer to <a class="externalLink" href="http://semanticweb.org/wiki/RDF2Go#Documentation_and_Tutorial">RDF2Go documentation</a>.</p></div>
<div class="section">
<h2><a name="Working_with_RDFBean_classes"></a>Working with RDFBean classes</h2>
<div class="section">
<h3><a name="Adding_instances"></a>Adding instances</h3>
<p>To add (marshall) a current state of an RDFBean object into the underlying RDF model, there is <tt>add()</tt> method:</p>
<div class="source">
<div class="source"><pre class="prettyprint">Person person = new Person();
person.setId("http://example.com/persons/jdoe");
person.setName("John Doe");
...
Resource r = manager.add(person);
</pre></div></div>
<p>If the RDFBean is not anonymous (i.e. has a not-null property annotated with <tt>@RDFSubject</tt> - see <a href="rdfbean.html">RDFBean format</a>), the method returns <a class="externalLink" href="http://mavenrepo.fzi.de/semweb4j.org/site/rdf2go.api/apidocs/org/ontoware/rdf2go/model/node/Resource.html">org.ontoware.rdf2go.model.node.Resource</a> object, representing an URI of RDF resource created in the model. Otherwise, the Resource result represents a <a class="externalLink" href="http://mavenrepo.fzi.de/semweb4j.org/site/rdf2go.api/apidocs/org/ontoware/rdf2go/model/node/BlankNode.html">org.ontoware.rdf2go.model.node.BlankNode</a> instance.</p></div>
<div class="section">
<h3><a name="Updating_instances"></a>Updating instances</h3>
<p><tt>update()</tt> method synchronizes the state of an RDFBean instance and the state of its RDF representation of in the model:</p>
<div class="source">
<div class="source"><pre class="prettyprint">...
person.setEmail("john.doe@example.com");
Resource r = manager.update(person);
</pre></div></div>
<p>The code above sets new property of our Person instance and updates it in the RDF model, thus synchronizing the RDF resource with the actual object state. Note that this method works properly only with unanonymous RDFBeans - otherwise, it would insert another BlankNode into the model (i.e. has the same behaviour as <tt>add()</tt>).</p></div>
<div class="section">
<h3><a name="Retrieving_instances"></a>Retrieving instances</h3>
<p>RDFBean class instances can be retrieved (unmarshalled) from their RDF representations using <tt>get()</tt> method:</p>
<div class="source">
<div class="source"><pre class="prettyprint">...
Person person2 = manager.get("http://example.com/persons/jdoe", Person.class);
</pre></div></div>
<p>This method returns new instance of specified RDFBean class filled with data retrieved from the RDF model.</p>
<p>In the example above, we assume that the RDFBean identifier has been declared without namespace prefix. Otherwise, we would have to pass only the local part of the identifier URI as an argument:</p>
<div class="source">
<div class="source"><pre class="prettyprint">... // assuming 'http://example.com/persons/' is a prefix
Person person2 = manager.get("jdoe", Person.class);
</pre></div></div>
<p>The <tt>get()</tt> method returns <tt>null</tt> if no RDF resource matching the given RDFBean identifier and class is found.</p>
<p>If we already have an RDF resource URI or a BlankNode (returned by <tt>add()</tt> or <tt>update()</tt> methods for instance), we can retrive the matching RDFBean instance using that value:</p>
<div class="source">
<div class="source"><pre class="prettyprint">...
Person person2 = (Person) manager.get(r);
</pre></div></div>
<p>The <tt>getAll()</tt> method iterates over all RDFBeans of a specified class in the model:</p>
<div class="source">
<div class="source"><pre class="prettyprint">// Displays the names of all Persons in the model:
ClosableIterator iter = manager.getAll(Person.class);
while (iter.hasNext()) {
Person p = (Person)iter.next();
System.out.println(p.getName());
}
iter.close();
</pre></div></div></div></div>
<div class="section">
<h2><a name="Working_with_RDFBean_interfaces"></a>Working with RDFBean interfaces</h2>
<p>This is an alternative mapping technique which is based on using RDFBean interfaces and dynamic proxy objects.</p>
<p>Let’s extract the interface from our RDFBean <tt>Person</tt> class and annotate it the same way:</p>
<div class="source">
<div class="source"><pre class="prettyprint">@RDFBean("http://xmlns.com/foaf/0.1/Person")
public interface IPerson {
@RDFSubject
String getId();
@RDF("http://xmlns.com/foaf/0.1/name")
String getName();
...
</pre></div></div>
<p>As we have this interface, we can map it directly to an RDF resource in the model. For that, we need to obtain an instance of the dynamic proxy object from RDFBeanManager:</p>
<div class="source">
<div class="source"><pre class="prettyprint">IPerson person = manager.create("http://example.com/persons/jdoe", IPerson.class);
</pre></div></div>
<p>The <tt>create()</tt> method returns an object implementing our <tt>IPerson</tt> interface and matching the RDFBean with the specified identifier in the model. This proxy object has the same behaviour as an instance of the class implementing that interface, with the exception that all its data is stored not in the Java heap, but directly in the underlying RDF model. So, the call:</p>
<div class="source">
<div class="source"><pre class="prettyprint">person.setName("John Doe");
</pre></div></div>
<p>will cause a statement with RDF property <tt>http://xmlns.com/foaf/0.1/name</tt> and the given literal value to be created or updated in the model. Similarly, the <tt>getName()</tt> method of the proxy would return this value addressing directly to that statement.</p>
<p>If no resource matching the specified RDFBean identifier exists in the model, <tt>create()</tt> returns an empty instance, that is all its <tt>getXXX()</tt> methods return nulls. The underlying RDF model will be unchanged until the first <tt>setXXX()</tt> method is called.</p>
<p>To instantiate the proxy objects for existing RDFBeans, the <tt>create()</tt> method with a Resource argument can be used. The method returns null if the specified Resource doesn’t exist in the model:</p>
<div class="source">
<div class="source"><pre class="prettyprint">IPerson person = manager.create(r);
</pre></div></div>
<p>The reference to the Resource can be obtained with <tt>getResource()</tt> method (see {Resolving RDFBean identifiers} below), or by querying the underlying RDF model (see Querying the model).</p></div>
<div class="section">
<h2><a name="Managing_RDFBeans_in_the_model"></a>Managing RDFBeans in the model</h2>
<div class="section">
<h3><a name="Resolving_RDFBean_identifiers"></a>Resolving RDFBean identifiers</h3>
<p>If an RDFBean identifier is known, it can be resolved to an RDF resource using the identifier’s String value and RDFBean class:</p>
<div class="source">
<div class="source"><pre class="prettyprint">...
Resource r = manager.getResource("http://example.com/persons/jdoe", Person.class);
</pre></div></div>
<p>or, if a namespace prefix is set for identifiers:</p>
<div class="source">
<div class="source"><pre class="prettyprint">... // assuming 'http://example.com/persons/' is a prefix
Resource r = manager.getResource("jdoe", Person.class);
</pre></div></div>
<p>The method returns null if no matching Resource is found in the model.</p></div>
<div class="section">
<h3><a name="Deleting_RDFBeans"></a>Deleting RDFBeans</h3>
<p>RDFBean representation can be deleted from RDF model with <tt>delete()</tt> method:</p>
<div class="source">
<div class="source"><pre class="prettyprint">...
manager.delete("http://example.com/persons/jdoe", Person.class);
</pre></div></div>
<p>or</p>
<div class="source">
<div class="source"><pre class="prettyprint">...
Resource r = manager.getResource("http://example.com/persons/jdoe", Person.class);
if (r != null) {
manager.delete(r);
}
</pre></div></div></div></div>
<div class="section">
<h2><a name="Advanced_topics"></a>Advanced topics</h2>
<div class="section">
<h3><a name="Cascade_databinding"></a>Cascade databinding</h3>
<p><tt>add()</tt> and <tt>update()</tt> methods performs cascade databinding, that is if a marshalling object has other RDFBeans as its properties, they are marshalled and added to the model recursively. It allows to manipulate with the whole complex object models with single method calls.</p>
<p>For example, let the <tt>Person</tt> class declares a <tt>knows</tt> property (probably, mapped to <tt>foaf:knows</tt>) to link Persons one another (for simplicity, put cardinality of this property to 1):</p>
<div class="source">
<div class="source"><pre class="prettyprint">Person john = new Person();
john.setId("http://example.com/persons/john");
...
Person mary = new Person();
mary.setId("http://example.com/persons/mary");
...
john.setKnows(mary);
</pre></div></div>
<p>Calling <tt>manager.add(john)</tt> will result in adding both objects (<tt>john</tt> and <tt>mary</tt>) and generating a statement to relate their RDF representations with the <tt>knows</tt> property.</p>
<p>Similarly, on retrieving the <tt>john</tt> object, the <tt>mary</tt> RDFBean will be automatically unmarshalled and assigned to <tt>john.knows</tt> property, thus reconstructing the whole graph of related objects.</p>
<p>The dynamic proxies follow the same principle: when a getter method is called and the property references to another RDFBean, the proxy object is automatically created and returned:</p>
<div class="source">
<div class="source"><pre class="prettyprint">IPerson john = manager.create("http://example.com/persons/john", IPerson.class);
IPerson mary = manager.create("http://example.com/persons/mary", IPerson.class);
john.setKnows(mary);
...
john.getKnows().setName("Mary"); // getKnows() returns the proxy equals to mary
System.out.println(mary.getName()); // -- will be "Mary"
</pre></div></div></div>
<div class="section">
<h3><a name="Transactions"></a>Transactions</h3>
<p>By default, each call of <tt>add()</tt>, <tt>update()</tt> or <tt>delete()</tt> methods will commit the transaction into a RDF store after an operation is completed. This behaviour can be changed by setting the autocommit mode to false with <tt>setAutocommit()</tt> method. If autocommit is off, the transactions can be commited by explicit calling of the <tt>commit()</tt> method of a underlying RDF2Go Model interface:</p>
<div class="source">
<div class="source"><pre class="prettyprint">// Adding multiple RDFBeans as a single transaction:
manager.setAutocommit(false);
for (Person p: persons) {
manager.add(p);
}
manager.getModel().commit();
</pre></div></div>
<p>Note that the autocommit mode in RDFBeanManager is unrelated to the autocommit settings of the underlying model. RDFBeanManager operations always set the autocommit flag of the model to false to avoid commiting every single RDF triple.</p>
<p>If dynamic proxies are used and autocommit mode is on, every setter method call will commit a transaction. You can turn the autocommit off for manual transaction management:</p>
<div class="source">
<div class="source"><pre class="prettyprint">manager.setAutocommit(false);
IPerson john = manager.create("http://example.com/persons/john", IPerson.class);
john.setName("John");
System.out.println(john.getName()); // -- will be null
manager.getModel().commit();
System.out.println(john.getName()); // -- and now it is "John"
</pre></div></div></div>
<div class="section">
<h3><a name="Querying_the_model"></a>Querying the model</h3>
<p>RDFBeans framework does not include its own facilities to query the RDF model, but it is possible to query the underlying RDF2Go model and retrieve RDFBean objects from results.</p>
<p>Example of querying with the triple patterns:</p>
<div class="source">
<div class="source"><pre class="prettyprint">// Find all persons with Google as a workplace homepage:
Set<Person> results = new HashSet<Person>();
URI predicate = model.createURI("http://xmlns.com/foaf/0.1/workplaceHomepage");
URI object = model.createURI("http://google.com");
ClosableIterator<Statement> ci = model.findStatements(Variable.ANY, predicate, object);
while (ci.hasNext()) {
Resource r = ci.next().getSubject();
results.add((Person)manager.get(r));
}
ci.close();
</pre></div></div>
<p>Example of using Sparql:</p>
<div class="source">
<div class="source"><pre class="prettyprint">Set<Person> results = new HashSet<Person>();
ClosableIterator<QueryRow> ci = model.sparqlSelect(
"SELECT ?r WHERE { ?r <http://xmlns.com/foaf/0.1/workplaceHomepage> <http://google.com> . }"
).iterator();
while (ci.hasNext()) {
Resource r = ci.next().getValue("r").asResource();
results.add((Person)manager.get(r));
}
ci.close();
</pre></div></div></div></div>
</div>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p >Copyright © 2017.
All rights reserved.
</p>
</div>
</div>
</footer>
</body>
</html>