content: /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF 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
   *
   *      https://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.apache.ivy.osgi.p2;
  
  import java.net.URI;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Set;
  
  import org.apache.ivy.osgi.core.BundleArtifact;
  import org.apache.ivy.osgi.core.BundleInfo;
  import org.apache.ivy.osgi.core.ExecutionEnvironmentProfileProvider;
  import org.apache.ivy.osgi.repo.EditableRepoDescriptor;
  import org.apache.ivy.osgi.repo.ModuleDescriptorWrapper;
  import org.apache.ivy.osgi.util.Version;
  import org.apache.ivy.util.Message;
  
  public class P2Descriptor extends EditableRepoDescriptor {
  
      private Map<String, Map<Version, BundleInfo>> sourceTargetBundles = new HashMap<>();
  
      private Map<String, Map<Version, BundleInfo>> sourceBundles = new HashMap<>();
  
      public P2Descriptor(URI repoUri, ExecutionEnvironmentProfileProvider profileProvider) {
          super(repoUri, profileProvider);
      }
  
      public void addBundle(BundleInfo bundleInfo) {
          if (bundleInfo.isSource()) {
              if (bundleInfo.getSymbolicNameTarget() == null || bundleInfo.getVersionTarget() == null) {
                  if (getLogLevel() <= Message.MSG_VERBOSE) {
                      Message.verbose("The source bundle " + bundleInfo.getSymbolicName()
                              + " did not declare its target. Ignoring it");
                  }
                  return;
              }
              Map<Version, BundleInfo> byVersion = sourceBundles.get(bundleInfo.getSymbolicName());
              if (byVersion == null) {
                  byVersion = new HashMap<>();
                  sourceBundles.put(bundleInfo.getSymbolicName(), byVersion);
              }
              byVersion.put(bundleInfo.getVersion(), bundleInfo);
  
              Map<Version, BundleInfo> byTargetVersion = sourceTargetBundles.get(bundleInfo
                      .getSymbolicNameTarget());
              if (byTargetVersion == null) {
                  byTargetVersion = new HashMap<>();
                  sourceTargetBundles.put(bundleInfo.getSymbolicNameTarget(), byTargetVersion);
              }
              BundleInfo old = byTargetVersion.put(bundleInfo.getVersionTarget(), bundleInfo);
              if (old != null && !old.equals(bundleInfo)) {
                  if (getLogLevel() <= Message.MSG_VERBOSE) {
                      Message.verbose("Duplicate source for the bundle "
                              + bundleInfo.getSymbolicNameTarget() + "@"
                              + bundleInfo.getVersionTarget() + " : " + bundleInfo + " is replacing "
                              + old);
                  }
              }
              return;
          }
  
          super.addBundle(bundleInfo);
      }
  
      public void finish() {
          sourceBundles = null;
          Set<String> bundleIds = getCapabilityValues(BundleInfo.BUNDLE_TYPE);
          if (bundleIds == null) {
              return;
          }
          for (String bundleId : bundleIds) {
              for (ModuleDescriptorWrapper mdw : findModules(BundleInfo.BUNDLE_TYPE, bundleId)) {
                  String symbolicName = mdw.getBundleInfo().getSymbolicName();
                  Map<Version, BundleInfo> byVersion = sourceTargetBundles.get(symbolicName);
                  if (byVersion == null) {
                      continue;
                  }
                  BundleInfo source = byVersion.get(mdw.getBundleInfo().getVersion());
                  if (source == null) {
                      continue;
                  }
                  for (BundleArtifact artifact : source.getArtifacts()) {
                      mdw.getBundleInfo().addArtifact(artifact);
                  }
              }
          }
          sourceTargetBundles = null;
      }
  
      public void addArtifactUrl(String classifier, String id, Version version, URI uri, String format) {
          if (!classifier.equals("osgi.bundle")) {
              // we only support OSGi bundle, no Eclipse feature or anything else
              return;
          }
          ModuleDescriptorWrapper module = findModule(id, version);
          if (module != null) {
              addArtifact(module.getBundleInfo(), new BundleArtifact(false, uri, format));
              return;
          }
  
          // not found in the regular bundle. Let's look up in the source ones
          Map<Version, BundleInfo> byVersion = sourceBundles.get(id);
          if (byVersion == null) {
              return;
          }
          BundleInfo source = byVersion.get(version);
          if (source == null) {
              return;
          }
          addArtifact(source, new BundleArtifact(true, uri, format));
      }
  
      private void addArtifact(BundleInfo bundle, BundleArtifact artifact) {
          // find an existing artifact that might be a duplicate
          BundleArtifact same = null;
          for (BundleArtifact a : bundle.getArtifacts()) {
              if (a.isSource() == artifact.isSource()) {
                  same = a;
                  break;
              }
          }
  
          if (same != null) {
              // we have two artifacts for the same bundle, let's choose a "packed" one
              if (artifact.getFormat() == null || same.getFormat() != null) {
                  // the new one cannot be better
                  return;
              }
              bundle.removeArtifact(same);
          }
  
          bundle.addArtifact(artifact);
      }
  }
  