/*
 * This file is part of Dependency-Track.
 *
 * 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.
 *
 * Copyright (c) Steve Springett. All Rights Reserved.
 */
package org.owasp.dependencytrack.parser.dependencycheck.resolver;

import alpine.logging.Logger;
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import org.owasp.dependencytrack.parser.dependencycheck.model.Dependency;
import org.owasp.dependencytrack.parser.dependencycheck.model.Identifier;
import java.util.TreeMap;

/**
 * Attempts to resolve the PackageURL from high-quality and reliable evidence.
 *
 * @author Steve Springett
 * @since 3.0.0
 */
public class PackageURLResolver implements IResolver {

    private static final Logger LOGGER = Logger.getLogger(PackageURLResolver.class);

    /**
     * {@inheritDoc}
     */
    public PackageURL resolve(Dependency dependency) {
        try {
            if (dependency.getIdentifiers() != null && dependency.getIdentifiers().getIdentifiers() != null) {
                for (Identifier identifier : dependency.getIdentifiers().getIdentifiers()) {
                    if ("maven".equals(identifier.getType())
                            && ("HIGHEST".equals(identifier.getConfidence()) || "HIGH".equals(identifier.getConfidence()))) {

                        final GAV gav = parseIdentifier(identifier);
                        if (dependency.getFileName() != null && dependency.getFileName().contains(".")) {
                            final String extension = dependency.getFileName().substring(
                                    dependency.getFileName().lastIndexOf(".") + 1, dependency.getFileName().length()
                            );
                            TreeMap<String, String> qualifiers = new TreeMap<>();
                            qualifiers.put("type", extension);
                            return new PackageURL(PackageURL.StandardTypes.MAVEN, gav.group, gav.artifact, gav.version, qualifiers, null);
                        } else {
                            return new PackageURL(PackageURL.StandardTypes.MAVEN, gav.group, gav.artifact, gav.version, null, null);
                        }

                    } else if ("npm".equals(identifier.getType())
                            && ("HIGHEST".equals(identifier.getConfidence()) || "HIGH".equals(identifier.getConfidence()))) {
                        final GAV gav = parseIdentifier(identifier);
                        return new PackageURL(PackageURL.StandardTypes.NPM, gav.group, gav.artifact, gav.version, null, null);
                    }

                    // todo: add PHP Composer, NuGet, Rubygems, and other supported types. Pull requests welcome :-)
                }

            }
        } catch (MalformedPackageURLException e) {
            LOGGER.warn("An error occurred while attempting to resolve PackageURL", e);
        }
        return null;
    }

    private GAV parseIdentifier(Identifier identifier) {
        if (identifier == null || identifier.getName() == null) {
            return null;
        }
        if (identifier.getName().startsWith("(") && identifier.getName().endsWith(")")) {
            final GAV gav = new GAV();
            final String[] parts = identifier.getName().substring(1, identifier.getName().length() - 1).split(":");
            if (parts.length == 2) {
                gav.artifact = parts[0];
                gav.version = parts[1];
            } else if (parts.length == 3) {
                gav.group = parts[0];
                gav.artifact = parts[1];
                gav.version = parts[2];
            } else {
                return null; // this is not being accounted for and would likely never happen.
            }
            return gav;
        }
        return null;
    }

    private class GAV {
        private String group = null;
        private String artifact = null;
        private String version = null;
    }

}

@@ -3566,47 +3566,128 @@
     
-    return null;%0A        %7D%0A        if (
+%09throw new IllegalArgumentException(%22Must specify an identifier with a name%22);%0A        %7D%0A        %0A        String name = 
 iden
@@ -3702,16 +3702,34 @@
 etName()
+;%0A        if (name
 .startsW
@@ -3740,36 +3740,20 @@
 %22(%22) && 
-identifier.getN
+n
 ame
-()
 .endsWit
@@ -3758,32 +3758,99 @@
 ith(%22)%22)) %7B%0A    
+    %09name = name.substring(1, name.length()-1);%0A        %7D%0A        %0A
         final GA
@@ -3868,36 +3868,32 @@
  GAV();%0A        
-    
 final String%5B%5D p
@@ -3903,76 +3903,12 @@
 s = 
-identifier.getName().substring(1, identifier.getName().length() - 1)
+name
 .spl
@@ -3912,28 +3912,24 @@
 split(%22:%22);%0A
-    
         if (
@@ -3945,28 +3945,24 @@
 gth == 2) %7B%0A
-    
             
@@ -3990,36 +3990,32 @@
 0%5D;%0A            
-    
 gav.version = pa
@@ -4022,36 +4022,32 @@
 rts%5B1%5D;%0A        
-   
- 
 %7D else if (parts
@@ -4070,28 +4070,24 @@
             
-    
 gav.group = 
@@ -4100,36 +4100,32 @@
 0%5D;%0A            
-  
-  
 gav.artifact = p
@@ -4137,36 +4137,32 @@
 1%5D;%0A            
-    
 gav.version = pa
@@ -4169,36 +4169,32 @@
 rts%5B2%5D;%0A        
- 
-   
 %7D else %7B%0A       
@@ -4198,131 +4198,73 @@
     
-   
-     return null; // this is not being accounted for and would likely never happen.%0A            %7D%0A            return gav
+%09throw new IllegalArgumentException(%22Got bad identifier %22 + name)
 ;%0A  
@@ -4278,36 +4278,35 @@
 %0A        return 
-null
+gav
 ;%0A    %7D%0A%0A    pri
@@ -4444,11 +4444,10 @@
 ;%0A    %7D%0A
-%0A
 %7D%0A

Fix GAV parsing so it can handle scan reports from Gradle (fixes #156)