mirror of https://github.com/apache/jclouds.git
Merge pull request #276 from grkvlt/master
CloudStack ISO Stub Live Test
This commit is contained in:
commit
1e637acbee
|
@ -22,6 +22,8 @@ import org.jclouds.cloudstack.domain.ISO;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for the ISO listISOs method.
|
* Options for the ISO listISOs method.
|
||||||
*
|
*
|
||||||
|
@ -30,14 +32,24 @@ import com.google.common.collect.ImmutableSet;
|
||||||
* @author Richard Downer
|
* @author Richard Downer
|
||||||
*/
|
*/
|
||||||
public class ListISOsOptions extends AccountInDomainOptions {
|
public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
|
|
||||||
public static final ListISOsOptions NONE = new ListISOsOptions();
|
public static final ListISOsOptions NONE = new ListISOsOptions();
|
||||||
|
|
||||||
|
private static final Set<String> TRUE = ImmutableSet.of(Boolean.toString(true));
|
||||||
|
private static final Set<String> FALSE = ImmutableSet.of(Boolean.toString(false));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bootable true if the ISO is bootable, false otherwise
|
* the ISO is bootable
|
||||||
*/
|
*/
|
||||||
public ListISOsOptions bootable(boolean bootable) {
|
public ListISOsOptions bootable() {
|
||||||
this.queryParameters.replaceValues("bootable", ImmutableSet.of(bootable + ""));
|
this.queryParameters.replaceValues("bootable", TRUE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the ISO is bootable
|
||||||
|
*/
|
||||||
|
public ListISOsOptions notBootable() {
|
||||||
|
this.queryParameters.replaceValues("bootable", FALSE);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +57,7 @@ public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
* @param hypervisor the hypervisor for which to restrict the search
|
* @param hypervisor the hypervisor for which to restrict the search
|
||||||
*/
|
*/
|
||||||
public ListISOsOptions hypervisor(String hypervisor) {
|
public ListISOsOptions hypervisor(String hypervisor) {
|
||||||
this.queryParameters.replaceValues("hypervisor", ImmutableSet.of(hypervisor + ""));
|
this.queryParameters.replaceValues("hypervisor", ImmutableSet.of(hypervisor));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +65,7 @@ public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
* @param id list all isos by id
|
* @param id list all isos by id
|
||||||
*/
|
*/
|
||||||
public ListISOsOptions id(long id) {
|
public ListISOsOptions id(long id) {
|
||||||
this.queryParameters.replaceValues("id", ImmutableSet.of(id + ""));
|
this.queryParameters.replaceValues("id", ImmutableSet.of(Long.toString(id)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,23 +73,39 @@ public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
* @param isoFilter possible values are "featured", "self", "self-executable","executable", and "community".
|
* @param isoFilter possible values are "featured", "self", "self-executable","executable", and "community".
|
||||||
*/
|
*/
|
||||||
public ListISOsOptions isoFilter(ISO.ISOFilter isoFilter) {
|
public ListISOsOptions isoFilter(ISO.ISOFilter isoFilter) {
|
||||||
this.queryParameters.replaceValues("isofilter", ImmutableSet.of(isoFilter + ""));
|
this.queryParameters.replaceValues("isofilter", ImmutableSet.of(isoFilter.name()));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param isPublic true if the ISO is publicly available to all users, false otherwise.
|
* the ISO is publicly available to all users
|
||||||
*/
|
*/
|
||||||
public ListISOsOptions isPublic(boolean isPublic) {
|
public ListISOsOptions isPublic() {
|
||||||
this.queryParameters.replaceValues("ispublic", ImmutableSet.of(isPublic + ""));
|
this.queryParameters.replaceValues("ispublic", TRUE);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param isReady true if this ISO is ready to be deployed
|
* the ISO is not publicly available to all users
|
||||||
*/
|
*/
|
||||||
public ListISOsOptions isReady(boolean isReady) {
|
public ListISOsOptions isPrivate() {
|
||||||
this.queryParameters.replaceValues("isready", ImmutableSet.of(isReady + ""));
|
this.queryParameters.replaceValues("ispublic", FALSE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this ISO is ready to be deployed
|
||||||
|
*/
|
||||||
|
public ListISOsOptions isReady() {
|
||||||
|
this.queryParameters.replaceValues("isready", TRUE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this ISO is not ready to be deployed
|
||||||
|
*/
|
||||||
|
public ListISOsOptions isNotReady() {
|
||||||
|
this.queryParameters.replaceValues("isready", FALSE);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +113,7 @@ public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
* @param keyword List by keyword
|
* @param keyword List by keyword
|
||||||
*/
|
*/
|
||||||
public ListISOsOptions keyword(String keyword) {
|
public ListISOsOptions keyword(String keyword) {
|
||||||
this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword + ""));
|
this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +121,7 @@ public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
* @param name list all isos by name
|
* @param name list all isos by name
|
||||||
*/
|
*/
|
||||||
public ListISOsOptions name(String name) {
|
public ListISOsOptions name(String name) {
|
||||||
this.queryParameters.replaceValues("name", ImmutableSet.of(name + ""));
|
this.queryParameters.replaceValues("name", ImmutableSet.of(name));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,12 +129,11 @@ public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
* @param zoneId the ID of the zone
|
* @param zoneId the ID of the zone
|
||||||
*/
|
*/
|
||||||
public ListISOsOptions zoneId(long zoneId) {
|
public ListISOsOptions zoneId(long zoneId) {
|
||||||
this.queryParameters.replaceValues("zoneid", ImmutableSet.of(zoneId + ""));
|
this.queryParameters.replaceValues("zoneid", ImmutableSet.of(Long.toString(zoneId)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param account the account of the ISO file. Must be used with the domainId parameter.
|
* @param account the account of the ISO file. Must be used with the domainId parameter.
|
||||||
*/
|
*/
|
||||||
|
@ -115,10 +142,17 @@ public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bootable true if the ISO is bootable, false otherwise
|
* the ISO is bootable
|
||||||
*/
|
*/
|
||||||
public static ListISOsOptions bootable(boolean bootable) {
|
public static ListISOsOptions bootable() {
|
||||||
return new ListISOsOptions().bootable(bootable);
|
return new ListISOsOptions().bootable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the ISO is bootable
|
||||||
|
*/
|
||||||
|
public static ListISOsOptions notBootable() {
|
||||||
|
return new ListISOsOptions().notBootable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,17 +184,31 @@ public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param isPublic true if the ISO is publicly available to all users, false otherwise.
|
* the ISO is publicly available to all users
|
||||||
*/
|
*/
|
||||||
public static ListISOsOptions isPublic(boolean isPublic) {
|
public static ListISOsOptions isPublic() {
|
||||||
return new ListISOsOptions().isPublic(isPublic);
|
return new ListISOsOptions().isPublic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param isReady true if this ISO is ready to be deployed
|
* the ISO is not publicly available to all users
|
||||||
*/
|
*/
|
||||||
public static ListISOsOptions isReady(boolean isReady) {
|
public static ListISOsOptions isPrivate() {
|
||||||
return new ListISOsOptions().isReady(isReady);
|
return new ListISOsOptions().isPrivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this ISO is ready to be deployed
|
||||||
|
*/
|
||||||
|
public static ListISOsOptions isReady() {
|
||||||
|
return new ListISOsOptions().isReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this ISO is not ready to be deployed
|
||||||
|
*/
|
||||||
|
public static ListISOsOptions isNotReady() {
|
||||||
|
return new ListISOsOptions().isNotReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,5 +232,4 @@ public class ListISOsOptions extends AccountInDomainOptions {
|
||||||
return new ListISOsOptions().zoneId(zoneId);
|
return new ListISOsOptions().zoneId(zoneId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ public class ISOAsyncClientTest extends BaseCloudStackAsyncClientTest<ISOAsyncCl
|
||||||
|
|
||||||
public void testListISOsOptions() throws NoSuchMethodException {
|
public void testListISOsOptions() throws NoSuchMethodException {
|
||||||
Method method = ISOAsyncClient.class.getMethod("listISOs", ListISOsOptions[].class);
|
Method method = ISOAsyncClient.class.getMethod("listISOs", ListISOsOptions[].class);
|
||||||
HttpRequest httpRequest = processor.createRequest(method, ListISOsOptions.Builder.accountInDomain("fred", 5).bootable(true).hypervisor("xen").id(3).isoFilter(ISO.ISOFilter.featured).isPublic(true).isReady(true).keyword("bob").name("bob's iso").zoneId(7));
|
HttpRequest httpRequest = processor.createRequest(method, ListISOsOptions.Builder.accountInDomain("fred", 5).bootable().hypervisor("xen").id(3).isoFilter(ISO.ISOFilter.featured).isPublic().isReady().keyword("bob").name("bob's iso").zoneId(7));
|
||||||
|
|
||||||
assertRequestLineEquals(httpRequest,
|
assertRequestLineEquals(httpRequest,
|
||||||
"GET http://localhost:8080/client/api?response=json&command=listISOs&account=fred&domainid=5&bootable=true&hypervisor=xen&id=3&isofilter=featured&ispublic=true&isready=true&keyword=bob&name=bob%27s%20iso&zoneid=7 HTTP/1.1");
|
"GET http://localhost:8080/client/api?response=json&command=listISOs&account=fred&domainid=5&bootable=true&hypervisor=xen&id=3&isofilter=featured&ispublic=true&isready=true&keyword=bob&name=bob%27s%20iso&zoneid=7 HTTP/1.1");
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.cloudstack.features;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.domain.ISO;
|
||||||
|
import org.jclouds.cloudstack.domain.Zone;
|
||||||
|
import org.jclouds.cloudstack.options.ListISOsOptions;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@link ISOClient} and {@link ISOAsyncClient}
|
||||||
|
*
|
||||||
|
* @author grkvlt@apache.org
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", singleThreaded = true, testName = "ISOClientLiveTest")
|
||||||
|
public class ISOClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
|
public void testListPublicISOs() throws Exception {
|
||||||
|
Set<ISO> response = client.getISOClient().listISOs(ListISOsOptions.Builder.isPublic());
|
||||||
|
assertNotNull(response);
|
||||||
|
assertFalse(response.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.cloudstack.options;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import org.jclouds.cloudstack.domain.ISO;
|
||||||
|
import org.jclouds.cloudstack.domain.TemplateFilter;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.jclouds.cloudstack.options.ListISOsOptions.Builder.*;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@link ListISOsOptions}
|
||||||
|
*
|
||||||
|
* @author grkvlt@apache.org
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class ListISOsOptionsTest {
|
||||||
|
private static final Set<String> TRUE = ImmutableSet.of(Boolean.toString(true));
|
||||||
|
private static final Set<String> FALSE = ImmutableSet.of(Boolean.toString(false));
|
||||||
|
|
||||||
|
public void testBootable() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().bootable();
|
||||||
|
assertEquals(options.buildQueryParameters().get("bootable"), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBootableStatic() {
|
||||||
|
ListISOsOptions options = bootable();
|
||||||
|
assertEquals(options.buildQueryParameters().get("bootable"), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNotBootable() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().notBootable();
|
||||||
|
assertEquals(options.buildQueryParameters().get("bootable"), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNotBootableStatic() {
|
||||||
|
ListISOsOptions options = notBootable();
|
||||||
|
assertEquals(options.buildQueryParameters().get("bootable"), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testHypervisor() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().hypervisor("KVM");
|
||||||
|
assertEquals(options.buildQueryParameters().get("hypervisor"), ImmutableSet.of("KVM"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testHypervisorStatic() {
|
||||||
|
ListISOsOptions options = hypervisor("KVM");
|
||||||
|
assertEquals(options.buildQueryParameters().get("hypervisor"), ImmutableSet.of("KVM"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testId() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().id(6);
|
||||||
|
assertEquals(options.buildQueryParameters().get("id"), ImmutableSet.of("6"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIdStatic() {
|
||||||
|
ListISOsOptions options = id(6);
|
||||||
|
assertEquals(options.buildQueryParameters().get("id"), ImmutableSet.of("6"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testISOFilter() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().isoFilter(ISO.ISOFilter.community);
|
||||||
|
assertEquals(options.buildQueryParameters().get("isofilter"), ImmutableSet.of(ISO.ISOFilter.community.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testISOFilterStatic() {
|
||||||
|
ListISOsOptions options = isoFilter(ISO.ISOFilter.community);
|
||||||
|
assertEquals(options.buildQueryParameters().get("isofilter"), ImmutableSet.of(ISO.ISOFilter.community.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsPublic() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().isPublic();
|
||||||
|
assertEquals(options.buildQueryParameters().get("ispublic"), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsPublicStatic() {
|
||||||
|
ListISOsOptions options = isPublic();
|
||||||
|
assertEquals(options.buildQueryParameters().get("ispublic"), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsPrivate() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().isPrivate();
|
||||||
|
assertEquals(options.buildQueryParameters().get("ispublic"), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsPrivateStatic() {
|
||||||
|
ListISOsOptions options = isPrivate();
|
||||||
|
assertEquals(options.buildQueryParameters().get("ispublic"), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsReady() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().isReady();
|
||||||
|
assertEquals(options.buildQueryParameters().get("isready"), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsReadyStatic() {
|
||||||
|
ListISOsOptions options = isReady();
|
||||||
|
assertEquals(options.buildQueryParameters().get("isready"), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsNotReady() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().isNotReady();
|
||||||
|
assertEquals(options.buildQueryParameters().get("isready"), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsNotReadyStatic() {
|
||||||
|
ListISOsOptions options = isNotReady();
|
||||||
|
assertEquals(options.buildQueryParameters().get("isready"), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testKeyword() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().keyword("text");
|
||||||
|
assertEquals(options.buildQueryParameters().get("keyword"), ImmutableSet.of("text"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testKeywordStatic() {
|
||||||
|
ListISOsOptions options = keyword("text");
|
||||||
|
assertEquals(options.buildQueryParameters().get("keyword"), ImmutableSet.of("text"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testName() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().name("text");
|
||||||
|
assertEquals(options.buildQueryParameters().get("name"), ImmutableSet.of("text"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNameStatic() {
|
||||||
|
ListISOsOptions options = name("text");
|
||||||
|
assertEquals(options.buildQueryParameters().get("name"), ImmutableSet.of("text"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testZoneId() {
|
||||||
|
ListISOsOptions options = new ListISOsOptions().zoneId(6);
|
||||||
|
assertEquals(ImmutableSet.of("6"), options.buildQueryParameters().get("zoneid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testZoneIdStatic() {
|
||||||
|
ListISOsOptions options = zoneId(6);
|
||||||
|
assertEquals(ImmutableSet.of("6"), options.buildQueryParameters().get("zoneid"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,10 +47,9 @@ public interface PopulateDefaultLoginCredentialsForImageStrategy extends Functio
|
||||||
Credentials execute(Object resourceToAuthenticate);
|
Credentials execute(Object resourceToAuthenticate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Processes the cloud-specific resources to determine the login credentials.
|
* Processes the cloud-specific resources to determine the login credentials.
|
||||||
*
|
*
|
||||||
* @param resourceToAuthenticate
|
* @param image
|
||||||
* this is the cloud-specific representation of the image object.
|
* this is the cloud-specific representation of the image object.
|
||||||
* @return credentials parsed from the image if not null
|
* @return credentials parsed from the image if not null
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue