diff options
Diffstat (limited to 'aai-core')
20 files changed, 1813 insertions, 744 deletions
diff --git a/aai-core/pom.xml b/aai-core/pom.xml index 22d6daf8..fb0b985d 100644 --- a/aai-core/pom.xml +++ b/aai-core/pom.xml @@ -22,7 +22,126 @@ <sonar.jacoco.reportPath>${project.build.directory}/coverage-reports/jacoco.exec</sonar.jacoco.reportPath> <sonar.jacoco.reportMissing.force.zero>false</sonar.jacoco.reportMissing.force.zero> <sonar.projectVersion>${project.version}</sonar.projectVersion> + <gendoc.version>v10</gendoc.version> + <aai.wiki.link>https://wiki.onap.org/</aai.wiki.link> </properties> + <profiles> + <profile> + <id>generateXsd</id> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.1.1</version> + <executions> + <execution> + <phase>process-classes</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>org.openecomp.aai.util.GenerateXsd</mainClass> + <systemProperties> + <systemProperty> + <key>gen_version</key> + <value>${gendoc.version}</value> + </systemProperty> + <systemProperty> + <key>gen_type</key> + <value>XSD</value> + </systemProperty> + <systemProperty> + <key>yamlresponses_url</key> + <value></value> + </systemProperty> + <systemProperty> + <key>yamlresponses_label</key> + <value></value> + </systemProperty> + </systemProperties> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>generateYaml</id> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.1.1</version> + <executions> + <execution> + <phase>process-classes</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>org.openecomp.aai.util.GenerateXsd</mainClass> + <systemProperties> + <systemProperty> + <key>gen_version</key> + <value>${gendoc.version}</value> + </systemProperty> + <systemProperty> + <key>gen_type</key> + <value>YAML</value> + </systemProperty> + <systemProperty> + <key>yamlresponses_url</key> + <value>${aai.wiki.link}</value> + </systemProperty> + <systemProperty> + <key>yamlresponses_label</key> + <value>Response codes found in [response codes]</value> + </systemProperty> + </systemProperties> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>generateHtml</id> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.1.1</version> + <executions> + <execution> + <phase>process-classes</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>org.openecomp.aai.util.swagger.GenerateSwagger</mainClass> + <systemProperties> + <property> + <key>aai.generate.version</key> + <value>${gendoc.version}</value> + </property> + <property> + <key>aai.wiki.link</key> + <value>${aai.wiki.link}</value> + </property> + </systemProperties> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> <dependencies> <dependency> <groupId>org.onap.aai.aai-common</groupId> @@ -190,6 +309,11 @@ <version>2.1.4</version> </dependency> <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-yaml</artifactId> + <version>2.1.4</version> + </dependency> + <dependency> <groupId>xml-apis</groupId> <artifactId>xml-apis</artifactId> <version>1.0.b2</version> diff --git a/aai-core/src/main/java/org/openecomp/aai/dbgen/DataGrooming.java b/aai-core/src/main/java/org/openecomp/aai/dbgen/DataGrooming.java index d1480d15..2acfe904 100644 --- a/aai-core/src/main/java/org/openecomp/aai/dbgen/DataGrooming.java +++ b/aai-core/src/main/java/org/openecomp/aai/dbgen/DataGrooming.java @@ -39,6 +39,8 @@ import java.util.Set; import java.util.UUID; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Property; @@ -53,6 +55,8 @@ import org.openecomp.aai.introspection.LoaderFactory; import org.openecomp.aai.introspection.ModelType; import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.serialization.db.EdgeProperties; +import org.openecomp.aai.serialization.db.EdgeProperty; import org.openecomp.aai.util.AAIConfig; import org.openecomp.aai.util.AAIConstants; import org.openecomp.aai.util.FormatDate; @@ -64,7 +68,6 @@ import com.thinkaurelius.titan.core.TitanEdge; import com.thinkaurelius.titan.core.TitanFactory; import com.thinkaurelius.titan.core.TitanGraph; import com.thinkaurelius.titan.core.TitanTransaction; -import com.thinkaurelius.titan.core.TitanVertex; public class DataGrooming { @@ -199,6 +202,7 @@ public class DataGrooming { System.exit(1); } + try { if (!prevFileName.equals("")) { // They are trying to fix some data based on a data in a @@ -380,16 +384,16 @@ public class DataGrooming { String emsg = "null graphTransaction object in DataGrooming\n"; throw new AAIException("AAI_6101", emsg); } - + GraphTraversalSource source1 = g.traversal(); ArrayList<String> errArr = new ArrayList<>(); int totalNodeCount = 0; HashMap<String, String> misMatchedHash = new HashMap<String, String>(); - HashMap<String, TitanVertex> orphanNodeHash = new HashMap<String, TitanVertex>(); - HashMap<String, TitanVertex> missingDepNodeHash = new HashMap<String, TitanVertex>(); + HashMap<String, Vertex> orphanNodeHash = new HashMap<String, Vertex>(); + HashMap<String, Vertex> missingDepNodeHash = new HashMap<String, Vertex>(); HashMap<String, Edge> oneArmedEdgeHash = new HashMap<String, Edge>(); HashMap<String, String> emptyVertexHash = new HashMap<String, String>(); - HashMap<String, TitanVertex> ghostNodeHash = new HashMap<String, TitanVertex>(); + HashMap<String, Vertex> ghostNodeHash = new HashMap<String, Vertex>(); ArrayList<String> dupeGroups = new ArrayList<>(); Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, AAIProperties.LATEST); @@ -419,15 +423,14 @@ public class DataGrooming { // Loop through all the nodes of this Node type int lastShownForNt = 0; - ArrayList <TitanVertex> tmpList = new ArrayList <> (); - Iterable <?> verts = g.query().has("aai-node-type",nType).vertices(); - Iterator<?> iterv = verts.iterator(); + ArrayList <Vertex> tmpList = new ArrayList <> (); + Iterator <Vertex> iterv = source1.V().has("aai-node-type",nType); while (iterv.hasNext()) { // We put the nodes into an ArrayList because the graph.query iterator can time out - tmpList.add((TitanVertex)iterv.next()); + tmpList.add(iterv.next()); } - Iterator <?> iter = tmpList.iterator(); + Iterator <Vertex> iter = tmpList.iterator(); while (iter.hasNext()) { try { thisNtCount++; @@ -435,14 +438,14 @@ public class DataGrooming { lastShownForNt = thisNtCount; LOGGER.debug("count for " + nType + " so far = " + thisNtCount ); } - TitanVertex thisVtx = (TitanVertex) iter.next(); + Vertex thisVtx = iter.next(); String thisVid = thisVtx.id().toString(); if (processedVertices.contains(thisVid)) { LOGGER.debug("skipping already processed vertex: " + thisVid); continue; } totalNodeCount++; - List <TitanVertex> secondGetList = new ArrayList <> (); + List <Vertex> secondGetList = new ArrayList <> (); // ----------------------------------------------------------------------- // For each vertex of this nodeType, we want to: // a) make sure that it can be retrieved using it's AAI defined key @@ -470,19 +473,18 @@ public class DataGrooming { if( depNodeTypes.isEmpty() ){ // This kind of node is not dependent on any other. // Make sure we can get it back using it's key properties and that we only get one. - secondGetList = getNodeJustUsingKeyParams( TRANSID, FROMAPPID, g, nType, + secondGetList = getNodeJustUsingKeyParams( TRANSID, FROMAPPID, source1, nType, propHashWithKeys, version ); } else { // This kind of node is dependent on another for uniqueness. // Start at it's parent (the dependent vertex) and make sure we can get it // back using it's key properties and that we only get one. - Iterable <?> verts2 = thisVtx.query().direction(Direction.IN).has("isParent",true).vertices(); - Iterator <?> vertI2 = verts2.iterator(); - TitanVertex parentVtx = null; + Iterator <Vertex> vertI2 = source1.V(thisVtx).union(__.inE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true).outV(), __.outE().has(EdgeProperties.in(EdgeProperty.IS_PARENT)).inV()); + Vertex parentVtx = null; int pCount = 0; while( vertI2 != null && vertI2.hasNext() ){ - parentVtx = (TitanVertex) vertI2.next(); + parentVtx = vertI2.next(); pCount++; } if( pCount <= 0 ){ @@ -543,12 +545,12 @@ public class DataGrooming { // We found the parent - so use it to do the second-look. // NOTE --- We're just going to do the same check from the other direction - because // there could be duplicates or the pointer going the other way could be broken - ArrayList <TitanVertex> tmpListSec = new ArrayList <> (); + ArrayList <Vertex> tmpListSec = new ArrayList <> (); - tmpListSec = getConnectedChildrenOfOneType( g, parentVtx, nType ) ; - Iterator<TitanVertex> vIter = tmpListSec.iterator(); + tmpListSec = getConnectedChildrenOfOneType( source1, parentVtx, nType ) ; + Iterator<Vertex> vIter = tmpListSec.iterator(); while (vIter.hasNext()) { - TitanVertex tmpV = vIter.next(); + Vertex tmpV = vIter.next(); if( vertexHasTheseKeys(tmpV, propHashWithKeys) ){ secondGetList.add(tmpV); } @@ -580,7 +582,7 @@ public class DataGrooming { // Found some DUPLICATES - need to process them LOGGER.info(" - now check Dupes for this guy - "); List<String> tmpDupeGroups = checkAndProcessDupes( - TRANSID, FROMAPPID, g, version, + TRANSID, FROMAPPID, g, source1, version, nType, secondGetList, dupeFixOn, deleteCandidateList, singleCommits, dupeGroups, loader); Iterator<String> dIter = tmpDupeGroups.iterator(); @@ -710,7 +712,7 @@ public class DataGrooming { } String vNtI = ""; String vIdI = ""; - TitanVertex ghost2 = null; + Vertex ghost2 = null; Boolean keysMissing = true; Boolean cantGetUsingVid = false; @@ -729,7 +731,7 @@ public class DataGrooming { } if( ! ghost2CheckOff ){ - TitanVertex connectedVert = g2.getVertex(vIdLong); + Vertex connectedVert = g2.getVertex(vIdLong); if( connectedVert == null ) { LOGGER.warn( "GHOST2 -- got NULL when doing getVertex for vid = " + vIdLong); cantGetUsingVid = true; @@ -842,7 +844,7 @@ public class DataGrooming { } if( ! ghost2CheckOff ){ - TitanVertex connectedVert = g2.getVertex(vIdLong); + Vertex connectedVert = g2.getVertex(vIdLong); if( connectedVert == null ) { cantGetUsingVid = true; LOGGER.info( "GHOST2 -- got NULL when doing getVertex for vid = " + vIdLong); @@ -972,13 +974,13 @@ public class DataGrooming { + misMatchedHash.size() + "\n"); bw.write("\n ------------- Delete Candidates ---------\n"); - for (Map.Entry<String, TitanVertex> entry : ghostNodeHash + for (Map.Entry<String, Vertex> entry : ghostNodeHash .entrySet()) { String vid = entry.getKey(); bw.write("DeleteCandidate: Phantom Vid = [" + vid + "]\n"); cleanupCandidateCount++; } - for (Map.Entry<String, TitanVertex> entry : orphanNodeHash + for (Map.Entry<String, Vertex> entry : orphanNodeHash .entrySet()) { String vid = entry.getKey(); bw.write("DeleteCandidate: OrphanDepNode Vid = [" + vid + "]\n"); @@ -991,7 +993,7 @@ public class DataGrooming { bw.write("DeleteCandidate: Bad EDGE Edge-id = [" + eid + "]\n"); cleanupCandidateCount++; } - for (Map.Entry<String, TitanVertex> entry : missingDepNodeHash + for (Map.Entry<String, Vertex> entry : missingDepNodeHash .entrySet()) { String vid = entry.getKey(); bw.write("DeleteCandidate: (maybe) missingDepNode Vid = [" @@ -1001,7 +1003,7 @@ public class DataGrooming { bw.write("\n-- NOTE - To see DeleteCandidates for Duplicates, you need to look in the Duplicates Detail section below.\n"); bw.write("\n ------------- GHOST NODES - detail "); - for (Map.Entry<String, TitanVertex> entry : ghostNodeHash + for (Map.Entry<String, Vertex> entry : ghostNodeHash .entrySet()) { try { String vid = entry.getKey(); @@ -1023,7 +1025,7 @@ public class DataGrooming { } bw.write("\n ------------- Missing Dependent Edge ORPHAN NODES - detail: "); - for (Map.Entry<String, TitanVertex> entry : orphanNodeHash + for (Map.Entry<String, Vertex> entry : orphanNodeHash .entrySet()) { try { String vid = entry.getKey(); @@ -1045,7 +1047,7 @@ public class DataGrooming { } bw.write("\n ------------- Missing Dependent Edge (but not orphan) NODES: "); - for (Map.Entry<String, TitanVertex> entry : missingDepNodeHash + for (Map.Entry<String, Vertex> entry : missingDepNodeHash .entrySet()) { try { String vid = entry.getKey(); @@ -1113,9 +1115,9 @@ public class DataGrooming { idArr.add(vidString); long longVertId = Long.parseLong(vidString); Iterator<Vertex> vtxIterator = g.vertices(longVertId); - TitanVertex vtx = null; + Vertex vtx = null; if (vtxIterator.hasNext()) { - vtx = (TitanVertex)vtxIterator.next(); + vtx = vtxIterator.next(); } ArrayList<String> retArr = showPropertiesForNode(TRANSID, FROMAPPID, vtx); for (String info : retArr) { @@ -1269,7 +1271,7 @@ public class DataGrooming { * @param propHashWithKeys the prop hash with keys * @return the boolean */ - private static Boolean vertexHasTheseKeys( TitanVertex tmpV, HashMap <String, Object> propHashWithKeys) { + private static Boolean vertexHasTheseKeys( Vertex tmpV, HashMap <String, Object> propHashWithKeys) { Iterator <?> it = propHashWithKeys.entrySet().iterator(); while( it.hasNext() ){ String propName = ""; @@ -1398,19 +1400,19 @@ public class DataGrooming { * @param g the g * @param dupeVertexList the dupe vertex list * @param ver the ver - * @return TitanVertex + * @return Vertex * @throws AAIException the AAI exception */ - public static TitanVertex getPreferredDupe(String transId, - String fromAppId, TitanTransaction g, - ArrayList<TitanVertex> dupeVertexList, String ver, Loader loader) + public static Vertex getPreferredDupe(String transId, + String fromAppId, GraphTraversalSource g, + ArrayList<Vertex> dupeVertexList, String ver, Loader loader) throws AAIException { // This method assumes that it is being passed a List of vertex objects // which // violate our uniqueness constraints. - TitanVertex nullVtx = null; + Vertex nullVtx = null; if (dupeVertexList == null) { return nullVtx; @@ -1420,13 +1422,13 @@ public class DataGrooming { return nullVtx; } if (listSize == 1) { - return ((TitanVertex) dupeVertexList.get(0)); + return (dupeVertexList.get(0)); } - TitanVertex vtxPreferred = null; - TitanVertex currentFaveVtx = (TitanVertex) dupeVertexList.get(0); + Vertex vtxPreferred = null; + Vertex currentFaveVtx = dupeVertexList.get(0); for (int i = 1; i < listSize; i++) { - TitanVertex vtxB = (TitanVertex) dupeVertexList.get(i); + Vertex vtxB = dupeVertexList.get(i); vtxPreferred = pickOneOfTwoDupes(transId, fromAppId, g, currentFaveVtx, vtxB, ver, loader); if (vtxPreferred == null) { @@ -1450,15 +1452,15 @@ public class DataGrooming { * @param vtxA the vtx A * @param vtxB the vtx B * @param ver the ver - * @return TitanVertex + * @return Vertex * @throws AAIException the AAI exception */ - public static TitanVertex pickOneOfTwoDupes(String transId, - String fromAppId, TitanTransaction g, TitanVertex vtxA, - TitanVertex vtxB, String ver, Loader loader) throws AAIException { + public static Vertex pickOneOfTwoDupes(String transId, + String fromAppId, GraphTraversalSource g, Vertex vtxA, + Vertex vtxB, String ver, Loader loader) throws AAIException { - TitanVertex nullVtx = null; - TitanVertex preferredVtx = null; + Vertex nullVtx = null; + Vertex preferredVtx = null; Long vidA = new Long(vtxA.id().toString()); Long vidB = new Long(vtxB.id().toString()); @@ -1520,11 +1522,11 @@ public class DataGrooming { HashMap<String, String> nodeTypesConn2A = new HashMap<>(); HashMap<String, String> nodeTypesConn2B = new HashMap<>(); - ArrayList<TitanVertex> vertListA = getConnectedNodes( g, vtxA ); + ArrayList<Vertex> vertListA = getConnectedNodes( g, vtxA ); if (vertListA != null) { - Iterator<TitanVertex> iter = vertListA.iterator(); + Iterator<Vertex> iter = vertListA.iterator(); while (iter.hasNext()) { - TitanVertex tvCon = iter.next(); + Vertex tvCon = iter.next(); String conVid = tvCon.id().toString(); String nt = ""; objType = tvCon.<Object>property("aai-node-type").orElse(null); @@ -1536,11 +1538,11 @@ public class DataGrooming { } } - ArrayList<TitanVertex> vertListB = getConnectedNodes( g, vtxB ); + ArrayList<Vertex> vertListB = getConnectedNodes( g, vtxB ); if (vertListB != null) { - Iterator<TitanVertex> iter = vertListB.iterator(); + Iterator<Vertex> iter = vertListB.iterator(); while (iter.hasNext()) { - TitanVertex tvCon = iter.next(); + Vertex tvCon = iter.next(); String conVid = tvCon.id().toString(); String nt = ""; objType = tvCon.<Object>property("aai-node-type").orElse(null); @@ -1663,13 +1665,13 @@ public class DataGrooming { * @return the array list */ private static List<String> checkAndProcessDupes(String transId, - String fromAppId, TitanTransaction g, String version, String nType, - List<TitanVertex> passedVertList, Boolean dupeFixOn, + String fromAppId, TitanTransaction g, GraphTraversalSource source, String version, String nType, + List<Vertex> passedVertList, Boolean dupeFixOn, Set<String> deleteCandidateList, Boolean singleCommits, ArrayList<String> alreadyFoundDupeGroups, Loader loader ) { ArrayList<String> returnList = new ArrayList<>(); - ArrayList<TitanVertex> checkVertList = new ArrayList<>(); + ArrayList<Vertex> checkVertList = new ArrayList<>(); ArrayList<String> alreadyFoundDupeVidArr = new ArrayList<>(); Boolean noFilterList = true; Iterator<String> afItr = alreadyFoundDupeGroups.iterator(); @@ -1710,9 +1712,9 @@ public class DataGrooming { // not process any vertices that we've already seen. try { - Iterator<TitanVertex> pItr = passedVertList.iterator(); + Iterator<Vertex> pItr = passedVertList.iterator(); while (pItr.hasNext()) { - TitanVertex tvx = (TitanVertex) pItr.next(); + Vertex tvx = pItr.next(); String passedId = tvx.id().toString(); if (noFilterList || !alreadyFoundDupeVidArr.contains(passedId)) { // We haven't seen this one before - so we should check it. @@ -1733,12 +1735,12 @@ public class DataGrooming { String dupesStr = ""; for (int i = 0; i < checkVertList.size(); i++) { dupesStr = dupesStr - + ((TitanVertex) (checkVertList.get(i))).id() + + ((checkVertList.get(i))).id() .toString() + "|"; } if (dupesStr != "") { - TitanVertex prefV = getPreferredDupe(transId, fromAppId, - g, checkVertList, version, loader); + Vertex prefV = getPreferredDupe(transId, fromAppId, + source, checkVertList, version, loader); if (prefV == null) { // We could not determine which duplicate to keep dupesStr = dupesStr + "KeepVid=UNDETERMINED"; @@ -1767,12 +1769,12 @@ public class DataGrooming { // are also pointing at the same 'parent' node. // Note: for a given set of key data, it is possible that there // could be more than one set of duplicates. - HashMap<String, ArrayList<TitanVertex>> vertsGroupedByParentHash = groupVertsByDepNodes( - transId, fromAppId, g, version, nType, + HashMap<String, ArrayList<Vertex>> vertsGroupedByParentHash = groupVertsByDepNodes( + transId, fromAppId, source, version, nType, checkVertList, loader); - for (Map.Entry<String, ArrayList<TitanVertex>> entry : vertsGroupedByParentHash + for (Map.Entry<String, ArrayList<Vertex>> entry : vertsGroupedByParentHash .entrySet()) { - ArrayList<TitanVertex> thisParentsVertList = entry + ArrayList<Vertex> thisParentsVertList = entry .getValue(); if (thisParentsVertList.size() > 1) { // More than one vertex found with the same key info @@ -1780,12 +1782,12 @@ public class DataGrooming { String dupesStr = ""; for (int i = 0; i < thisParentsVertList.size(); i++) { dupesStr = dupesStr - + ((TitanVertex) (thisParentsVertList + + ((thisParentsVertList .get(i))).id() + "|"; } if (dupesStr != "") { - TitanVertex prefV = getPreferredDupe(transId, - fromAppId, g, thisParentsVertList, + Vertex prefV = getPreferredDupe(transId, + fromAppId, source, thisParentsVertList, version, loader); if (prefV == null) { @@ -1835,9 +1837,9 @@ public class DataGrooming { * @return the hash map * @throws AAIException the AAI exception */ - private static HashMap<String, ArrayList<TitanVertex>> groupVertsByDepNodes( - String transId, String fromAppId, TitanTransaction g, String version, - String nType, ArrayList<TitanVertex> passedVertList, Loader loader) + private static HashMap<String, ArrayList<Vertex>> groupVertsByDepNodes( + String transId, String fromAppId, GraphTraversalSource g, String version, + String nType, ArrayList<Vertex> passedVertList, Loader loader) throws AAIException { // Given a list of Titan Vertices of one nodeType (see AAI-8956), group // them together by the parent node they depend on. @@ -1847,7 +1849,7 @@ public class DataGrooming { // we're trying to find duplicates - so we // allow for the case where more than one is under the same parent node. - HashMap<String, ArrayList<TitanVertex>> retHash = new HashMap<String, ArrayList<TitanVertex>>(); + HashMap<String, ArrayList<Vertex>> retHash = new HashMap<String, ArrayList<Vertex>>(); if (loader.introspectorFromName(nType).isTopLevel()) { // This method really should not have been called if this is not the // kind of node @@ -1866,10 +1868,10 @@ public class DataGrooming { // For each vertex, we want find its depended-on/parent vertex so we // can track what other vertexes that are dependent on that same guy. if (passedVertList != null) { - Iterator<TitanVertex> iter = passedVertList.iterator(); + Iterator<Vertex> iter = passedVertList.iterator(); while (iter.hasNext()) { - TitanVertex thisVert = iter.next(); - TitanVertex tmpParentVtx = getConnectedParent( g, thisVert ); + Vertex thisVert = iter.next(); + Vertex tmpParentVtx = getConnectedParent( g, thisVert ); if( tmpParentVtx != null ) { String parentNt = null; Object obj = tmpParentVtx.<Object>property("aai-node-type").orElse(null); @@ -1884,7 +1886,7 @@ public class DataGrooming { retHash.get(parentVid).add(thisVert); } else { // This is the first one we found on this parent - ArrayList<TitanVertex> vList = new ArrayList<>(); + ArrayList<Vertex> vList = new ArrayList<>(); vList.add(thisVert); retHash.put(parentVid, vList); } @@ -1960,7 +1962,7 @@ public class DataGrooming { try { long longVertId = Long .parseLong(thisVid); - TitanVertex vtx = g + Vertex vtx = g .getVertex(longVertId); vtx.remove(); if (singleCommits) { @@ -2005,10 +2007,10 @@ public class DataGrooming { * @return the node just using key params * @throws AAIException the AAI exception */ - public static List <TitanVertex> getNodeJustUsingKeyParams( String transId, String fromAppId, TitanTransaction graph, String nodeType, + public static List <Vertex> getNodeJustUsingKeyParams( String transId, String fromAppId, GraphTraversalSource graph, String nodeType, HashMap<String,Object> keyPropsHash, String apiVersion ) throws AAIException{ - List <TitanVertex> retVertList = new ArrayList <> (); + List <Vertex> retVertList = new ArrayList <> (); // We assume that all NodeTypes have at least one key-property defined. // Note - instead of key-properties (the primary key properties), a user could pass @@ -2026,32 +2028,32 @@ public class DataGrooming { kVal.add(i, entry.getValue()); } int topPropIndex = i; - TitanVertex tiV = null; + Vertex tiV = null; String propsAndValuesForMsg = ""; - Iterable <?> verts = null; + Iterator <Vertex> verts = null; try { if( topPropIndex == 0 ){ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ") "; - verts= graph.query().has(kName.get(0),kVal.get(0)).has("aai-node-type",nodeType).vertices(); + verts= graph.V().has(kName.get(0),kVal.get(0)).has("aai-node-type",nodeType); } else if( topPropIndex == 1 ){ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", " + kName.get(1) + " = " + kVal.get(1) + ") "; - verts = graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has("aai-node-type",nodeType).vertices(); + verts = graph.V().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has("aai-node-type",nodeType); } else if( topPropIndex == 2 ){ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", " + kName.get(1) + " = " + kVal.get(1) + ", " + kName.get(2) + " = " + kVal.get(2) + ") "; - verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has("aai-node-type",nodeType).vertices(); + verts= graph.V().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has("aai-node-type",nodeType); } else if( topPropIndex == 3 ){ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", " + kName.get(1) + " = " + kVal.get(1) + ", " + kName.get(2) + " = " + kVal.get(2) + ", " + kName.get(3) + " = " + kVal.get(3) + ") "; - verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has(kName.get(3),kVal.get(3)).has("aai-node-type",nodeType).vertices(); + verts= graph.V().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has(kName.get(3),kVal.get(3)).has("aai-node-type",nodeType); } else { throw new AAIException("AAI_6114", " We only support 4 keys per nodeType for now \n"); @@ -2062,9 +2064,8 @@ public class DataGrooming { } if( verts != null ){ - Iterator <?> vertI = verts.iterator(); - while( vertI.hasNext() ){ - tiV = (TitanVertex) vertI.next(); + while( verts.hasNext() ){ + tiV = verts.next(); retVertList.add(tiV); } } @@ -2086,7 +2087,7 @@ public class DataGrooming { * @param tVert the t vert * @return the array list */ - private static ArrayList <String> showAllEdgesForNode( String transId, String fromAppId, TitanVertex tVert ){ + private static ArrayList <String> showAllEdgesForNode( String transId, String fromAppId, Vertex tVert ){ ArrayList <String> retArr = new ArrayList <> (); Iterator <Edge> eI = tVert.edges(Direction.IN); @@ -2096,7 +2097,7 @@ public class DataGrooming { while( eI.hasNext() ){ TitanEdge ed = (TitanEdge) eI.next(); String lab = ed.label(); - TitanVertex vtx = (TitanVertex) ed.otherVertex(tVert); + Vertex vtx = ed.otherVertex(tVert); if( vtx == null ){ retArr.add(" >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< "); } @@ -2115,7 +2116,7 @@ public class DataGrooming { while( eI.hasNext() ){ TitanEdge ed = (TitanEdge) eI.next(); String lab = ed.label(); - TitanVertex vtx = (TitanVertex) ed.otherVertex(tVert); + Vertex vtx = ed.otherVertex(tVert); if( vtx == null ){ retArr.add(" >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< "); } @@ -2137,7 +2138,7 @@ public class DataGrooming { * @param tVert the t vert * @return the array list */ - private static ArrayList <String> showPropertiesForNode( String transId, String fromAppId, TitanVertex tVert ){ + private static ArrayList <String> showPropertiesForNode( String transId, String fromAppId, Vertex tVert ){ ArrayList <String> retArr = new ArrayList <> (); if( tVert == null ){ @@ -2166,19 +2167,19 @@ public class DataGrooming { } - private static ArrayList <TitanVertex> getConnectedNodes(TitanTransaction g, TitanVertex startVtx ) + private static ArrayList <Vertex> getConnectedNodes(GraphTraversalSource g, Vertex startVtx ) throws AAIException { - ArrayList <TitanVertex> retArr = new ArrayList <> (); + ArrayList <Vertex> retArr = new ArrayList <> (); if( startVtx == null ){ return retArr; } else { GraphTraversal<Vertex, Vertex> modPipe = null; - modPipe = g.traversal().V(startVtx).both(); + modPipe = g.V(startVtx).both(); if( modPipe != null && modPipe.hasNext() ){ while( modPipe.hasNext() ){ - TitanVertex conVert = (TitanVertex) modPipe.next(); + Vertex conVert = modPipe.next(); retArr.add(conVert); } } @@ -2188,15 +2189,14 @@ public class DataGrooming { }// End of getConnectedNodes() - private static ArrayList <TitanVertex> getConnectedChildrenOfOneType( TitanTransaction graph, - TitanVertex startVtx, String childNType ) throws AAIException{ + private static ArrayList <Vertex> getConnectedChildrenOfOneType( GraphTraversalSource g, + Vertex startVtx, String childNType ) throws AAIException{ - ArrayList <TitanVertex> childList = new ArrayList <> (); - Iterable <?> verts = startVtx.query().direction(Direction.OUT).has("isParent",true).vertices(); - Iterator <?> vertI = verts.iterator(); - TitanVertex tmpVtx = null; + ArrayList <Vertex> childList = new ArrayList <> (); + Iterator <Vertex> vertI = g.V(startVtx).union(__.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true), __.inE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true)).bothV(); + Vertex tmpVtx = null; while( vertI != null && vertI.hasNext() ){ - tmpVtx = (TitanVertex) vertI.next(); + tmpVtx = vertI.next(); Object ob = tmpVtx.<Object>property("aai-node-type").orElse(null); if (ob != null) { String tmpNt = ob.toString(); @@ -2211,15 +2211,14 @@ public class DataGrooming { }// End of getConnectedChildrenOfOneType() - private static TitanVertex getConnectedParent( TitanTransaction graph, - TitanVertex startVtx ) throws AAIException{ + private static Vertex getConnectedParent( GraphTraversalSource g, + Vertex startVtx ) throws AAIException{ - TitanVertex parentVtx = null; - Iterable <?> verts = startVtx.query().direction(Direction.IN).has("isParent",true).vertices(); - Iterator <?> vertI = verts.iterator(); + Vertex parentVtx = null; + Iterator <Vertex> vertI = g.V(startVtx).union(__.inE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true), __.outE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true)).bothV(); while( vertI != null && vertI.hasNext() ){ // Note - there better only be one! - parentVtx = (TitanVertex) vertI.next(); + parentVtx = vertI.next(); } return parentVtx; diff --git a/aai-core/src/main/java/org/openecomp/aai/introspection/generator/CreateExample.java b/aai-core/src/main/java/org/openecomp/aai/introspection/generator/CreateExample.java index a94d5406..fd258460 100644 --- a/aai-core/src/main/java/org/openecomp/aai/introspection/generator/CreateExample.java +++ b/aai-core/src/main/java/org/openecomp/aai/introspection/generator/CreateExample.java @@ -20,9 +20,9 @@ package org.openecomp.aai.introspection.generator; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; -import java.util.Random; import org.openecomp.aai.exceptions.AAIException; import org.openecomp.aai.introspection.Introspector; @@ -33,7 +33,7 @@ import org.openecomp.aai.introspection.Wanderer; public class CreateExample implements Wanderer { - private Random rand = new Random(); + private SecureRandom rand = new SecureRandom(); private final long range = 100000000L; private Loader loader = null; private Introspector result = null; diff --git a/aai-core/src/main/java/org/openecomp/aai/restcore/RESTAPI.java b/aai-core/src/main/java/org/openecomp/aai/restcore/RESTAPI.java index f1f53a4d..18aef073 100644 --- a/aai-core/src/main/java/org/openecomp/aai/restcore/RESTAPI.java +++ b/aai-core/src/main/java/org/openecomp/aai/restcore/RESTAPI.java @@ -44,8 +44,6 @@ import org.openecomp.aai.introspection.tools.RemoveNonVisibleProperty; import org.openecomp.aai.logging.ErrorLogHelper; import org.openecomp.aai.logging.LoggingContext; import org.openecomp.aai.util.AAIConfig; -import org.openecomp.aai.util.AAIConstants; -import org.openecomp.aai.util.AAITxnLog; import org.openecomp.aai.util.FormatDate; import com.att.eelf.configuration.EELFLogger; @@ -74,9 +72,6 @@ public class RESTAPI { GET, PUT, POST, DELETE }; - - public AAITxnLog txn = null; - /** * Gets the from app id. * @@ -140,7 +135,7 @@ public class RESTAPI { * @return the string */ protected String genDate() { - FormatDate fd = new FormatDate(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT, "YYMMdd-HH:mm:ss:SSS")); + FormatDate fd = new FormatDate( "YYMMdd-HH:mm:ss:SSS"); return fd.getDateTime(); } @@ -162,67 +157,6 @@ public class RESTAPI { } - /** - * Log transaction. - * - * @param appId the app id - * @param tId the t id - * @param action the action - * @param input the input - * @param rqstTm the rqst tm - * @param respTm the resp tm - * @param request the request - * @param response the response - */ - /* ---------------- Log Transaction into HBase --------------------- */ - public void logTransaction( String appId, String tId, String action, - String input, String rqstTm, String respTm, String request, Response response) { - String respBuf = ""; - int status = 0; - - if (response != null && response.getEntity() != null) { - respBuf = response.getEntity().toString(); - status = response.getStatus(); - } - logTransaction(appId, tId, action, input, rqstTm, respTm, request, respBuf, String.valueOf(status)); - } - - /** - * Log transaction. - * - * @param appId the app id - * @param tId the t id - * @param action the action - * @param input the input - * @param rqstTm the rqst tm - * @param respTm the resp tm - * @param request the request - * @param respBuf the resp buf - * @param status the status - * @param logline the logline - */ - public void logTransaction( String appId, String tId, String action, - String input, String rqstTm, String respTm, String request, String respBuf, String status) { - try { - // we only run this way if we're not doing it in the CXF interceptor - if (!AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true")) { - if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("true")) { - txn = new AAITxnLog(tId, appId); - // tid, status, rqstTm, respTm, srcId, rsrcId, rsrcType, rqstBuf, respBuf - String hbtid = txn.put(tId, status, - rqstTm, respTm, appId, input, action, request, respBuf); - - LOGGER.debug("HbTransId={}",hbtid); - LOGGER.debug("action={}", action); - LOGGER.debug("urlin={}", input); - } - - } - } catch (AAIException e) { - // i think we do nothing - } - } - /* ----------helpers for common consumer actions ----------- */ /** diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/db/DBSerializer.java b/aai-core/src/main/java/org/openecomp/aai/serialization/db/DBSerializer.java index 4e261060..49bcfd5a 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/db/DBSerializer.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/db/DBSerializer.java @@ -142,6 +142,13 @@ public class DBSerializer { } + private void touchStandardVertexProperties(String nodeType, Vertex v, boolean isNewVertex) { + + v.property(AAIProperties.NODE_TYPE, nodeType); + touchStandardVertexProperties(v, isNewVertex); + + } + /** @@ -156,8 +163,7 @@ public class DBSerializer { Vertex v = this.engine.tx().addVertex(); - v.property(AAIProperties.NODE_TYPE, wrappedObject.getDbName()); - touchStandardVertexProperties(v, true); + touchStandardVertexProperties(wrappedObject.getDbName(), v, true); return v; } @@ -272,6 +278,9 @@ public class DBSerializer { List<Vertex> processedVertexes = new ArrayList<>(); boolean isComplexType = false; boolean isListType = false; + if (!obj.isContainer()) { + this.touchStandardVertexProperties(obj.getDbName(), v, false); + } this.executePreSideEffects(obj, v); for (String property : properties) { Object value = null; @@ -1156,7 +1165,7 @@ public class DBSerializer { e = this.getEdgeBetween(EdgeType.COUSIN, inputVertex, relatedVertex); if (e == null) { edgeRules.addEdge(this.engine.asAdmin().getTraversalSource(), inputVertex, relatedVertex); - + } else { //attempted to link two vertexes already linked } @@ -1358,7 +1367,12 @@ public class DBSerializer { //are there any cousin edges? long children = 0; for (Edge e : inEdges) { - if (e.<Boolean>property("isParent").orElse(false)) { + if (e.<Boolean>property(EdgeProperties.out(EdgeProperty.IS_PARENT)).orElse(false)) { + children++; + } + } + for (Edge e : outEdges) { + if (e.<Boolean>property(EdgeProperties.in(EdgeProperty.IS_PARENT)).orElse(false)) { children++; } } @@ -1376,7 +1390,7 @@ public class DBSerializer { } else { result = true; for (Edge edge : outEdges) { - Object property = edge.<Boolean>property("isParent").orElse(null); + Object property = edge.<Boolean>property(EdgeProperties.out(EdgeProperty.IS_PARENT)).orElse(null); if (property != null && property.equals(Boolean.TRUE)) { Vertex v = edge.inVertex(); String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null); @@ -1389,7 +1403,7 @@ public class DBSerializer { } for (Edge edge : inEdges) { - Object property = edge.<Boolean>property("isParent-REV").orElse(null); + Object property = edge.<Boolean>property(EdgeProperties.in(EdgeProperty.IS_PARENT)).orElse(null); if (property != null && property.equals(Boolean.TRUE)) { Vertex v = edge.outVertex(); String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null); diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperties.java b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperties.java new file mode 100644 index 00000000..8ce1d1c9 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperties.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.serialization.db; + +public class EdgeProperties { + + public static String out(EdgeProperty prop) { + + return out(prop.toString()); + } + + public static String in(EdgeProperty prop) { + return in(prop.toString()); + } + + public static String out(String prop) { + + return prop; + } + + public static String in(String prop) { + return prop + "-REV"; + } + +} diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperty.java b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperty.java new file mode 100644 index 00000000..ce21431d --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeProperty.java @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.serialization.db; + +public enum EdgeProperty { + IS_PARENT("isParent"), + USES_RESOURCE("usesResource"), + HAS_DEL_TARGET("hasDelTarget"), + SVC_INFRA("SVC-INFRA"); + private final String name; + + private EdgeProperty(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/engines/query/GraphTraversalQueryEngine.java b/aai-core/src/main/java/org/openecomp/aai/serialization/engines/query/GraphTraversalQueryEngine.java index 7144aa69..a1967223 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/engines/query/GraphTraversalQueryEngine.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/engines/query/GraphTraversalQueryEngine.java @@ -32,9 +32,10 @@ import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Element; import org.apache.tinkerpop.gremlin.structure.Vertex; - import org.openecomp.aai.db.props.AAIProperties; import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.serialization.db.EdgeProperties; +import org.openecomp.aai.serialization.db.EdgeProperty; /* * This class needs some big explanation despite its compact size. @@ -62,7 +63,7 @@ public class GraphTraversalQueryEngine extends QueryEngine { @Override public List<Vertex> findParents(Vertex start) { - final GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).emit(v -> true).repeat(__.inE().has("isParent", true).outV()); + final GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).emit(v -> true).repeat(__.union(__.inE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true).outV(), __.outE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true).inV())); return pipe.toList(); } @@ -73,7 +74,7 @@ public class GraphTraversalQueryEngine extends QueryEngine { public List<Vertex> findAllChildren(Vertex start) { GraphTraversal<Vertex, Vertex> pipe = this.g - .V(start).emit(v -> true).repeat(__.outE().has("isParent", true).inV()); + .V(start).emit(v -> true).repeat(__.union(__.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true).inV(), __.inE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true).outV())); return pipe.toList(); @@ -82,8 +83,8 @@ public class GraphTraversalQueryEngine extends QueryEngine { public List<Vertex> findChildrenOfType(Vertex start, String type) { GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).union( - __.outE().has("isParent", true).inV(), - __.inE().has("isParent-REV", true).outV() + __.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true).inV(), + __.inE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true).outV() ).has(AAIProperties.NODE_TYPE, type).dedup(); return pipe.toList(); @@ -91,8 +92,8 @@ public class GraphTraversalQueryEngine extends QueryEngine { public List<Vertex> findChildren(Vertex start) { GraphTraversal<Vertex, Vertex> pipe = this.g.V(start).union( - __.outE().has("isParent", true), - __.inE().has("isParent-REV", true) + __.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true), + __.inE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true) ).otherV().dedup(); return pipe.toList(); @@ -104,9 +105,18 @@ public class GraphTraversalQueryEngine extends QueryEngine { @Override public List<Vertex> findDeletable(Vertex start) { GraphTraversal<Vertex, Vertex> pipe = this.g - .V(start).emit(v -> true).repeat(__.outE().or( - __.has("isParent", true), - __.has("hasDelTarget", true)).inV()); + .V(start).emit(v -> true).repeat( + __.union( + __.outE().or( + __.has(EdgeProperties.out(EdgeProperty.IS_PARENT), true), + __.has(EdgeProperties.out(EdgeProperty.HAS_DEL_TARGET), true) + ).inV(), + __.inE().or( + __.has(EdgeProperties.in(EdgeProperty.IS_PARENT), true), + __.has(EdgeProperties.in(EdgeProperty.HAS_DEL_TARGET), true) + ).outV() + ) + ); return pipe.toList(); } @@ -138,12 +148,15 @@ public class GraphTraversalQueryEngine extends QueryEngine { @Override public Tree<Element> findSubGraph(Vertex start, int iterations, boolean nodeOnly) { final GraphTraversal<Vertex, ?> t = this.g.V(start).emit(v -> true).times(iterations).repeat( - __.outE().has("isParent", true).inV()); + __.union( + __.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), true).inV(), + __.inE().has(EdgeProperties.in(EdgeProperty.IS_PARENT), true).outV()) + ); if (!nodeOnly) { t.union( __.identity(), - __.bothE().has("isParent", false).dedup().otherV() + __.bothE().and(__.has(EdgeProperties.out(EdgeProperty.IS_PARENT), false), __.has(EdgeProperties.in(EdgeProperty.IS_PARENT), false)).dedup().otherV() ); } t.tree(); @@ -158,8 +171,8 @@ public class GraphTraversalQueryEngine extends QueryEngine { public List<Edge> findEdgesForVersion(Vertex start, Loader loader) { final Set<String> objects = loader.getAllObjects().keySet(); GraphTraversal<Vertex, Edge> pipeline = this.g.V(start).union( - __.inE().has("isParent", false).has("isParent-REV", false).where(__.outV().has(AAIProperties.NODE_TYPE, P.within(objects))), - __.outE().has("isParent", false).has("isParent-REV", false).where(__.inV().has(AAIProperties.NODE_TYPE, P.within(objects))) + __.inE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), false).has(EdgeProperties.in(EdgeProperty.IS_PARENT), false).where(__.outV().has(AAIProperties.NODE_TYPE, P.within(objects))), + __.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), false).has(EdgeProperties.in(EdgeProperty.IS_PARENT), false).where(__.inV().has(AAIProperties.NODE_TYPE, P.within(objects))) ).dedup(); return pipeline.toList(); @@ -169,8 +182,8 @@ public class GraphTraversalQueryEngine extends QueryEngine { @Override public List<Vertex> findCousinVertices(Vertex start) { GraphTraversal<Vertex, Vertex> pipeline = this.g.V(start).union( - __.inE().has("isParent", false).has("isParent-REV", false), - __.outE().has("isParent", false).has("isParent-REV", false)).otherV().dedup(); + __.inE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), false).has(EdgeProperties.in(EdgeProperty.IS_PARENT), false), + __.outE().has(EdgeProperties.out(EdgeProperty.IS_PARENT), false).has(EdgeProperties.in(EdgeProperty.IS_PARENT), false)).otherV().dedup(); return pipeline.toList(); } diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinQueryEngine.java b/aai-core/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinQueryEngine.java new file mode 100644 index 00000000..1a6aa6d0 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinQueryEngine.java @@ -0,0 +1,175 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +// +//package org.openecomp.aai.serialization.engines.query; +// +//import java.util.List; +//import java.util.regex.Matcher; +//import java.util.regex.Pattern; +// +//import org.apache.commons.collections.IteratorUtils; +// +//import org.openecomp.aai.db.AAIProperties; +//import org.openecomp.aai.query.builder.QueryBuilder; +//import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; +//import com.tinkerpop.blueprints.Direction; +//import com.tinkerpop.blueprints.Graph; +//import com.tinkerpop.blueprints.TransactionalGraph; +//import com.tinkerpop.blueprints.Vertex; +//import com.tinkerpop.gremlin.groovy.Gremlin; +//import com.tinkerpop.gremlin.java.GremlinPipeline; +//import com.tinkerpop.pipes.Pipe; +//import com.tinkerpop.pipes.util.iterators.SingleIterator; +// +//public class GremlinQueryEngine extends QueryEngine { +// +// public GremlinQueryEngine (TransactionalGraphEngine engine) { +// super(engine); +// +// } +// +// +// @Override +// public List<Vertex> executeQuery(TransactionalGraph g, QueryBuilder query) { +// List<Vertex> result = null; +// Vertex start = query.getStart(); +// if (start != null) { +// result = this.executeQuery(start, (String)query.getQuery()); +// } else { +// result = this.processGremlinQuery((String)query.getQuery()); +// } +// return result; +// +// } +// +// @Override +// public List<Vertex> executeParentQuery(TransactionalGraph g, QueryBuilder query) { +// +// List<Vertex> result = null; +// Vertex start = query.getStart(); +// if (start != null) { +// result = this.executeQuery(start, (String)query.getParentQuery()); +// } else { +// result = this.processGremlinQuery((String)query.getParentQuery()); +// } +// return result; +// } +// +// private List<Vertex> executeQuery(Vertex startVertex, String query) { +// +// return this.processGremlinQuery(startVertex, "_()" + query); +// +// } +// +// @Override +// public List<Vertex> findParents(Vertex start) { +// +// String findAllParents = ".as('x').inE.has('isParent', true).outV" +// + ".loop('x'){it.object.inE.has('isParent',true).count()==1}{true}"; +// +// List<Vertex> results = this.executeQuery(start, findAllParents); +// results.add(0, start); +// return results; +// +// } +// +// @Override +// public List<Vertex> findChildren(Vertex start) { +// String findAllChildren = ".as('x').outE.has('isParent', true).inV" +// + ".loop('x'){it.object.outE.has('isParent', true).count() >= 1}{true}"; +// +// List<Vertex> results = this.executeQuery(start, findAllChildren); +// results.add(0, start); +// return results; +// +// } +// +// @Override +// public List<Vertex> findDeletable(Vertex start) { +// String findAllChildren = ".as('x').outE.or(_().has('isParent', true), _().has('hasDelTarget', true)).inV" +// + ".loop('x'){it.object.outE.or(_().has('isParent', true), _().has('hasDelTarget', true)).count() >= 1}{true}"; +// +// List<Vertex> results = this.executeQuery(start, findAllChildren); +// results.add(0, start); +// return results; +// } +// private List<Vertex> processGremlinQuery(String query) { +// +// Pattern firstHasSet = Pattern.compile("^(\\.has\\(.*?\\))(\\.has\\(.*?\\))*(?!\\.has)"); +// Pattern p = Pattern.compile("\\.has\\('(.*?)',\\s?'(.*?)'\\)"); +// Matcher m = firstHasSet.matcher(query); +// List<Vertex> results = null; +// GremlinPipeline<Graph, Vertex> pipe = new GremlinPipeline<>(dbEngine.getGraph()); +// if (m.find()) { +// String hasSet = m.group(); +// query = query.replace(m.group(0), ""); +// m = p.matcher(hasSet); +// pipe.V(); +// while (m.find()) { +// pipe.has(m.group(1), m.group(2)); +// } +// results = processGremlinQuery(pipe.toList(), "_()" + query); +// } +// +// return results; +// +// } +// private List<Vertex> processGremlinQuery(Vertex startVertex, String query) { +// +// Pipe pipe = Gremlin.compile(query); +// pipe.setStarts(new SingleIterator<Vertex>(startVertex)); +// +// return (List<Vertex>)IteratorUtils.toList(pipe.iterator()); +// } +// private List<Vertex> processGremlinQuery(List<Vertex> list, String query) { +// +// Pipe pipe = Gremlin.compile(query); +// +// pipe.setStarts(list); +// +// return (List<Vertex>)IteratorUtils.toList(pipe.iterator()); +// } +// +// +// @Override +// public List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) { +// String findRelatedVertices = "_()"; +// switch (direction) { +// case OUT: +// findRelatedVertices += ".out('" + label + "')"; +// break; +// case IN: +// findRelatedVertices += ".in('" + label + "')"; +// break; +// case BOTH: +// findRelatedVertices += ".both('" + label + "')"; +// break; +// default: +// break; +// } +// findRelatedVertices += ".has('" + AAIProperties.NODE_TYPE + "', '" + nodeType + "').dedup()"; +// List<Vertex> results = this.executeQuery(start, findRelatedVertices); +// results.add(0, start); +// return results; +// } +// +//} +// diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/utils/UrlBuilder.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/utils/UrlBuilder.java index 50e50e43..817a6795 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/utils/UrlBuilder.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/utils/UrlBuilder.java @@ -51,11 +51,11 @@ public class UrlBuilder { try { final StringBuilder result = new StringBuilder(); final URI uri = this.serializer.getURIForVertex(v); - + result.append(this.serverBase); result.append(this.version); result.append(uri.getRawPath()); - + return result.toString(); } catch (UnsupportedEncodingException | IllegalArgumentException | SecurityException e) { throw new AAIFormatVertexException(e); diff --git a/aai-core/src/main/java/org/openecomp/aai/util/AAIConstants.java b/aai-core/src/main/java/org/openecomp/aai/util/AAIConstants.java index 7d9bcccd..010f7a24 100644 --- a/aai-core/src/main/java/org/openecomp/aai/util/AAIConstants.java +++ b/aai-core/src/main/java/org/openecomp/aai/util/AAIConstants.java @@ -105,16 +105,6 @@ public final class AAIConstants { public static final String AAI_DBMODEL_FILENAME = "aai.dbmodel.filename"; public static final String AAI_RESVERSION_ENABLEFLAG = "aai.resourceversion.enableflag"; - public static final String ECM_OPENSTACK_TENANTID = "ecm.openstack.tenantid"; - - public static final String HBASE_TABLE_NAME = "hbase.table.name"; - public static final String HBASE_NOTIFICATION_TABLE_NAME = "hbase.notificationTable.name"; - public static final String HBASE_TABLE_TIMESTAMP_FORMAT = "hbase.table.timestamp.format"; - public static final String HBASE_CONFIGURATION_ZOOKEEPER_QUORUM = "hbase.zookeeper.quorum"; - public static final String HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT = "hbase.zookeeper.property.clientPort"; - public static final String HBASE_ZOOKEEPER_ZNODE_PARENT = "hbase.zookeeper.znode.parent"; - public static final String ZOOKEEPER_ZNODE_PARENT = "zookeeper.znode.parent"; - public static final int AAI_MAX_TRANS_RETRIES = 5; public static final long AAI_TRANS_RETRY_SLEEP_MSEC = 500; @@ -129,12 +119,12 @@ public final class AAIConstants { /** Default to skipping real-time grooming unless system property aai.skiprealtime.grooming is set to "false" */ public static final String AAI_SKIPREALTIME_GROOMING = (System.getProperty("aai.skiprealtime.grooming") == null) ? "true" : System.getProperty("aai.skiprealtime.grooming"); - + /*** UEB ***/ public static final String UEB_PUB_PARTITION_AAI = "AAI"; public static final String UEB_PUB_AAI_VCE_INTERFACE_DATA_TOPIC = "ueb.pub.aai.vce.interface.data.topic"; - + /** Service description for Hosted Communications */ public static final String AAI_SERVICEDESCRIPTION_HOSTEDCOMM = "aai.servicedescription.hostedcomm"; @@ -143,7 +133,7 @@ public final class AAIConstants { /** Service description for Mobility */ public static final String AAI_SERVICEDESCRIPTION_VUSP = "aai.servicedescription.vusp"; - + /** Service description for Vvig */ public static final String AAI_SERVICEDESCRIPTION_VVIG = "aai.servicedescription.vvig"; diff --git a/aai-core/src/main/java/org/openecomp/aai/util/AAITxnLog.java b/aai-core/src/main/java/org/openecomp/aai/util/AAITxnLog.java deleted file mode 100644 index 3a90e8e9..00000000 --- a/aai-core/src/main/java/org/openecomp/aai/util/AAITxnLog.java +++ /dev/null @@ -1,499 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.openecomp.aai - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.aai.util; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hbase.client.Get; -import org.apache.hadoop.hbase.client.HTable; -import org.apache.hadoop.hbase.client.Put; -import org.apache.hadoop.hbase.client.Result; -import org.apache.hadoop.hbase.client.ResultScanner; -import org.apache.hadoop.hbase.client.Scan; -import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; -import org.apache.hadoop.hbase.filter.Filter; -import org.apache.hadoop.hbase.filter.FilterList; -import org.apache.hadoop.hbase.filter.RegexStringComparator; -import org.apache.hadoop.hbase.filter.SingleColumnValueFilter; -import org.apache.hadoop.hbase.util.Bytes; -import org.openecomp.aai.domain.notificationEvent.NotificationEvent; -import org.openecomp.aai.domain.translog.TransactionLogEntries; -import org.openecomp.aai.domain.translog.TransactionLogEntry; -import org.openecomp.aai.exceptions.AAIException; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; - -public class AAITxnLog { - - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAITxnLog.class); - - private final org.apache.hadoop.conf.Configuration config; - private HTable table = null; - private String tm = null; - - /** - * Instantiates a new AAI txn log. - * - * @param transId the trans id - * @param fromAppId the from app id - */ - public AAITxnLog(String transId, String fromAppId) { - /* When you create a HBaseConfiguration, it reads in whatever you've set - into your hbase-site.xml and in hbase-default.xml, as long as these can - be found on the CLASSPATH */ - - config = HBaseConfiguration.create(); - - try { - config.set(AAIConstants.ZOOKEEPER_ZNODE_PARENT, AAIConfig.get(AAIConstants.HBASE_ZOOKEEPER_ZNODE_PARENT)); - config.set(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM, AAIConfig.get(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM)); - config.set(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT, AAIConfig.get(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT)); - - FormatDate fd = new FormatDate(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT, "YYMMdd-HH:mm:ss:SSS")); - - tm = fd.getDateTime(); - } catch (AAIException e) { - LOGGER.warn("Missing configuration in AAIConfig: " + e.getMessage()); - } - } - - /** - * Put. - * - * @param status the status - * @param srcId the src id - * @param rsrcId the rsrc id - * @param rsrcType the rsrc type - * @param rqstBuf the rqst buf - * @param respBuf the resp buf - * @return the string - */ - public String put( - String status, - String srcId, - String rsrcId, - String rsrcType, - String rqstBuf, - String respBuf - ) { - return put ("",status,"","",srcId,rsrcId,rsrcType,rqstBuf,respBuf,false,new NotificationEvent()); - - } - - /** - * Put. - * - * @param tid the tid - * @param status the status - * @param srcId the src id - * @param rsrcId the rsrc id - * @param rsrcType the rsrc type - * @param rqstBuf the rqst buf - * @param respBuf the resp buf - * @return the string - */ - public String put( - String tid, - String status, - String srcId, - String rsrcId, - String rsrcType, - String rqstBuf, - String respBuf - ) { - return put (tid,status,"","",srcId,rsrcId,rsrcType,rqstBuf,respBuf,false,new NotificationEvent()); - } - - /** - * Put. - * - * @param tid the tid - * @param status the status - * @param rqstTm the rqst tm - * @param respTm the resp tm - * @param srcId the src id - * @param rsrcId the rsrc id - * @param rsrcType the rsrc type - * @param rqstBuf the rqst buf - * @param respBuf the resp buf - * @return the string - */ - public String put( - String tid, - String status, - String rqstTm, - String respTm, - String srcId, - String rsrcId, - String rsrcType, - String rqstBuf, - String respBuf - ) { - return put (tid,status,"","",srcId,rsrcId,rsrcType,rqstBuf,respBuf,false,new NotificationEvent()); - } - - /** - * Put. - * - * @param tid the tid - * @param status the status - * @param rqstTm the rqst tm - * @param respTm the resp tm - * @param srcId the src id - * @param rsrcId the rsrc id - * @param rsrcType the rsrc type - * @param rqstBuf the rqst buf - * @param respBuf the resp buf - * @param hasNotificationEvent the has notification event - * @param ne the ne - * @return the string - */ - public String put( - String tid, - String status, - String rqstTm, - String respTm, - String srcId, - String rsrcId, - String rsrcType, - String rqstBuf, - String respBuf, - boolean hasNotificationEvent, - NotificationEvent ne - ) { - - if (tid == null || "".equals(tid)) { - FormatDate fd = new FormatDate(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT, "YYMMdd-HH:mm:ss:SSS")); - - tm = fd.getDateTime(); - tid = tm + "-"; - } - String htid = tid; - - //need to add a prefix for better hbase logging server balancing - htid = HbaseSaltPrefixer.getInstance().prependSalt(htid); - - if (rqstTm == null || "".equals(rqstTm)) { - rqstTm = tm; - } - - if (respTm == null || "".equals(respTm)) { - respTm = tm; - } - - try { - table = new HTable(config, AAIConfig.get(AAIConstants.HBASE_TABLE_NAME)); - - Put p = new Put(Bytes.toBytes(htid)); - - p.add(Bytes.toBytes("transaction"),Bytes.toBytes("tid"),Bytes.toBytes(tid)); - p.add(Bytes.toBytes("transaction"),Bytes.toBytes("status"),Bytes.toBytes(status)); - p.add(Bytes.toBytes("transaction"),Bytes.toBytes("rqstDate"),Bytes.toBytes(rqstTm)); - p.add(Bytes.toBytes("transaction"),Bytes.toBytes("respDate"),Bytes.toBytes(respTm)); - p.add(Bytes.toBytes("transaction"),Bytes.toBytes("sourceId"),Bytes.toBytes(srcId)); - - p.add(Bytes.toBytes("resource"),Bytes.toBytes("resourceId"),Bytes.toBytes(rsrcId)); - p.add(Bytes.toBytes("resource"),Bytes.toBytes("resourceType"),Bytes.toBytes(rsrcType)); - - p.add(Bytes.toBytes("payload"),Bytes.toBytes("rqstBuf"),Bytes.toBytes(rqstBuf)); - p.add(Bytes.toBytes("payload"),Bytes.toBytes("respBuf"),Bytes.toBytes(respBuf)); - - if (hasNotificationEvent == true) { - String eventType = ne.getEventHeader().getEventType(); - String eventStatus = ne.getEventHeader().getStatus(); - - if (eventStatus == null) { - eventStatus = AAIConfig.get("aai.notificationEvent.default.status", "UNPROCESSED"); - } - if (eventType == null) { - eventType = AAIConfig.get("aai.notificationEvent.default.eventType", "AAI-EVENT"); - } - - if (ne.getEntity() != null) { - PojoUtils pu = new PojoUtils(); - p.add(Bytes.toBytes("notification"),Bytes.toBytes("notificationPayload"),Bytes.toBytes(pu.getJsonFromObject(ne))); - } - if (ne.getEventHeader().getId() != null) { - p.add(Bytes.toBytes("notification"),Bytes.toBytes("notificationId"),Bytes.toBytes(ne.getEventHeader().getId())); - } - - p.add(Bytes.toBytes("notification"),Bytes.toBytes("notificationStatus"),Bytes.toBytes(eventStatus)); - p.add(Bytes.toBytes("notification"),Bytes.toBytes("notificationTopic"),Bytes.toBytes(eventType)); - - if (ne.getEventHeader().getEntityLink() != null) { - p.add(Bytes.toBytes("notification"),Bytes.toBytes("notificationEntityLink"),Bytes.toBytes(ne.getEventHeader().getEntityLink())); - } - if (ne.getEventHeader().getAction() != null) { - p.add(Bytes.toBytes("notification"),Bytes.toBytes("notificationAction"),Bytes.toBytes(ne.getEventHeader().getAction()) ); - } - } - /* Once you've adorned your Put instance with all the updates you want to - make, to commit it do the following */ - table.put(p); - table.flushCommits(); - table.close(); - return htid; - } catch (Exception e) { - LOGGER.warn("AAITxnLog: put: Exception", e); - return htid; - } - } - - /** - * Gets the. - * - * @param htid the htid - * @return the transaction log entry - * @throws AAIException the AAI exception - */ - public TransactionLogEntry get(String htid) throws AAIException { - - LOGGER.debug("In get: searching hbase config file..."); - String tidStr = ""; - TransactionLogEntry txObj = new TransactionLogEntry(); - - try { - table = new HTable(config, AAIConfig.get(AAIConstants.HBASE_TABLE_NAME)); - - Get g = new Get(Bytes.toBytes(htid)); - - Result r = table.get(g); - byte [] tid = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("tid")); - byte [] status = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("status")); - byte [] rqstDate = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("rqstDate")); - byte [] respDate = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("respDate")); - byte [] sourceId = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("sourceId")); - - byte [] resourceId = r.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceId")); - byte [] resourceType = r.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceType")); - - byte [] rqstBuf = r.getValue(Bytes.toBytes("payload"),Bytes.toBytes("rqstBuf")); - byte [] respBuf = r.getValue(Bytes.toBytes("payload"),Bytes.toBytes("respBuf")); - - byte [] notificationPayload = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationPayload")); - byte [] notificationStatus = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationStatus")); - byte [] notificationId = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationId")); - byte [] notificationTopic = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationTopic")); - byte [] notificationEntityLink = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationEntityLink")); - byte [] notificationAction = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationAction")); - - table.close(); - - tidStr = Bytes.toString(tid); - txObj.setTransactionLogEntryId(tidStr); - txObj.setStatus(Bytes.toString(status)); - txObj.setRqstDate(Bytes.toString(rqstDate)); - txObj.setRespDate(Bytes.toString(respDate)); - txObj.setSourceId(Bytes.toString(sourceId)); - txObj.setResourceId(Bytes.toString(resourceId)); - txObj.setResourceType(Bytes.toString(resourceType)); - txObj.setRqstBuf(Bytes.toString(rqstBuf)); - txObj.setrespBuf(Bytes.toString(respBuf)); - txObj.setNotificationPayload(Bytes.toString(notificationPayload)); - txObj.setNotificationStatus(Bytes.toString(notificationStatus)); - txObj.setNotificationId(Bytes.toString(notificationId)); - txObj.setNotificationTopic(Bytes.toString(notificationTopic)); - txObj.setNotificationEntityLink(Bytes.toString(notificationEntityLink)); - txObj.setNotificationAction(Bytes.toString(notificationAction)); - } catch (IOException e) { - LOGGER.error("IOException on hbase call", e); - throw new AAIException("AAI_4000"); - } - - return txObj; - } - - - /** - * Scan filtered. - * - * @param startMillis the start millis - * @param endMillis the end millis - * @param methodList the method list - * @param putFilter the put filter - * @param getFilter the get filter - * @param resourceFilter the resource filter - * @param fromAppIdFilter the from app id filter - * @return the transaction log entries - */ - public TransactionLogEntries scanFiltered(long startMillis, long endMillis, List<String> methodList, - String putFilter, String getFilter, String resourceFilter, String fromAppIdFilter) { - - LOGGER.debug("Starting scanFiltered()"); - - // we should have the config ready from the constructor - - TransactionLogEntries txs = new TransactionLogEntries(); - - if (config == null) { - LOGGER.debug("in scan: can't create HBase configuration"); - return txs; - } - - try { - table = new HTable(config, AAIConfig.get(AAIConstants.HBASE_TABLE_NAME)); - Scan s = new Scan(); - FilterList flMaster = new FilterList(FilterList.Operator.MUST_PASS_ALL); - FilterList methodflMaster = new FilterList(FilterList.Operator.MUST_PASS_ONE); - if (methodList != null) { - for (String method : methodList) { - Filter filt = new SingleColumnValueFilter(Bytes.toBytes("resource"), - Bytes.toBytes("resourceType"), CompareOp.EQUAL, Bytes.toBytes(method)); - methodflMaster.addFilter(filt); - } - flMaster.addFilter(methodflMaster); - } - - if (getFilter != null) { - Filter filt = new SingleColumnValueFilter(Bytes.toBytes("payload"), - Bytes.toBytes("respBuf"), CompareOp.EQUAL, new RegexStringComparator(getFilter)); - flMaster.addFilter(filt); - } - if (putFilter != null) { - Filter filt = new SingleColumnValueFilter(Bytes.toBytes("payload"), - Bytes.toBytes("rqstBuf"), CompareOp.EQUAL, new RegexStringComparator(putFilter)); - flMaster.addFilter(filt); - } - if (resourceFilter != null) { - Filter filt = new SingleColumnValueFilter(Bytes.toBytes("resource"), - Bytes.toBytes("resourceId"), CompareOp.EQUAL, new RegexStringComparator(resourceFilter)); - flMaster.addFilter(filt); - } - if (fromAppIdFilter != null) { - Filter filt = new SingleColumnValueFilter(Bytes.toBytes("transaction"), - Bytes.toBytes("sourceId"), CompareOp.EQUAL, new RegexStringComparator("^" + fromAppIdFilter)); - flMaster.addFilter(filt); - } - - if (flMaster.hasFilterRow()) { - s.setFilter(flMaster); - } - - s.setTimeRange(startMillis, endMillis); - ResultScanner scanner = table.getScanner(s); - - try { - for (Result rr = scanner.next(); rr != null; rr = scanner.next()) { - - byte [] tid = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("tid")); - byte [] status = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("status")); - byte [] rqstDate = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("rqstDate")); - byte [] respDate = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("respDate")); - byte [] sourceId = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("sourceId")); - - byte [] resourceId = rr.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceId")); - byte [] resourceType = rr.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceType")); - - byte [] rqstBuf = rr.getValue(Bytes.toBytes("payload"),Bytes.toBytes("rqstBuf")); - byte [] respBuf = rr.getValue(Bytes.toBytes("payload"),Bytes.toBytes("respBuf")); - - byte [] notificationPayload = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationPayload")); - byte [] notificationStatus = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationStatus")); - byte [] notificationId = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationId")); - byte [] notificationTopic = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationTopic")); - byte [] notificationEntityLink = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationEntityLink")); - byte [] notificationAction = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationAction")); - TransactionLogEntry txObj = new TransactionLogEntry(); - String tidStr = Bytes.toString(tid); - txObj.setTransactionLogEntryId(tidStr); - txObj.setStatus(Bytes.toString(status)); - txObj.setRqstDate(Bytes.toString(rqstDate)); - txObj.setRespDate(Bytes.toString(respDate)); - txObj.setSourceId(Bytes.toString(sourceId)); - txObj.setResourceId(Bytes.toString(resourceId)); - txObj.setResourceType(Bytes.toString(resourceType)); - txObj.setRqstBuf(Bytes.toString(rqstBuf)); - txObj.setrespBuf(Bytes.toString(respBuf)); - txObj.setNotificationPayload(Bytes.toString(notificationPayload)); - txObj.setNotificationStatus(Bytes.toString(notificationStatus)); - txObj.setNotificationId(Bytes.toString(notificationId)); - txObj.setNotificationTopic(Bytes.toString(notificationTopic)); - txObj.setNotificationEntityLink(Bytes.toString(notificationEntityLink)); - txObj.setNotificationAction(Bytes.toString(notificationAction)); - txs.getTransactionLogEntries().add(txObj); - } - } finally { - // Make sure you close your scanners when you are done! - scanner.close(); - } - table.close(); - } catch (Exception e) { - LOGGER.warn("AAITxnLog: scan: Exception=" + e.toString()); - } - - return txs; - } - - /** - * Scan. - * - * @param htid the htid - * @return the list - */ - public List<String> scan(String htid) { - - List<String> list = new ArrayList<String>(); - LOGGER.debug("In scan: searching hbase config file..."); - // we should have the config ready from the constructor - if (config == null) { - LOGGER.debug("in scan: can't create HBase configuration"); - return list; - } - - try { - table = new HTable(config, AAIConfig.get(AAIConstants.HBASE_TABLE_NAME)); - Scan s = new Scan(Bytes.toBytes(htid)); - ResultScanner scanner = table.getScanner(s); - - try { - for (Result rr = scanner.next(); rr != null; rr = scanner.next()) { - list.add(rr.toString()); - LOGGER.debug("in scan: Found row : " + rr); - - } - } finally { - // Make sure you close your scanners when you are done! - scanner.close(); - } - table.close(); - } catch (Exception e) { - - LOGGER.debug("AAITxnLog: scan: Exception=" + e.toString()); - } - return list; - } - -} - -/* -Need to implement HBase Connection Pooling in the future. -This is to reduce the 1 second delay during the first open of HConnection, and HTable instantiation. -Hbase provides the Hconnection class and the HConnectionManager class. -Both provifde the functionaltity similar to jdbc connection pooling -to share pre-existing opened connections. -Here we should be able to use the getTable() method to get a -reference to an HTable instance. - - */ diff --git a/aai-core/src/main/java/org/openecomp/aai/util/GenerateXsd.java b/aai-core/src/main/java/org/openecomp/aai/util/GenerateXsd.java index 7cc6bcf0..83fcf634 100644 --- a/aai-core/src/main/java/org/openecomp/aai/util/GenerateXsd.java +++ b/aai-core/src/main/java/org/openecomp/aai/util/GenerateXsd.java @@ -83,14 +83,14 @@ public class GenerateXsd { private static final String generateTypeXSD = "xsd"; private static final String generateTypeYAML = "yaml"; - + private static final String root = "../aai-schema/src/main/resources"; private static final String xsd_dir = root + "/aai_schema"; private static final String yaml_dir = root + "/aai_swagger_yaml"; - + private static int annotationsStartVersion = 9; // minimum version to support annotations in xsd private static int swaggerSupportStartsVersion = 7; // minimum version to support swagger documentation - + private static XPath xpath = XPathFactory.newInstance().newXPath(); @@ -229,11 +229,11 @@ public class GenerateXsd { } private static boolean validVersion(String versionToGen) { - + if ("ALL".equalsIgnoreCase(versionToGen)) { return true; } - + for (Version v : Version.values()) { if (v.name().equals(versionToGen)) { return true; @@ -242,49 +242,49 @@ public class GenerateXsd { return false; } - + private static boolean versionUsesAnnotations( String version) { if (new Integer(version.substring(1)).intValue() >= annotationsStartVersion ) { return true; } return false; } - + private static boolean versionSupportsSwagger( String version) { if (new Integer(version.substring(1)).intValue() >= swaggerSupportStartsVersion ) { return true; } return false; } - + public static void main(String[] args) throws IOException { String versionToGen = System.getProperty("gen_version").toLowerCase(); String fileTypeToGen = System.getProperty("gen_type").toLowerCase(); if ( fileTypeToGen == null ) { fileTypeToGen = generateTypeXSD; } - + if ( !fileTypeToGen.equals( generateTypeXSD ) && !fileTypeToGen.equals( generateTypeYAML )) { System.err.println("Invalid gen_type passed. " + fileTypeToGen); System.exit(1); } - - + + if ( versionToGen == null ) { System.err.println("Version is required, ie v<n> or ALL."); - System.exit(1); + System.exit(1); } - + responsesUrl = System.getProperty("yamlresponses_url"); String responsesLabel = System.getProperty("yamlresponses_label"); List<Version> versionsToGen = new ArrayList<>(); - + if (!"ALL".equalsIgnoreCase(versionToGen) && !versionToGen.matches("v\\d+") && !validVersion(versionToGen)) { System.err.println("Invalid version passed. " + versionToGen); System.exit(1); } - + if ("ALL".equalsIgnoreCase(versionToGen)) { versionsToGen = Arrays.asList(Version.values()); Collections.sort(versionsToGen); @@ -294,7 +294,7 @@ public class GenerateXsd { } if ( fileTypeToGen.equals(generateTypeYAML) ) { - if ( responsesUrl == null || responsesUrl.length() < 1 + if ( responsesUrl == null || responsesUrl.length() < 1 || responsesLabel == null || responsesLabel.length() < 1 ) { System.err.println("generating swagger yaml file requires yamlresponses_url and yamlresponses_label properties" ); System.exit(1); @@ -302,11 +302,11 @@ public class GenerateXsd { responsesUrl = "description: "+ responsesLabel+ "(" + responsesUrl + ").\n"; } String oxmPath = root + "/oxm/"; - + String outfileName; File outfile; String fileContent; - + for (Version v : versionsToGen) { apiVersion = v.toString(); System.out.println("Generating " + apiVersion + " " + fileTypeToGen); @@ -326,9 +326,9 @@ public class GenerateXsd { } outfile = new File(outfileName); File parentDir = outfile.getParentFile(); - if(! parentDir.exists()) + if(! parentDir.exists()) parentDir.mkdirs(); - + try { outfile.createNewFile(); } catch (IOException e) { @@ -347,7 +347,7 @@ public class GenerateXsd { } System.out.println( "GeneratedXSD successful, saved in " + outfileName); } - + } @@ -688,7 +688,7 @@ public class GenerateXsd { sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"); String namespace = "org.openecomp"; if ( useAnnotationsInXsd ) { - sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/" + sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" + "\n" + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"\r\n" + @@ -696,7 +696,7 @@ public class GenerateXsd { " xmlns:annox=\"http://annox.dev.java.net\" \r\n" + " jaxb:extensionBindingPrefixes=\"annox\">\n\n"); } else { - sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/" + sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n"); } @@ -927,6 +927,7 @@ public class GenerateXsd { case "Network": case "ServiceDesignAndCreation": case "Business": + case "LicenseManagement": case "CloudInfrastructure": break; default: @@ -1639,6 +1640,8 @@ public class GenerateXsd { sb.append("swagger: \"2.0\"\ninfo:\n description: |\n Copyright © 2017 AT&T Intellectual Property. All rights reserved.\n\n Licensed under the Creative Commons License, Attribution 4.0 Intl. (the "License"); you may not use this documentation except in compliance with the License.\n\n You may obtain a copy of the License at\n\n (https://creativecommons.org/licenses/by/4.0/)\n\n 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.\n\n ECOMP and OpenECOMP are trademarks and service marks of AT&T Intellectual Property.\n\n This document is best viewed with Firefox or Chrome. Nodes can be found by appending /#/definitions/node-type-to-find to the path to this document. Edge definitions can be found with the node definitions.\n version: \"" + apiVersion +"\"\n"); sb.append(" title: Active and Available Inventory REST API\n"); sb.append(" license:\n name: Apache 2.0\n url: http://www.apache.org/licenses/LICENSE-2.0.html\n"); + sb.append(" contact:\n name:\n url:\n email:\n"); + sb.append("host:\nbasePath: /aai/" + apiVersion + "\n"); sb.append("schemes:\n - https\npaths:\n"); /* sb.append("responses:\n"); diff --git a/aai-core/src/main/java/org/openecomp/aai/util/swagger/Api.java b/aai-core/src/main/java/org/openecomp/aai/util/swagger/Api.java new file mode 100644 index 00000000..241be43a --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/util/swagger/Api.java @@ -0,0 +1,310 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.util.swagger; + +import java.util.List; +import java.util.Map; + +public class Api { + + private String path; + + private List<HttpVerb> httpMethods; + + private String tag; + + public List<HttpVerb> getHttpMethods() { + return httpMethods; + } + + public void setHttpMethods(List<HttpVerb> httpMethods) { + this.httpMethods = httpMethods; + } + + public String getTag(){ + + if(this.tag != null){ + return this.tag; + } + + if(this.httpMethods != null){ + if(this.httpMethods.size() != 0){ + if(this.httpMethods.get(0).getTags() != null){ + if(this.httpMethods.get(0).getTags().size() != 0){ + this.tag = this.httpMethods.get(0).getTags().get(0); + } + } + } + } + + if(this.tag == null){ + this.tag = ""; + } + + return this.tag; + } + + @Override + public String toString() { + return "Api{" + + "path='" + path + '\'' + + ", httpMethods=" + httpMethods + + '}'; + } + + public void setPath(String path) { + this.path = path; + } + + public String getPath() { + return this.path; + } + + public String getOperation(){ + + if(this.path != null){ + return this.path.replaceAll("[^a-zA-Z0-9\\-]", "-") + "-"; + } + + return ""; + } + + public static class HttpVerb { + + private List<String> tags; + + private String type; + + private String summary; + + private String operationId; + + private List<String> consumes; + + private boolean consumerEnabled; + + private List<String> produces; + + private List<Response> responses; + + private List<Map<String, Object>> parameters; + + private Map<String, Object> bodyParameters; + + private boolean bodyParametersEnabled; + + private boolean parametersEnabled; + + private String schemaLink; + + private String schemaType; + + private boolean hasReturnSchema; + + private String returnSchemaLink; + + private String returnSchemaObject; + + public void setConsumerEnabled(boolean consumerEnabled){ + this.consumerEnabled = consumerEnabled; + } + + public boolean isConsumerEnabled() { + return consumerEnabled; + } + + + public List<String> getTags() { + return tags; + } + + public void setTags(List<String> tags) { + this.tags = tags; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + public String getOperationId() { + return operationId; + } + + public void setOperationId(String operationId) { + this.operationId = operationId; + } + + public List<String> getConsumes() { + return consumes; + } + + public void setConsumes(List<String> consumes) { + this.consumes = consumes; + } + + public List<String> getProduces() { + return produces; + } + + public void setProduces(List<String> produces) { + this.produces = produces; + } + + public List<Response> getResponses() { + return responses; + } + + public void setResponses(List<Response> responses) { + this.responses = responses; + } + + public List<Map<String, Object>> getParameters() { + return parameters; + } + + public void setParameters(List<Map<String, Object>> parameters) { + this.parameters = parameters; + } + + @Override + public String toString() { + return "HttpVerb{" + + "tags=" + tags + + ", type='" + type + '\'' + + ", summary='" + summary + '\'' + + ", operationId='" + operationId + '\'' + + ", consumes=" + consumes + + ", produces=" + produces + + ", responses=" + responses + + ", parameters=" + parameters + + '}'; + } + + public void setParametersEnabled(boolean b) { + this.parametersEnabled = b; + } + + public boolean isParametersEnabled() { + return parametersEnabled; + } + + public boolean isBodyParametersEnabled() { + return bodyParametersEnabled; + } + + public void setBodyParametersEnabled(boolean bodyParametersEnabled) { + this.bodyParametersEnabled = bodyParametersEnabled; + } + + public Map<String, Object> getBodyParameters() { + return bodyParameters; + } + + public void setBodyParameters(Map<String, Object> bodyParameters) { + this.bodyParameters = bodyParameters; + } + + public String getSchemaLink() { + return schemaLink; + } + + public void setSchemaLink(String schemaLink) { + this.schemaLink = schemaLink; + } + + public String getSchemaType() { + return schemaType; + } + + public void setSchemaType(String schemaType) { + this.schemaType = schemaType; + } + + public boolean isHasReturnSchema() { + return hasReturnSchema; + } + + public void setHasReturnSchema(boolean hasReturnSchema) { + this.hasReturnSchema = hasReturnSchema; + } + + public String getReturnSchemaLink() { + return returnSchemaLink; + } + + public void setReturnSchemaLink(String returnSchemaLink) { + this.returnSchemaLink = returnSchemaLink; + } + + public String getReturnSchemaObject() { + return returnSchemaObject; + } + + public void setReturnSchemaObject(String returnSchemaObject) { + this.returnSchemaObject = returnSchemaObject; + } + + public static class Response { + + private String responseCode; + + private String description; + + public String getResponseCode() { + return responseCode; + } + + public void setResponseCode(String responseCode) { + this.responseCode = responseCode; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String toString() { + return "Response{" + + "responseCode='" + responseCode + '\'' + + ", description='" + description + '\'' + + '}'; + } + } + + } + +} diff --git a/aai-core/src/main/java/org/openecomp/aai/util/swagger/Definition.java b/aai-core/src/main/java/org/openecomp/aai/util/swagger/Definition.java new file mode 100644 index 00000000..31c38c56 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/util/swagger/Definition.java @@ -0,0 +1,199 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.util.swagger; + +import java.util.List; + +public class Definition { + + private String definitionName; + + private String definitionDescription; + + private List<Property> propertyList; + + private List<Property> schemaPropertyList; + + private List<Property> regularPropertyList; + + private boolean hasDescription; + + public String getDefinitionName() { + return definitionName; + } + + public void setDefinitionName(String definitionName) { + this.definitionName = definitionName; + } + + public List<Property> getPropertyList() { + return propertyList; + } + + public void setPropertyList(List<Property> propertyList) { + this.propertyList = propertyList; + } + + public String getDefinitionDescription() { + return definitionDescription; + } + + public void setDefinitionDescription(String definitionDescription) { + this.definitionDescription = definitionDescription; + } + + @Override + public String toString() { + return "Definition{" + + "definitionName='" + definitionName + '\'' + + ", definitionDescription='" + definitionDescription + '\'' + + ", propertyList=" + propertyList + + '}'; + } + + public boolean isHasDescription() { + return hasDescription; + } + + public void setHasDescription(boolean hasDescription) { + this.hasDescription = hasDescription; + } + + public List<Property> getSchemaPropertyList() { + return schemaPropertyList; + } + + public void setSchemaPropertyList(List<Property> schemaPropertyList) { + this.schemaPropertyList = schemaPropertyList; + } + + public List<Property> getRegularPropertyList() { + return regularPropertyList; + } + + public void setRegularPropertyList(List<Property> regularPropertyList) { + this.regularPropertyList = regularPropertyList; + } + + public static class Property { + + private String propertyName; + + private String propertyDescription; + + private boolean hasPropertyDescription; + + private String propertyType; + + private boolean hasType; + + private String propertyReference; + + private String propertyReferenceObjectName; + + private boolean isRequired; + + private boolean hasPropertyReference; + + public Property(){} + + public String getPropertyName() { + return propertyName; + } + + public void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + public String getPropertyType() { + return propertyType; + } + + public void setPropertyType(String propertyType) { + this.propertyType = propertyType; + } + + public String getPropertyReference() { + return propertyReference; + } + + public void setPropertyReference(String propertyReference) { + this.propertyReference = propertyReference; + } + + @Override + public String toString() { + return "Property{" + + "propertyName='" + propertyName + '\'' + + ", propertyType='" + propertyType + '\'' + + ", propertyReference='" + propertyReference + '\'' + + '}'; + } + + public boolean isHasType() { + return hasType; + } + + public void setHasType(boolean hasType) { + this.hasType = hasType; + } + + public boolean isRequired() { + return isRequired; + } + + public void setRequired(boolean required) { + isRequired = required; + } + + public boolean isHasPropertyReference() { + return hasPropertyReference; + } + + public void setHasPropertyReference(boolean hasPropertyReference) { + this.hasPropertyReference = hasPropertyReference; + } + + public String getPropertyReferenceObjectName() { + return propertyReferenceObjectName; + } + + public void setPropertyReferenceObjectName(String propertyReferenceObjectName) { + this.propertyReferenceObjectName = propertyReferenceObjectName; + } + + public String getPropertyDescription() { + return propertyDescription; + } + + public void setPropertyDescription(String propertyDescription) { + this.propertyDescription = propertyDescription; + } + + public boolean isHasPropertyDescription() { + return hasPropertyDescription; + } + + public void setHasPropertyDescription(boolean hasPropertyDescription) { + this.hasPropertyDescription = hasPropertyDescription; + } + } +} diff --git a/aai-core/src/main/java/org/openecomp/aai/util/swagger/GenerateSwagger.java b/aai-core/src/main/java/org/openecomp/aai/util/swagger/GenerateSwagger.java new file mode 100644 index 00000000..66e91318 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/util/swagger/GenerateSwagger.java @@ -0,0 +1,428 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.util.swagger; + +import com.fasterxml.jackson.dataformat.yaml.snakeyaml.Yaml; +import com.fasterxml.jackson.dataformat.yaml.snakeyaml.constructor.SafeConstructor; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; + +import java.io.*; +import java.util.*; +import java.util.stream.Collectors; + +public class GenerateSwagger { + + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + public static final String DEFAULT_WIKI = ""; + + public static final String DEFAULT_SCHEMA_DIR = "../aai-schema"; + public static final String CURRENT_VERSION = "v10"; + + public static void main(String[] args) throws IOException, TemplateException { + + String schemaDir = System.getProperty("aai.schema.dir"); + String versionToGenerate = System.getProperty("aai.generate.version"); + String wikiLink = System.getProperty("aai.wiki.link"); + + if(schemaDir == null){ + System.out.println("Warning: Schema directory is not set so using default schema dir: " + DEFAULT_SCHEMA_DIR); + schemaDir = DEFAULT_SCHEMA_DIR; + } + + if(versionToGenerate == null){ + System.out.println("Warning: Version to generate is not set so using default version: " + CURRENT_VERSION); + versionToGenerate = CURRENT_VERSION; + } + + if(wikiLink == null){ + System.out.println("Warning: aai.wiki.link property is not set so using default"); + wikiLink = DEFAULT_WIKI; + } + + String yamlFile = schemaDir + "/src/main/resources/aai_swagger_yaml/aai_swagger_" + versionToGenerate + ".yaml"; + File swaggerYamlFile = new File(yamlFile); + + if(!swaggerYamlFile.exists()){ + System.err.println("Unable to find the swagger yaml file: " + swaggerYamlFile); + System.exit(1); + } + + Yaml yaml = new Yaml(new SafeConstructor()); + Map<String, Object> swaggerMap = null; + + try (BufferedReader reader = new BufferedReader(new FileReader(swaggerYamlFile))){ + swaggerMap = (Map<String, Object>) yaml.load(reader); + } catch(IOException ex){ + ex.printStackTrace(); + } + + Map<String, Object> map = (Map<String, Object>) swaggerMap.get("paths"); + Map<String, Object> schemaDefinitionmap = (Map<String, Object>) swaggerMap.get("definitions"); + Map<String, Object> infoMap = (Map<String, Object>) swaggerMap.get("info"); + Map<String, List<Api>> tagMap = new LinkedHashMap<>(); + + List<Api> apis = convertToApi(map); + apis.forEach((api) -> { + if(!tagMap.containsKey(api.getTag())){ + List<Api> newApis = new ArrayList<>(); + newApis.add(api); + tagMap.put(api.getTag(), newApis); + } else { + tagMap.get(api.getTag()).add(api); + } + }); + + Map<String, List<Api>> sortedTagMap = new TreeMap<>(tagMap); + sortedTagMap.forEach((key, value) -> { + value.sort(Comparator.comparing(Api::getPath)); + }); + + Map<String, Object> resultMap = new HashMap<>(); + + List<Definition> definitionList = convertToDefinition(schemaDefinitionmap); + + definitionList = definitionList + .stream().sorted(Comparator.comparing(Definition::getDefinitionName)).collect(Collectors.toList()); + + resultMap.put("aaiApis", tagMap); + resultMap.put("sortedAaiApis", sortedTagMap); + resultMap.put("wikiLink", wikiLink); + resultMap.put("definitions", definitionList); + if (infoMap.containsKey("description")) { + String infoDescription = infoMap.get("description").toString(); + + infoDescription = Arrays.stream(infoDescription.split("\n")) + .map(line -> { + line = line.trim(); + String hyperLink = ""; + if(line.trim().contains("https://")){ + int startIndex = line.indexOf("https://"); + int endIndex = line.lastIndexOf("/"); + hyperLink = line.substring(startIndex, endIndex); + return String.format("<a href=\"%s\">%s</a><br/>", hyperLink, line); + } + return String.format("%s<br/>", line); + }) + + .collect(Collectors.joining(LINE_SEPARATOR)); + + resultMap.put("description", infoDescription); + } + + Configuration configuration = new Configuration(); + configuration.setClassForTemplateLoading(Api.class, "/"); + configuration.setDirectoryForTemplateLoading(new File("src/main/resources/")); + + Template template = configuration.getTemplate("swagger.html.ftl"); + + String outputDirStr = schemaDir + "/src/main/resources/aai_swagger_html"; + + File outputDir = new File(outputDirStr); + + if(!outputDir.exists()){ + boolean resp = outputDir.mkdir(); + if(!resp){ + System.err.println("Unable to create the directory: " + outputDirStr); + System.exit(1); + } + } else if(outputDir.isFile()){ + System.err.println("Unable to create the directory: " + outputDirStr + " since a filename with that string exists"); + System.exit(1); + } + + Writer file = new FileWriter(new File(outputDirStr + "/aai_swagger_" + versionToGenerate + ".html")); + template.process(resultMap, file); + } + + public static List<Api> convertToApi(Map<String, Object> pathMap){ + + if(pathMap == null) + throw new IllegalArgumentException(); + + List<Api> apis = new ArrayList<>(); + + pathMap.forEach( (pathKey, pathValue) -> { + + Api api = new Api(); + Map<String, Object> httpVerbMap = (Map<String, Object>) pathValue; + List<Api.HttpVerb> httpVerbs = new ArrayList<>(); + + api.setPath(pathKey); + + httpVerbMap.forEach((httpVerbKey, httpVerbValue) -> { + + Api.HttpVerb httpVerb = new Api.HttpVerb(); + + Map<String, Object> httpVerbValueMap = (Map<String,Object>)httpVerbValue; + + httpVerb.setType(httpVerbKey); + + if(httpVerbValueMap.containsKey("tags")){ + httpVerb.setTags((List<String>)httpVerbValueMap.get("tags")); + } + + if(httpVerbValueMap.containsKey("summary")){ + httpVerb.setSummary((String)httpVerbValueMap.get("summary")); + } + + if(httpVerbValueMap.containsKey("operationId")){ + httpVerb.setOperationId((String)httpVerbValueMap.get("operationId")); + } + + if(httpVerbValueMap.containsKey("consumes")){ + httpVerb.setConsumes((List<String>)httpVerbValueMap.get("consumes")); + if(httpVerb.getConsumes() != null){ + httpVerb.setConsumerEnabled(true); + } + } + + if(httpVerbValueMap.containsKey("produces")){ + httpVerb.setProduces((List<String>)httpVerbValueMap.get("produces")); + } + + if(httpVerbValueMap.containsKey("parameters")){ + List<Map<String, Object>> parameters = (List<Map<String, Object>>) httpVerbValueMap.get("parameters"); + List<Map<String, Object>> requestParameters = parameters + .stream() + .filter((parameter) -> !parameter.get("name").equals("body")) + .collect(Collectors.toList()); + httpVerb.setParameters(requestParameters); + if(httpVerb.getParameters() != null){ + httpVerb.setParametersEnabled(true); + } + + List<Map<String, Object>> requestBodyList = parameters + .stream() + .filter((parameter) -> parameter.get("name").equals("body")) + .collect(Collectors.toList()); + + Map<String, Object> requestBody = null; + + if(requestBodyList != null && requestBodyList.size() == 1){ + requestBody = requestBodyList.get(0); + httpVerb.setBodyParametersEnabled(true); + httpVerb.setBodyParameters(requestBody); + + if(requestBody != null && requestBody.containsKey("schema")){ + Map<String, Object> schemaMap = (Map<String, Object>)requestBody.get("schema"); + if(schemaMap != null && schemaMap.containsKey("$ref")){ + String schemaLink = schemaMap.get("$ref").toString(); + httpVerb.setSchemaLink(schemaLink); + int retCode = schemaLink.lastIndexOf('/'); + if(retCode != -1 && retCode != schemaLink.length()){ + httpVerb.setSchemaType(schemaLink.substring(retCode)); + } + } + } + } + } + + if(httpVerbValueMap.containsKey("responses")){ + + List<Api.HttpVerb.Response> responses = new ArrayList<Api.HttpVerb.Response>(); + + Map<String, Object> responsesMap = (Map<String, Object>) httpVerbValueMap.get("responses"); + + responsesMap + .entrySet() + .stream() + .filter((res) -> !"default".equalsIgnoreCase(res.getKey())) + .forEach((responseMap) -> { + + Map<String, Object> responseValueMap = (Map<String, Object>)responseMap.getValue(); + + Api.HttpVerb.Response response = new Api.HttpVerb.Response(); + + response.setResponseCode(responseMap.getKey()); + response.setDescription((String) responseValueMap.get("description")); + + if(responseValueMap != null && responseValueMap.containsKey("schema")){ + Map<String, Object> schemaMap = (Map<String, Object>)responseValueMap.get("schema"); + if(schemaMap != null && schemaMap.containsKey("$ref")){ + String schemaLink = schemaMap.get("$ref").toString(); + httpVerb.setHasReturnSchema(true); + httpVerb.setReturnSchemaLink(schemaLink); + int retCode = schemaLink.lastIndexOf('/'); + if(retCode != -1 && retCode != schemaLink.length()){ + httpVerb.setReturnSchemaObject(schemaLink.substring(retCode)); + } + } + } + + responses.add(response); + } + ); + + httpVerb.setResponses(responses); + } + + httpVerbs.add(httpVerb); + }); + + api.setHttpMethods(httpVerbs); + apis.add(api); + }); + + return apis; + } + + public static List<Definition> convertToDefinition(Map<String, Object> definitionMap) { + + if(definitionMap == null) + throw new IllegalArgumentException(); + + List<Definition> defintionsList = new ArrayList<>(); + + definitionMap + .entrySet() + .forEach((entry) -> { + + Definition definition = new Definition(); + String key = entry.getKey(); + Map<String, Object> valueMap = (Map<String, Object>) entry.getValue(); + + definition.setDefinitionName(key); + + if(valueMap.containsKey("description")){ + String description = valueMap.get("description").toString(); + description = formatDescription(description); + definition.setDefinitionDescription(description); + definition.setHasDescription(true); + } + + List<Definition.Property> definitionProperties = new ArrayList<>(); + + List<String> requiredProperties = (valueMap.get("required") == null) ? new ArrayList<>() : (List<String>) valueMap.get("required"); + + Set<String> requiredPropsSet = requiredProperties.stream().collect(Collectors.toSet()); + + valueMap + .entrySet() + .stream() + .filter( (e) -> "properties".equals(e.getKey())) + .forEach((propertyEntries) -> { + Map<String, Object> propertyRealEntries = (Map<String, Object>) propertyEntries.getValue(); + propertyRealEntries + .entrySet() + .forEach((propertyEntry) -> { + Definition.Property definitionProperty = new Definition.Property(); + String propertyKey = propertyEntry.getKey(); + if(requiredPropsSet.contains(propertyKey)){ + definitionProperty.setRequired(true); + } + definitionProperty.setPropertyName(propertyKey); + Map<String, Object> definitionPropertyMap = (Map<String, Object>) propertyEntry.getValue(); + + if(definitionPropertyMap.containsKey("description")){ + definitionProperty.setPropertyDescription(definitionPropertyMap.get("description").toString()); + definitionProperty.setHasPropertyDescription(true); + } + if(definitionPropertyMap.containsKey("type")){ + String type = definitionPropertyMap.get("type").toString(); + definitionProperty.setPropertyType(type); + definitionProperty.setHasType(true); + if ("array".equals(type)) { + definitionProperty.setPropertyType("object[]"); + if(!definitionPropertyMap.containsKey("items")){ + throw new RuntimeException("Unable to find the property items even though the type is array for " + propertyEntry.getKey()); + } else { + Map<String, Object> itemMap = (Map<String, Object>) definitionPropertyMap.get("items"); + if(itemMap.containsKey("$ref")){ + definitionProperty.setHasPropertyReference(true); + String refItem = itemMap.get("$ref").toString(); + int retCode = refItem.lastIndexOf('/'); + if(retCode != -1 && retCode != refItem.length()){ + definitionProperty.setPropertyReferenceObjectName(refItem.substring(retCode + 1)); + } + definitionProperty.setPropertyReference(refItem); + } + } + } else { + if(definitionPropertyMap.containsKey("$ref")){ + definitionProperty.setHasPropertyReference(true); + String refItem = definitionPropertyMap.get("$ref").toString(); + int retCode = refItem.lastIndexOf('/'); + if(retCode != -1 && retCode != refItem.length()){ + definitionProperty.setPropertyReferenceObjectName(refItem.substring(retCode + 1)); + } + definitionProperty.setPropertyReference(refItem); + } + } + } + definitionProperties.add(definitionProperty); + }); + }); + + definition.setPropertyList(definitionProperties); + + List<Definition.Property> schemaProperties = definitionProperties. + stream() + .filter((o) -> o.isHasPropertyReference()) + .collect(Collectors.toList()); + + List<Definition.Property> regularProperties = definitionProperties. + stream() + .filter((o) -> !o.isHasPropertyReference()) + .collect(Collectors.toList()); + + definition.setRegularPropertyList(regularProperties); + definition.setSchemaPropertyList(schemaProperties); + + defintionsList.add(definition); + }); + return defintionsList; + } + + public static String formatDescription(String description){ + + description = Arrays.stream(description.split("\n")) + .map((line) -> { + line = line.trim(); + if(line.contains("######")){ + line = line.replaceAll("#", ""); + line = line.trim(); + String headerId = line.toLowerCase().replaceAll("\\s", "-"); + + if(line.contains("Related Nodes")){ + return String.format("<h6 id=\"%s\">%s</h6>%s<ul>", headerId, line, LINE_SEPARATOR); + } else { + return String.format("<h6 id=\"%s\">%s</h6>", headerId, line); + } + } else if(line.startsWith("-")){ + line = line.replaceFirst("-", ""); + line = line.trim(); + return String.format("<li>%s</li>", line); + } else { + return String.format("<p>%s</p>", line); + } + }) + .collect(Collectors.joining(LINE_SEPARATOR)); + + if(description.contains("<ul>")){ + description = description + "</ul>"; + } + + return description; + } + +} diff --git a/aai-core/src/main/resources/swagger.html.ftl b/aai-core/src/main/resources/swagger.html.ftl new file mode 100644 index 00000000..4b9a4908 --- /dev/null +++ b/aai-core/src/main/resources/swagger.html.ftl @@ -0,0 +1,293 @@ +<#-- + ============LICENSE_START======================================================= + org.openecomp.aai + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + 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. + ============LICENSE_END========================================================= +--> + +<!DOCTYPE html> +<html> +<head> +<style>/*! + * Bootstrap v3.3.6 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{p EdgeRules.ftl + ont-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover,a.text-primary:focus{color:#286090}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover,a.bg-primary:focus{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:800px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:900px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#fff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform 0.6s ease-in-out;-moz-transition:-moz-transform 0.6s ease-in-out;-o-transition:-o-transform 0.6s ease-in-out;transition:transform 0.6s ease-in-out;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;-moz-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.panel-definition{border-color:#a2a2a2}.panel-definition>.panel-heading{color:#000;background-color:#eee;border-color:#a2a2a2}.panel-definition>.panel-heading+.panel-collapse>.panel-body{border-top-color:#a2a2a2}.panel-definition>.panel-heading .badge{color:#eee;background-color:#000}.panel-definition>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#a2a2a2}.json-schema-description:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Description";padding-bottom:.5em;display:block}.json-schema-description:not(:last-child){padding-bottom:1.5em}.json-schema-properties:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Properties";padding-bottom:.5em;display:block}.json-schema-properties:not(:last-child){padding-bottom:1.5em}.json-schema-properties dd:not(:last-child){padding-bottom:1em}.json-schema-properties dl{margin:0}.json-schema-example:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Example";padding-bottom:.5em;display:block}.json-schema-example:not(:last-child){padding-bottom:1.5em}.json-schema-array-items:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Items";padding-bottom:.5em;display:block}.json-schema-array-items:not(:last-child){padding-bottom:1.5em}.json-schema-allOf-inherited:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Inherited";padding-bottom:.5em;display:block}.json-schema-allOf-inherited:not(:last-child){padding-bottom:1.5em}.json-schema-allOf-inherited ul{padding-left:0;list-style:none}.json-schema-anyOf>dl{border-left:2px solid #a2a2a2;padding-left:1em}.json-schema-anyOf>dl dt:not(:first-child):before{content:"or "}.json-schema-anyOf>dl dt:first-child:before{content:"either "}.json-schema-additionalProperties:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Additional properties";padding-bottom:.5em;display:block}.json-schema-additionalProperties:not(:last-child){padding-bottom:1.5em}.json-inner-schema .json-schema-properties,.json-inner-schema .json-schema-array-items,.json-inner-schema .json-schema-description,.json-inner-schema .json-schema-example{padding-left:1em;margin-top:.5em;padding-bottom:.5em;border-left:2px solid #a2a2a2}.json-property-discriminator:before{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;background-color:#777;content:"discriminator"}a.json-property-discriminator:before:hover,a.json-property-discriminator:before:focus{color:#fff;text-decoration:none;cursor:pointer}.json-property-discriminator:before:empty{display:none}.btn .json-property-discriminator:before{position:relative;top:-1px}.json-property-discriminator:before[href]:hover,.json-property-discriminator:before[href]:focus{background-color:#5e5e5e}.json-property-required:before{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;background-color:#777;content:"required"}a.json-property-required:before:hover,a.json-property-required:before:focus{color:#fff;text-decoration:none;cursor:pointer}.json-property-required:before:empty{display:none}.btn .json-property-required:before{position:relative;top:-1px}.json-property-required:before[href]:hover,.json-property-required:before[href]:focus{background-color:#5e5e5e}.json-property-read-only:before{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;background-color:#777;content:"read only"}a.json-property-read-only:before:hover,a.json-property-read-only:before:focus{color:#fff;text-decoration:none;cursor:pointer}.json-property-read-only:before:empty{display:none}.btn .json-property-read-only:before{position:relative;top:-1px}.json-property-read-only:before[href]:hover,.json-property-read-only:before[href]:focus{background-color:#5e5e5e}.json-property-type{font-style:italic;font-weight:100}.json-property-format{font-size:smaller}.json-property-enum{font-weight:lighter;font-size:small}.json-property-default-value{font-weight:lighter;font-size:small}.json-property-default-value:before{content:'(default: "'}.json-property-default-value:after{content:'")'}.json-property-enum-item{font-weight:lighter;font-size:small}.json-property-enum-item:before,.json-property-enum-item:after{content:"\""}.json-schema--reference{font-size:90%}.table.swagger--summary>tbody>tr>td.swagger--summary-path{vertical-align:middle}.table.swagger--summary>tbody>tr>td p{margin:0}.swagger--panel-operation-post{border-color:#78cc94}.swagger--panel-operation-post>.panel-heading{color:#333;background-color:#e7f6ec;border-color:#78cc94}.swagger--panel-operation-post>.panel-heading+.panel-collapse>.panel-body{border-top-color:#78cc94}.swagger--panel-operation-post>.panel-heading .badge{color:#e7f6ec;background-color:#333}.swagger--panel-operation-post>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#78cc94}.swagger--panel-operation-post .operation-name{font-weight:bold}.swagger--panel-operation-post .operation-summary{float:right !important}.swagger--panel-operation-get{border-color:#74a8d1}.swagger--panel-operation-get>.panel-heading{color:#333;background-color:#e7f0f7;border-color:#74a8d1}.swagger--panel-operation-get>.panel-heading+.panel-collapse>.panel-body{border-top-color:#74a8d1}.swagger--panel-operation-get>.panel-heading .badge{color:#e7f0f7;background-color:#333}.swagger--panel-operation-get>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#74a8d1}.swagger--panel-operation-get .operation-name{font-weight:bold}.swagger--panel-operation-get .operation-summary{float:right !important}.swagger--panel-operation-put{border-color:#d8ab71}.swagger--panel-operation-put>.panel-heading{color:#333;background-color:#f9f2e9;border-color:#d8ab71}.swagger--panel-operation-put>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d8ab71}.swagger--panel-operation-put>.panel-heading .badge{color:#f9f2e9;background-color:#333}.swagger--panel-operation-put>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d8ab71}.swagger--panel-operation-put .operation-name{font-weight:bold}.swagger--panel-operation-put .operation-summary{float:right !important}.swagger--panel-operation-patch{border-color:#ed7c59}.swagger--panel-operation-patch>.panel-heading{color:#333;background-color:#FCE9E3;border-color:#ed7c59}.swagger--panel-operation-patch>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ed7c59}.swagger--panel-operation-patch>.panel-heading .badge{color:#FCE9E3;background-color:#333}.swagger--panel-operation-patch>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ed7c59}.swagger--panel-operation-patch .operation-name{font-weight:bold}.swagger--panel-operation-patch .operation-summary{float:right !important}.swagger--panel-operation-options{border-color:#74a8d1}.swagger--panel-operation-options>.panel-heading{color:#333;background-color:#e7f0f7;border-color:#74a8d1}.swagger--panel-operation-options>.panel-heading+.panel-collapse>.panel-body{border-top-color:#74a8d1}.swagger--panel-operation-options>.panel-heading .badge{color:#e7f0f7;background-color:#333}.swagger--panel-operation-options>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#74a8d1}.swagger--panel-operation-options .operation-name{font-weight:bold}.swagger--panel-operation-options .operation-summary{float:right !important}.swagger--panel-operation-delete{border-color:#c77d7d}.swagger--panel-operation-delete>.panel-heading{color:#333;background-color:#f5e8e8;border-color:#c77d7d}.swagger--panel-operation-delete>.panel-heading+.panel-collapse>.panel-body{border-top-color:#c77d7d}.swagger--panel-operation-delete>.panel-heading .badge{color:#f5e8e8;background-color:#333}.swagger--panel-operation-delete>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#c77d7d}.swagger--panel-operation-delete .operation-name{font-weight:bold}.swagger--panel-operation-delete .operation-summary{float:right !important}.swagger--panel-operation-head{border-color:#f3ff34}.swagger--panel-operation-head>.panel-heading{color:#333;background-color:#fcffcd;border-color:#f3ff34}.swagger--panel-operation-head>.panel-heading+.panel-collapse>.panel-body{border-top-color:#f3ff34}.swagger--panel-operation-head>.panel-heading .badge{color:#fcffcd;background-color:#333}.swagger--panel-operation-head>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#f3ff34}.swagger--panel-operation-head .operation-name{font-weight:bold}.swagger--panel-operation-head .operation-summary{float:right !important}.sw-operation-description:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Description";padding-bottom:.5em;display:block}.sw-operation-description:not(:last-child){padding-bottom:1.5em}.sw-request-params:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Request parameters";padding-bottom:.5em;display:block}.sw-request-params:not(:last-child){padding-bottom:1.5em}.sw-request-body:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Request body";padding-bottom:.5em;display:block}.sw-request-body:not(:last-child){padding-bottom:1.5em}.sw-responses:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Responses";padding-bottom:.5em;display:block}.sw-responses:not(:last-child){padding-bottom:1.5em}.swagger--global:before{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;background-color:#777;content:'global'}a.swagger--global:before:hover,a.swagger--global:before:focus{color:#fff;text-decoration:none;cursor:pointer}.swagger--global:before:empty{display:none}.btn .swagger--global:before{position:relative;top:-1px}.swagger--global:before[href]:hover,.swagger--global:before[href]:focus{background-color:#5e5e5e}table.table th.sw-param-key{width:auto}table.table th.sw-param-key:before{content:"Key"}table.table th.sw-param-name{width:auto}table.table th.sw-param-name:before{content:"Name"}table.table th.sw-param-description{width:auto}table.table th.sw-param-description:before{content:"Description"}table.table th.sw-param-data-type{width:auto}table.table th.sw-param-data-type:before{content:"Data type"}table.table th.sw-param-type{width:auto}table.table th.sw-param-type:before{content:"Type"}table.table th.sw-request-security-schema{width:auto}table.table th.sw-request-security-schema:before{content:"Schema"}table.table th.sw-request-security-scopes{width:auto}table.table th.sw-request-security-scopes:before{content:"Scopes"}table.table th.sw-response-header-name{width:auto}table.table th.sw-response-header-name:before{content:"Header"}table.table th.sw-response-header-description{width:auto}table.table th.sw-response-header-description:before{content:"Description"}table.table th.sw-response-header-data-type{width:auto}table.table th.sw-response-header-data-type:before{content:"Data type"}.sw-response-name-value{font-weight:bold}.sw-response-description-text{padding-bottom:.5em}code.highlight{padding:0}.panel-security-definition{border-color:#a2a2a2}.panel-security-definition>.panel-heading{color:#000;background-color:#eee;border-color:#a2a2a2}.panel-security-definition>.panel-heading+.panel-collapse>.panel-body{border-top-color:#a2a2a2}.panel-security-definition>.panel-heading .badge{color:#eee;background-color:#000}.panel-security-definition>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#a2a2a2}.sw-request-security:before{font-weight:bold;color:#555;text-transform:uppercase;content:"Security";padding-bottom:.5em;display:block}.sw-request-security:not(:last-child){padding-bottom:1.5em}.sw-security-definition-basic:before{color:#555;font-size:smaller;content:"(HTTP Basic Authentication)"}span.sw-default-value-header{font-weight:bold}.sw-info-version{font-weight:bold}.sw-info-version span{font-family:monospace;font-weight:normal;font-size:1.1em}</style> + + <meta charset="UTF-8"> + <title>Active and Available Inventory REST API.</title> +</head> +<body> +<div class="container"> + <h1>Active and Available Inventory REST API.</h1> + <p class="sw-info-version">Version: <span>v10</span></p> + <p><p>${description}</p> + </p> + + <div id="sw-schemes" class="sw-default-value"> + <span class="sw-default-value-header">Schemes:</span> + https + </div> + + + <h2 id="swagger--summary-tags">Summary</h2> + <#list aaiApis?keys as key> + + <h3 id="tag-${key}" class="swagger-summary-tag">Tag: ${key}</h3> + + <table class="table table-bordered table-condensed swagger--summary"> + <thead> + <tr> + <th>Operation</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <#list aaiApis[key] as api> + <#list api.getHttpMethods() as httpVerb> + <tr> + <td><a href="#operation-${api.getOperation()}${httpVerb.getType()}">${httpVerb.getType()?upper_case} ${api.getPath()}</a></td> + <td><p>${httpVerb.getSummary()}</p> + </td> + </tr> + </#list> + </#list> + </tbody> + </table> + + </#list> + + + + <h2>Paths</h2> + + <#list sortedAaiApis?keys as key> + <#list sortedAaiApis[key] as api> + <#list api.getHttpMethods() as httpVerb> + + <span id="path-${api.getOperation()}"></span> + <div id="operation-${api.getOperation()}${httpVerb.getType()}" class="swagger--panel-operation-${httpVerb.getType()} panel"> + <div class="panel-heading"> + <div class="operation-summary">${httpVerb.getSummary()}</div> + <h3 class="panel-title"><span class="operation-name">${httpVerb.getType()?upper_case}</span> <strong>${api.getPath()}</strong></h3> + Tags: + <a href="#tag-${api.getTag()}">${api.getTag()}</a> + </div> + <div class="panel-body"> + <section class="sw-operation-description"> + <p>${httpVerb.getSummary()}</p> + + </section> + <#if httpVerb.isConsumerEnabled()> + <section class="sw-request-body"> + + <p><span class="label label-default">application/json</span> <span class="label label-default">application/xml</span> + </p> + <#if httpVerb.isBodyParametersEnabled()> + <div class="row"> + <div class="col-md-6"> + <p><p>${httpVerb.getBodyParameters()["description"]}</p> + </p> + </div> + <div class="col-md-6 sw-request-model"> + <div class="panel panel-definition"> + <div class="panel-body"> + <a class="json-schema-ref" href="${httpVerb.getSchemaLink()}">${httpVerb.getSchemaType()}</a> + </div> + </div></div> + </div> + </#if> + </section> + </#if> + <#if httpVerb.isParametersEnabled()> + <section class="sw-request-params"> + <table class="table"> + <thead> + <tr> + <th class="sw-param-name"></th> + <th class="sw-param-description"></th> + <th class="sw-param-type"></th> + <th class="sw-param-data-type"></th> + <th class="sw-param-annotation"></th> + </tr> + </thead> + <tbody> + <#list httpVerb.getParameters() as param> + <tr> + <td> + ${param["name"]} + </td> + <td> + <#if param['description']??> + <p>${param["description"]}</p> + </#if> + </td> + <td>${param["in"]}</td> + <td> + <#if param['type']??> + <span class="json-property-type">${param["type"]}</span> + <span class="json-property-range" title="Value limits"></span> + </#if> + </td> + <td> + <#if param['required']> + <span class="json-property-required"></span> + </#if> + </td> + </tr> + </#list> + </tbody> + </table> + </section> + </#if> + + <section class="sw-responses"> + <p><span class="label label-default">application/json</span> <span class="label label-default">application/xml</span> + </p> + + <dl> + <#list httpVerb.getResponses() as response> + <dt class="sw-response-${response.getResponseCode()}"> + ${response.getResponseCode()} OK + + </dt> + <dd class="sw-response-${response.getResponseCode()}"> + <div class="row"> + <div class="col-md-12"> + <p>successful operation</p> + + </div> + </div> + <div class="row"> + + <#if httpVerb.isHasReturnSchema()> + <div class="col-md-6 sw-response-model"> + <div class="panel panel-definition"> + + <div class="panel-body"> + <a class="json-schema-ref" href="${httpVerb.getReturnSchemaLink()}">${httpVerb.getReturnSchemaObject()}</a> + </div> + </div> + </div> + </#if> + + </div> </dd> + </#list> + <dt class="sw-response-default"> + default + + </dt> + <dd class="sw-response-default"> + <div class="row"> + <div class="col-md-12"> + <p>Response codes found in <a href="${wikiLink}">response codes</a>.</p> + + </div> + </div> + <div class="row"> + + <div class="col-md-6 sw-response-model"> + </div> + + </div> </dd> + </dl> + </section> + </div> + </div> + </#list> + </#list> + </#list> + + + <h2>Schema definitions</h2> + + <#list definitions as definition> + <div id="definition-${definition.getDefinitionName()}" class="panel panel-definition"> + <div class="panel-heading"> + <h3 class="panel-title"><a name="/definitions/${definition.getDefinitionName()}"></a>${definition.getDefinitionName()}: + <span class="json-property-type"><span class="json-property-type">object</span> + <span class="json-property-range" title="Value limits"></span> + + </span> + </h3> + </div> + <div class="panel-body"> + <#if definition.isHasDescription()> + <section class="json-schema-description"> + ${definition.getDefinitionDescription()} + + </section> + </#if> + + <section class="json-schema-properties"> + <dl> + <#list definition.getRegularPropertyList() as definitionProperty> + <dt data-property-name="${definitionProperty.getPropertyName()}"> + <span class="json-property-name">${definitionProperty.getPropertyName()}:</span> + <#if definitionProperty.isHasType()> + <span class="json-property-type">${definitionProperty.getPropertyType()}</span> + </#if> + <span class="json-property-range" title="Value limits"></span> + + <#if definitionProperty.isRequired()> + <span class="json-property-required"></span> + </#if> + </dt> + <dd> + <#if definitionProperty.isHasPropertyDescription()> + <p>${definitionProperty.getPropertyDescription()}</p> + </#if> + <div class="json-inner-schema"> + + </div> + </dd> + </#list> + <#list definition.getSchemaPropertyList() as definitionProperty> + <dt data-property-name="${definitionProperty.getPropertyName()}"> + <span class="json-property-name">${definitionProperty.getPropertyName()}:</span> + <#if definitionProperty.isHasType()> + <span class="json-property-type">${definitionProperty.getPropertyType()}</span> + </#if> + <span class="json-property-range" title="Value limits"></span> + + <#if definitionProperty.isRequired()> + <span class="json-property-required"></span> + </#if> + </dt> + <dd> + + <div class="json-inner-schema"> + + <section class="json-schema-array-items"> + <span class="json-property-type"> <a class="json-schema-ref" href="${definitionProperty.getPropertyReference()}">${definitionProperty.getPropertyReferenceObjectName()}</a> + </span> + <span class="json-property-range" title="Value limits"></span> + + <div class="json-inner-schema"> + + </div> + </section> </div> + </dd> + </#list> + </dl> + </section> + </div> + </div> + </#list> +</div> +</body> +</html> diff --git a/aai-core/src/test/java/org/openecomp/aai/serialization/tinkerpop/TreeBackedVertexTest.java b/aai-core/src/test/java/org/openecomp/aai/serialization/tinkerpop/TreeBackedVertexTest.java index 00e34e4c..23ebe07c 100644 --- a/aai-core/src/test/java/org/openecomp/aai/serialization/tinkerpop/TreeBackedVertexTest.java +++ b/aai-core/src/test/java/org/openecomp/aai/serialization/tinkerpop/TreeBackedVertexTest.java @@ -32,6 +32,7 @@ import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.Ignore; import org.openecomp.aai.serialization.engines.query.GraphTraversalQueryEngine; @@ -64,6 +65,8 @@ public class TreeBackedVertexTest { treeDepth1 = new GraphTraversalQueryEngine(g).findSubGraph((Vertex)startKey, 1, false); treeDepth0NodeOnly = new GraphTraversalQueryEngine(g).findSubGraph((Vertex)startKey, 0, true); } + + @Ignore @Test public void oneHopViaEdges() { @@ -77,6 +80,7 @@ public class TreeBackedVertexTest { } + @Ignore @Test public void oneHopViaVertices() { @@ -89,6 +93,7 @@ public class TreeBackedVertexTest { } + @Ignore @Test public void twoHopCousinViaVertices() { diff --git a/aai-core/src/test/resources/org/openecomp/aai/introspection/aai_oxm_v10.xml b/aai-core/src/test/resources/org/openecomp/aai/introspection/aai_oxm_v10.xml index bf87893c..27f03332 100644 --- a/aai-core/src/test/resources/org/openecomp/aai/introspection/aai_oxm_v10.xml +++ b/aai-core/src/test/resources/org/openecomp/aai/introspection/aai_oxm_v10.xml @@ -4447,7 +4447,7 @@ </xml-element> <xml-element java-attribute="ikev1Encryption" name="ikev1-encryption" type="java.lang.String"> <xml-properties> - <xml-property name="description" value="Encyption values like 3des-cbc, des-cbc, aes-128-cbc, aes-192-cbc, aes-265-cbc" /> + <xml-property name="description" value="Encyption values like 3des-cbc, des-cbc, aes-128-cbc,?aes-192-cbc, aes-265-cbc" /> </xml-properties> </xml-element> <xml-element java-attribute="ikev1DhGroup" name="ikev1-dh-group" type="java.lang.String"> @@ -4477,7 +4477,7 @@ </xml-element> <xml-element java-attribute="ipsecEncryption" name="ipsec-encryption" type="java.lang.String"> <xml-properties> - <xml-property name="description" value="3des-cbc, des-cbc, aes-128-cbc, aes-192-cbc, aes-265-cbc" /> + <xml-property name="description" value="3des-cbc, des-cbc, aes-128-cbc,?aes-192-cbc, aes-265-cbc" /> </xml-properties> </xml-element> <xml-element java-attribute="ipsecSaLifetime" name="ipsec-sa-lifetime" type="java.lang.String"> @@ -5536,7 +5536,7 @@ </xml-element> <xml-element java-attribute="designType" name="design-type" required="true" type="java.lang.String"> <xml-properties> - <xml-property name="description" value="Design of zone [Medium/Large…]" /> + <xml-property name="description" value="Design of zone [Medium/Large?]" /> </xml-properties> </xml-element> <xml-element java-attribute="zoneContext" name="zone-context" required="true" type="java.lang.String"> diff --git a/aai-core/src/test/resources/org/openecomp/aai/serialization/queryformats/resource_and_url-format.json b/aai-core/src/test/resources/org/openecomp/aai/serialization/queryformats/resource_and_url-format.json index 80d6560b..d90a71bc 100644 --- a/aai-core/src/test/resources/org/openecomp/aai/serialization/queryformats/resource_and_url-format.json +++ b/aai-core/src/test/resources/org/openecomp/aai/serialization/queryformats/resource_and_url-format.json @@ -1,7 +1,7 @@ { "results": [ { - "url" : "/cloud-infrastructure/cloud-regions/cloud-region/cloud-owner-987654321-9922/cloud-region-id-987654321-9922/tenants/tenant/tenant-987654321-9999/vservers/vserver/vserver-987654321-9999", + "url" : "/cloud-infrastructure/cloud-regions/cloud-region/cloud-owner-987654321-9922-as988q/cloud-region-id-987654321-9922-as988q/tenants/tenant/tenant-987654321-9999-as988q/vservers/vserver/vserver-987654321-9999-as988q", "vserver": { } @@ -13,4 +13,4 @@ } } ] -} +}
\ No newline at end of file |